Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
エラー処理の温故知新 / history of error handling technic
Search
nakaryo
May 01, 2026
Programming
2k
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
140
ギフティの技術ブログ 再出発とこれから / restart of giftee tech blog 2024
ryotanakaya
0
350
再利用パターン / Pattern of code reuse
ryotanakaya
0
200
エンジニアリングエッセイのススメ
ryotanakaya
0
510
ソフトウェアアーキテクチャについて 語るときに 僕の語ること
ryotanakaya
2
1.7k
エンジニアと要件定義
ryotanakaya
4
1.2k
Go と並行処理
ryotanakaya
0
410
ワクワク!Rubyクイズ!!
ryotanakaya
0
1.6k
増え続けるトランザクションデータと向き合う
ryotanakaya
0
550
Other Decks in Programming
See All in Programming
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
580
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
160
jQueryをバージョンアップする前に使いたいjQuery Migrate
matsuo_atsushi
0
490
Webフレームワークの ベンチマークについて
yusukebe
0
170
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
4k
代数的データ型って何が嬉しいの? #frontend_phpcon_do
kajitack
8
3.7k
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
230
スマートグラスで並列バイブコーディング
hyshu
0
140
Oxcを導入して開発体験が向上した話
yug1224
4
310
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
680
Oxlintのカスタムルールの現況
syumai
6
1.1k
不変条件と整合性境界—ビジネスが決める設計判断と実現パターン / Invariants and Consistency Boundaries
nrslib
13
4.4k
Featured
See All Featured
Designing for Timeless Needs
cassininazir
1
250
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.3k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.2k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.7k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
840
Building Applications with DynamoDB
mza
96
7.1k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.5k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.5k
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