概要
数年前、本番で動く Python のモノリポで「raise は原則やめよう」と決めました。例外が前提の言語での逆張りと分かったうえで2年間貫いた結果を報告します。
raise の代わりに選んだのは、失敗を「直和型」で表すことです。社内では Result 型と呼びますが、Haskell の Either、値の不在を表す Optional/Maybe も仲間で、「結果は値かエラーのどちらか一方」を型で示す発想です。対して Go の (value, error) や例外は、両者を同時に返せる「直積型」です。
得たものは明確です。シグネチャだけで何で失敗するか分かり、try/except で例外を握りつぶす事故が減り、バグと業務エラーを型で分けたことで、直すべきものだけが通知に上がるようになりました。
一方で失ったものもあります。標準も外部もライブラリは例外を投げるので、コードは例外と直和型の境界で暮らしています。共通エラー型 AppError を作ってかえって苦しみ、transaction.atomic() が err でロールバックしない罠にもはまりました。原則は現場の都合で何度も書き換わりました。
バッチやデータ基盤なら握りつぶして再実行でも回りますが、オンラインの実運用アプリでは取りこぼしが事故になります。だからこそ型に乗せる価値が高い。効く場所と要る覚悟までお話しします。
このトークで話すこと
- なぜ raise をやめたのか / 直和型(Result・Either・Optional)とは
- 直和 vs 直積:例外・(value, error)・null と何が違うか
- 得たもの・失ったもの(握りつぶし減・バグと業務エラー分離 ⇔ 例外境界・共通エラー型・トランザクションの罠)
- まとめ:実運用アプリだからこそ効く理由と覚悟が要る場所
スピーカーについて
加藤雅也