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

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

Avatar for morihirok morihirok
January 17, 2025

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

Avatar for morihirok

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 か? • 「例外を丸ごとハンドリングしない」という機械的な制約 をつけることで増殖を防ぎ、改善を進められた