Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
エラー処理の温故知新 / history of error handling technic
Search
nakaryo
May 01, 2026
Programming
2.3k
7
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
エラー処理の温故知新 / history of error handling technic
nakaryo
May 01, 2026
More Decks by nakaryo
See All by nakaryo
Ruby で gRPC を使おう / ruby-grpc
ryotanakaya
1
180
ギフティの技術ブログ 再出発とこれから / restart of giftee tech blog 2024
ryotanakaya
0
410
再利用パターン / Pattern of code reuse
ryotanakaya
0
230
エンジニアリングエッセイのススメ
ryotanakaya
0
560
ソフトウェアアーキテクチャについて 語るときに 僕の語ること
ryotanakaya
2
1.8k
エンジニアと要件定義
ryotanakaya
4
1.3k
Go と並行処理
ryotanakaya
0
450
ワクワク!Rubyクイズ!!
ryotanakaya
0
1.7k
増え続けるトランザクションデータと向き合う
ryotanakaya
0
570
Other Decks in Programming
See All in Programming
残高管理から台帳サービスへの進化
artoy
1
200
The Rails Doctrine Decade
koic
2
570
HTML-in-Canvasで作る未来のWeb UI表現
clockmaker
5
4.9k
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
120
sbt 2.0: takeoff
eed3si9n
0
150
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
22
22k
Verilogで学ぶCPU自作入門
uyuki234
8
4.1k
Compiling a real-world CLI tool to native with Static Hermes
tmikov2023
0
110
最近”作らせてる” ローカルAIアプリの話
akit37
0
460
ChromeでローカルLLM
ryu1013
0
130
AWSに止められる覚悟してますか?
morizo_1984
2
530
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
Featured
See All Featured
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
750
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
500
Balancing Empowerment & Direction
lara
6
1.3k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
What does AI have to do with Human Rights?
axbom
PRO
1
2.4k
Rails Girls Zürich Keynote
gr2m
96
14k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
730
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
540
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
470
AI Search: Where Are We & What Can We Do About It?
aleyda
0
8.1k
sira's awesome portfolio website redesign presentation
elsirapls
0
450
Transcript
エラー処理の温故知新 エラー処理の温故知新 エラー処理の温故知新 エラー処理の温故知新 Nakaya Ryota 2026.05.01 giftee TechBash 1
自己紹介 なかりょー @ 株式会社ギフティ バックエンドエンジニア ▸ 前職はバックオフィス ERP ベンダーで上流メイン ▸
Go / Ruby / Java ▸ AI に翻弄される今日この頃 ▸ 2
みなさん、エラー処理やってますか? 3
プログラムは必ず失敗する 人間と同じで、プログラムも必ず失敗する ▸ ファイルがない ▫ ネットワークが落ちる ▫ 入力値が不正 ▫ NULL
ポインター ▫ 型が食い違う ▫ etc... ▫ 様々な理由でエラーは発生する ▸ 4
そもそもエラーとは何か エラーとは、プログラムの期待と現実のギャップである ▸ 「このファイルは存在するはず」 → なかった ▫ 「この値は正の整数のはず」 → 負の値だった
▫ 「このサーバーは応答するはず」 → タイムアウトした ▫ つまり、プログラムが置いた前提や仮定が崩れた瞬間がエラー ▸ 前提は必ずどこかで崩れる — だからエラー処理が必要になる ▸ 5
ドメインエラー vs 非ドメインエラー ドメインエラー 非ドメインエラー 入力値が不正 ▸ 実行の前提条件が満たされていない ▸ 認証・認可の失敗
▸ etc ▸ メモリ不足(OOM ) ▸ ネットワーク障害 ▸ NULL ポインター参照 ▸ etc ▸ 6
エラーハンドリング、どう書いていますか? 各言語がどんな答えを出してきたのか、歴史を振り返りながら考えてみましょう プログラムを書くとは、エラーハンドリングを書くことでもある ▸ 皆さんはエラーハンドリングをどのように書いていますか? どのようなことを意識していますか? ▸ Ruby だと Exception
を使うのが常識になっていますよね? ▸ Exception を体系的に設計できていますか? ▫ 7
C 言語の時代 8
C 言語の時代 — エラーは値だった if (open(...) < 0) { perror("open");
} C 言語と Unix 哲学の世界 ▸ エラーというのは値だった → プログラムのロジックで処理するもの ▸ 関数やプログラムは成功・失敗を数値で表現する ▸ 0 なら正常、0 以外なら異常 ▫ ✔ シンプル ▸ ✘ 戻り値をチェックし忘れるリスクがある ▸ ✘ 正常系と異常系が混ざる ▸ 9
Exception の時代 10
Exception の時代 try { readFile(); } catch (IOException e) {
... } C++ 、Java 、Python 、Ruby など現代主流の言語に見られる ▸ 例外機構自体はもっと以前からあったが、90 年代の言語が普及に寄与 ▫ ✔ 正常系と異常系のフローを分けて書ける ▸ ✔ 大域脱出するため、チェック漏れのリスクがない ▸ 11
Exception の課題 どこでどういう例外が発生するのかを把握するのが難しい ▸ 関数定義をパッと見ただけではわからない ▫ プログラム全体を見ないと、どこで何がハンドリングされているのかわからない ▫ → 設計難易度が高い
▫ 結果、別の形のリスクが生まれる ▸ スローされたまま誰もキャッチしない ▫ 意図せず握りつぶされる ▫ 12
Java の検査例外 void foo() { bar(); // HogeException をキャッチするかスローしないとコンパイルエラー }
void bar() throws HogeException { ... } ✘ コンパイルエラー — foo() は HogeException を処理していない 関数がどういう例外をスローしうるかをシグネチャで表現する ▸ 13
Java の検査例外 — 正しい記述 A. キャッチして処理する void foo() { try
{ bar(); } catch (HogeException e) { // ここで回復処理 } } B. スローを伝播する void foo() throws HogeException { bar(); // 呼び出し元に責任を委譲 } どちらかを選ばないとコンパイルが通らない → 処理漏れを防ぐ ▸ 14
検査例外のトレードオフ 伝播コストがかかる ▸ 全員がキャッチ・スローを書いて伝播させなければならない ▫ ラップしてリスローするコードが至るところに生まれる ▫ API 変更に弱い ▸
例外の種類を増やすと、呼び出し側全員がキャッチを書く必要がある ▫ 高階関数やラムダ式、関数型記法との相性が悪い ▫ 失敗可能性を明示することと、失敗から回復できることは別問題だった ▸ 15
現代の別解:Go のエラーハンドリング 16
技術の進化は螺旋 f, err := os.Open("file.txt") if err != nil {
return err } 2009 年に生まれた Go は、エラーを値として返すという 古典的な方法をあえて選んだ ▸ 17
Go の思想 "Errors are values (エラーは値である)" — Rob Pike go.dev/blog/errors-are-values
- Why does Go not have exceptions? — Go FAQ - 「例外」がないからGo 言語はイケてないとかって言ってるヤツが本当にイケてない件 例外は使わない(panic はあるけど、回復不能な異常時のみ) ▸ エラーは「摩訶不思議なもの」でも「例外的なもの」でもない ▸ ファイルがない・入力値がおかしいのは日常的な事象 ▫ だから特別な制御構造(例外)ではなく、通常の値として扱うべき ▫ 常にその場で処理するか、呼び出し元に返す ▸ 「魔法を減らせ」 ▸ 18
なぜ値リターンに戻ったのか Exception はシグネチャに現れず、どこで何が飛ぶかわからない ▸ デバッグが難しい — throw 元と catch 先が離れがち
▸ "Cleaner, more elegant, and wrong" — Raymond Chen ▫ 制御フローが追いにくい — 暗黙の大域脱出が隠れている ▸ ドメインエラーと非ドメインエラーの使い分け ▸ ドメインエラー:予期される事象 → 制御構造(ロジック)で扱う ▫ 非ドメインエラー(OOM, NPE ) :制御できない → 大域脱出 ▫ 異なる性質の事象なので、対処方法を明示的に使い分ける ▫ そもそも goto 文はマジカルでよくないと教わったのに、 例外だけ例外的に扱うのどうなん? ▸ 19
オフトピック:Clean Code の見解 『Clean Code 』の中でボブおじは、 値リターンはコードの可読性を下げるからお勧めしないと書いている ▸ 正常系がストレートに読める方がコードの意図が掴みやすい ▸
ただし、イディオムの違いによる可読性は宗教論争になりがちで、 これもご多分に漏れない ▸ 20
エラーを型で扱う時代 21
エラーを型で扱う fn read_file() -> Result<String, Error> Rust 、Haskell 、Scala 、Swift
、Kotlin など ▸ 成功すれば String が、失敗すれば Error が返る。それ以外はありえない ▸ 失敗する可能性が型に現れる ▸ 値(データ)ではなく型(プログラムの構造)として表現 ▫ 値はハンドリングしなくても良いが、型はハンドリングを強制する ▫ 22
値として扱う vs 型として扱う Go — 値は無視できる f, err := os.Open("file.txt")
// err を無視しても // コンパイルは通る doSomething(f) Rust — 型は強制する let result = read_file(); // Result を開かないと // 中身を使えない do_something(result); // 型エラー 値はチェックするもしないも開発者の自己責任 ▸ 型はコンパイラが処理を強制する — うっかり無視できない ▸ 23
Result 型のハンドリング match read_file() { Ok(content) => println!("{}", content), Err(e)
=> eprintln!("Error: {}", e), } match で全パターンを網羅しないとコンパイルエラー ▸ Ok だけ書いて Err を省略 → コンパイルエラー ▸ 「処理し忘れ」がそもそも起こりえない構造になっている ▸ ただし、意図的に捨てることは可能( let _ = read_file(); ) ▸ Java の検査例外と違い、どの階層で処理するかは開発者が自由に選べる ▸ 24
型によるエラー表現の特徴 うっかり無視はできないが、意図的に捨てることはできる ▸ Java の検査例外:各階層に「処理 or 宣言」を強制 ▫ Rust の
Result :失敗の可能性を示すが、どこで処理するかは自由 ▫ ✔ コンパイラが処理漏れを検出できる — 例外より明示的 ▸ ✔ エラーを合成でき、関数型とも相性が良い ▸ ✘ 記述量は増えることもある ▸ 25
まとめ エラー処理に銀の弾丸はない — だからこそ面白い エラー処理の仕組みと思想は言語ごとに異なる ▸ 最近の言語トレンドはエラーを型で表現する方向へ ▸ それぞれの特性を理解して、正しく向き合おう ▸
26