Upgrade to Pro — share decks privately, control downloads, hide ads and more …

混沌とした例外処理とエラー監視に秩序をもたらす

morihirok
January 17, 2025

 混沌とした例外処理とエラー監視に秩序をもたらす

morihirok

January 17, 2025
Tweet

More Decks by morihirok

Other Decks in Programming

Transcript

  1. どのように考えていくか 1. 利用者からの入力は基本的に Expected として扱う 2. コンテキストから Accept か Un

    Accept か決めていく 3. 例外をまるごとハンドリングしない 4. それは本当に Expected か?
  2. 2.コンテキストから Accept か Un Accept か決めていく • Ruby の JSON.parse

    • JavaScript の JSON.parse JSON文法(RFC 8259)に 準拠しないテキストは Un Accept としている
  3. Webにおける Accept と Un Accept • Expected / Accepted:2XX •

    Expected / Un Accept:4XX, 5XX ◦ Expected だが 5XX を返すケースはありうるだろう • Un Expected:5XX
  4. JSONかどうか判定してくれる Web アプリケーション • Web サーバはあらゆる入力を Expected なものと扱う • JSON.parse

    が Un Accept しても Web サーバの振る舞 いはそれに引きずられない • コードを書くプログラマがコンテキストを踏まえて都度判 断する
  5. Accept と Un Accept どちらにしよう • Expected / Accepted:2XX •

    Expected / Un Accept:4XX, 5XX ◦ Expected だが 5XX を返すケースはありうるだろう • Un Expected:5XX
  6. Accept と Un Accept どちらにしよう • Expected / Accepted:2XX •

    Expected / Un Accept:4XX, 5XX ◦ Expected だが 5XX を返すケースはありうるだろう • Un Expected:5XX どちらもありえそう!
  7. (再掲)どのように考えていくか 1. 利用者からの入力は基本的に Expected として扱う 2. コンテキストから Accept か Un

    Accept か決めていく 3. 例外をまるごとハンドリングしない 4. それは本当に Expected か?
  8. (再掲)どのように考えていくか 1. 利用者からの入力は基本的に Expected として扱う 2. コンテキストから Accept か Un

    Accept か決めていく 3. 例外をまるごとハンドリングしない 4. それは本当に Expected か?
  9. (再掲)どのように考えていくか 1. 利用者からの入力は基本的に Expected として扱う 2. コンテキストから Accept か Un

    Accept か決めていく 3. 例外をまるごとハンドリングしない 4. それは本当に Expected か? プログラマが 判断するしかない
  10. (再掲)どのように考えていくか 1. 利用者からの入力は基本的に Expected として扱う 2. コンテキストから Accept か Un

    Accept か決めていく 3. 例外をまるごとハンドリングしない 4. それは本当に Expected か? 機械的に 判断できる
  11. Custom Cop を活用し課題を攻める • StandardError を握りつぶせない Custom Cop # bad

    begin some_method rescue => e handle_error end # bad begin some_method rescue StandardError => e handle_error end # good begin some_method rescue => e handle_error raise e end # good begin some_method rescue JSON::ParserError => e handle_error end
  12. こうしないといけない def show result = begin ResponseGenerator.call(params) rescue => e

    Sentry.capture_exception(e) raise e end render json: result end
  13. こうしないといけない def show result = begin ResponseGenerator.call(params) rescue => e

    Sentry.capture_exception(e) raise e end render json: result end これいらないな...?
  14. 過激な Custom Cop が爆誕 def show result = begin ResponseGenerator.call(params)

    rescue => e Sentry.capture_exception(e) raise e end render json: result end RuboCop 違反となる
  15. とはいえいろんなケースがある def show result = begin ResponseGenerator.call(params) rescue ResponseGenerator::SomeError return

    render status: :bad_request end render json: result end 発生自体は 知りたいケースがある
  16. 用途に応じて書き込み先を変える def show result = begin ResponseGenerator.call(params) rescue => e

    logger = Logger.new('hoge.log') logger.error(e) end render json: result end 謎ログを やめられる
  17. まとめ • 例外を整理した ◦ 利用者からの入力は基本的に Expected として扱う ◦ コンテキストから Accept

    か Un Accept か決めていく ◦ 例外をまるごとハンドリングしない ◦ それは本当に Expected か? • 「例外を丸ごとハンドリングしない」という機械的な制約 をつけることで増殖を防ぎ、改善を進められた