エラー処理をレビューする
握りつぶされた例外と、原因を追えないエラーを見つける
次のコードのエラー処理をレビューしてください。失敗経路だけに注目します:1)握りつぶされた例外、既定値に落とされている例外はどれか。障害が起きたとき静かに失敗しないか;2)エラーメッセージだけで原因を特定できるか(重要なid、入力値、上流の状態が含まれているか);3)安全でないリトライはどれか(非冪等で、二重課金や二重書き込みになる);4)失敗すべきなのに動き続けている箇所、続けるべきなのに全体を止めている箇所はどこか;5)修正後の主要な断片を示す。 ``` [コードを貼り付けてください] ```
使い方
指摘された「静かな失敗」を最優先で見ましょう。リリース後に最も見つけにくく、最も追跡しにくいバグです。
向いている場面
- 本番で「エラーは出ていないのにデータが違う」状態になり、ログが空のとき。
- 決済、返金、メッセージキューを組み込むとき。失敗経路のコストが正常経路よりはるかに大きい場面です。
向いていない場面
- 一度きりのスクリプトや CLI なら、例外を握りつぶして続行するのは妥当です。サービスの基準でレビューしません。
- 問題がリトライ設計全体(キュー、デッドレター、バックオフ)にあるなら、個々の try/catch ではなくアーキテクチャを見ます。
例
入力
def charge(order_id, amount):
try:
resp = payment.charge(order_id, amount)
db.update(order_id, status="paid")
return True
except Exception:
return False得られるもの
`except Exception` がすべての例外を握りつぶし、ログも出していないため原因を追えない点を指摘します。payment は成功したのに db.update が失敗すると、冪等キーもトランザクション境界もないため二重課金になります。bool を返す設計では「残高不足」と「ネットワークタイムアウト」を呼び出し側が区別できません。修正は order_id、amount、上流のエラーコードを記録し、冪等キーを使い、確定前にローカル状態を書くことです。
よくある誤用
- 「ログを足して」とだけ頼み、「失敗すべき」と「リトライすべき」を分けないと、ログは増えても意味は誤ったままです。
- 貼ったコードで例外がすでに `str(e)` で文字列化されていると、エラーの型が見えず、一般的な助言しか返りません。
こう変えると効く
- 「ユーザーが損をする、エラーを見る、統計が 1 件減るだけ、の 3 段階で優先度を付けて」と加えると、そのままスケジュールに落とせます。
- 「各失敗に対応するユーザー向けの文言を出して」と頼むと、静かな失敗の具体例が出てきます。