CO-NECT株式会社の二階堂です。
前回はコロナの影響で働き方が大きく変わったため、リモートワークをテーマにした記事を書きましたが、今回は、先日業務の中でどういったエラーハンドリングが適切かを考える機会がありましたので、その内容をお伝えしたいと思います。
適切なエラーハンドリングの必要性
現在、私は弊社サービスのサーバーサイド開発をメインに担当しており、これ以前も複数の開発案件に参画していますが、エラーハンドリングの方針が明確に決まっている現場はほとんどありませんでした。というのも、開発スピードが優先される現場では正常系の処理開発に注力するため、エラーハンドリングは後回しにされる傾向があるからだと考えられます。
しかし、正しくエラーハンドリングされていないシステムは
- エラーの原因箇所を特定しにくい
→ リカバリに時間がかかる- ユーザへのエラー通知が適切に行われない
→ 何か別の操作をすればエラーが回避できるのか、またはシステム管理者のリカバリが必要なのかの判断ができない
といった問題があり、適切にエラーハンドリングを実装することが求められます。
エラーハンドリングの方針検討
開発は、複数のメンバーで行われることがほとんどですが、開発メンバーによってエラーハンドリングの考え方・方法が異なるため、予め明確なエラーハンドリングの方針を示す必要があります。そこで、どういった方針が良いのかを検討してみました。
まずエラーは、業務エラーとシステムエラーに大きく分類することができます。(参考1)
業務エラー | ユーザ入力値の問題で、処理が完遂できなかった |
システムエラー | システムトラブルで、処理が完遂できなかった |
業務エラーに関しては、ユーザの入力値の問題なので、一般的にエラー発生後は再入力を促すメッセージを表示してエラー処理は終了になります。
システムエラーに関しては、ユーザに適切なエラーメッセージを表示し、システム管理者はバグかインフラ起因かどうかを判断して対処する必要があり、エラー発生時はバグかどうかを判断するためにエラーログを出力することが必須となります。
では、システムエラーの発生を捕捉する方法に、try~catchがありますが、どの範囲で行うのが適切でしょうか。
try~catchは関数の中で使用しますが、関数は共通関数とメイン関数で大きく分けられます。弊社開発メンバー内でアンケートをとったところ、メイン関数にのみtry~catchをかければ良いのではないかという意見がありましたが、確かに、メイン関数から共通関数は呼ばれるのでメイン関数内でtry~catchをかけておけばシステムエラーは捕捉できます。
ですが、共通関数内でシステムエラーを捕捉しないことによるデメリットとして、以下の問題があると考えています。
- 共通関数内で業務エラーとシステムエラーの分類が漏れる
- 共通関数内で処理が完結しない(再利用がしにくい)
- システムエラー発生時の原因調査で欲しい情報をピンポイントでエラーログに出力しにくい
まとめ
これまで検討した内容をまとめると、エラーハンドリングの方針は以下の通りとなりました。
- システムエラー発生時のエラーログには、関数名/捕捉したエラーメッセージ/パラメータを出力すること
- 共通関数でもシステムエラーの捕捉を行うこと
- 共通関数のシステムエラー発生時の戻り値を、システムエラー発生時以外の値で定義すること(documentに戻り値の定義を記載すること)
もちろん、上記は運用していく中で状況に応じてブラッシュアップが必要になると思いますが、方針を示すことで開発メンバー間で認識を合わせることが出来るようになり、システム品質の向上につながると考えています。
おわりに
当社では、サービスを一緒に作ってくれる仲間を募集中です。興味のある方はお気軽にお問い合わせください。
参考URL
(参考1)
エラーチェックの体系的な分類方法
https://docs.microsoft.com/en-us/archive/blogs/nakama/293