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.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
170
ギフティの技術ブログ 再出発とこれから / restart of giftee tech blog 2024
ryotanakaya
0
400
再利用パターン / Pattern of code reuse
ryotanakaya
0
220
エンジニアリングエッセイのススメ
ryotanakaya
0
550
ソフトウェアアーキテクチャについて 語るときに 僕の語ること
ryotanakaya
2
1.8k
エンジニアと要件定義
ryotanakaya
4
1.3k
Go と並行処理
ryotanakaya
0
440
ワクワク!Rubyクイズ!!
ryotanakaya
0
1.7k
増え続けるトランザクションデータと向き合う
ryotanakaya
0
560
Other Decks in Programming
See All in Programming
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
660
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
190
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
510
Intent as Code
shoppingjaws
6
1.1k
難しいけど、読めた。- OSSの入口に立った話。
sts11142
0
120
LoopHub - ローカルで動く GitHub で、AI と共同開発
jugyo
1
570
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
540
個人開発基盤をまるごとCloudflareに引っ越して爆速で総合的体験を向上させた話
tinykitten
0
200
アクセシビリティから考える情報設計
high_g_engineer
0
400
海上で動くGoサーバー: goroutineとchannelでさばく航行データストリーム
atsuki_seo
0
920
WebRTC映像をAirPlayに対応させる挑戦.pdf
monolithic_adam
0
300
テストを司るデーモンに会いに行く 〜隔離した仮想マシンでテストを通すまで〜
h1d3mun3
1
570
Featured
See All Featured
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
710
The Cost Of JavaScript in 2023
addyosmani
55
10k
Unsuck your backbone
ammeep
672
58k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
610
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
600
Navigating Weather and Climate Data
rabernat
0
530
Become a Pro
speakerdeck
PRO
31
6.3k
The World Runs on Bad Software
bkeepers
PRO
72
12k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
Practical Orchestrator
shlominoach
192
12k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
710
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
390
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