日々、開発の仕事をしているときに悩まされる大きな問題はバグです。
開発途中でも、本番サービスイン後でも、バグには頭を抱えさせられます。
このコンテンツでは、実際にエンジニアがどのようにバグを調査し、バグを解消するかについて紹介します。
まず、このコンテンツでバグとは何を指しているかを定義します。
などなど、エラーのシチュエーションは枚挙にいとまがありません。
「バグを定義する」場合、とにかく**「動作が期待通りではない」状態**だと言えます。
上記のように、開発におけるバグは様々なパターンで発生しますが、自分がプログラミング初心者時代に個人開発をしていて遭遇したケースを紹介します。
top
コマンドを打つと、データベースのメモリ消費が100%を越えていた、なんてこともあります。スロークエリをEXPLAINで調査するところから始まります。これらはあくまで一部です。主に初心者や入門者のときは、プログラミングは問題なくとも、サーバーやデータベースといった、目に見えづらい管理対象でバグ発生するケースが頻繁にあります。
ある程度経験を積んで様々なケースへ対処できるようになっても、まだバグとの付き合いは切れません。以下に、経験年数を越えてもよく見かけるバグを紹介します。
state
などの管理に対し、シビアになる必要が出てきました。送るデータがおかしいときは保持しているデータの流れをしっかり管理しなくてはなりません。経験年数とともに、対応するバグの難易度が上がっていきますが、その分、ログ追跡するときは宝探しのような趣が出てきます。(できればそのような状況に陥りたくありませんが)
では実際に、ログを追跡し、バグを調査し、修正するまでの技術について紹介していきます。
大きく分けて、以下の3つの要素が大切です。
バグ対応の手順ではじめに重要な要素は、バグを再現できることです。
サービスにアクセスできない、などは簡単な再現の部類ですが、「特定条件下で発生する」タイプだと再現が厄介です。
発生を検知したエンドユーザーに聞き取りができると良いですが、それが困難な場合はUIテスト自動化ツールや手作業で発見していくことになります。
ログトレースは「どこで」「どういった」バグが発生したかを調べるため際に良い指標です。ただし、あらかじめコードやツール、ソフトウェアにログ出力するように実装していないと、調査時間が延びてしまいます。
普段の開発から、ロガーに関するコーディング規約を決めたり、利用するツールやソフトウェアのログ設定を確認しておくなりして、事前に備えておきましょう。
ログが出力されていれば、ログをベースに原因追跡を始められますが、ログだけで完結しなかった場合はコードを追っていく作業となります。
コードのつながりや、再現したときに表示されるエラーメッセージから原因を特定していきましょう。
ここまで完了したら「調査」の段階は終了となります。
修正作業では、デバッグが重要となります。どういった値がどういったタイミングで発生し、それがどのように渡されているかを逐次確認しながら修正していきます。
このとき、使っているプログラミング言語やフレームワークのデバッガーを熟知しているとスムーズでしょう。多くのプログラミング言語には、高品質なデバッガーが組み込みで存在していたり、ライブラリとして提供されていたりするため、積極的に利用していきましょう。
もし、バグを追跡・修正している中で複数のバグが発見された場合は、1つずつ対処することを強くお勧めします。
理由として、ソースコードのバージョン管理や、インフラのデプロイ履歴が追いやすくなるためです。
1つのバグを直しても、そこから更にバグが派生した場合は、その修正履歴を追うだけで済みます。しかし、複数のバグを一度に修正した場合は、複数の修正箇所を追うことになるからです。
理想的なのは、二度と同じ箇所でバグを発生させないことです。もちろん、そのときのバグの要因は種々雑多となりますが、コードであれば型安全を守ることや、インフラであれば設定のチェッカーを実行するなどできることはたくさんあります。
障害発生はできれば遭遇したくないものの、素晴らしい学びのタイミングです。
どこが悪かったかをしっかり分析し、その後のより良い実装や設計に活かしていきましょう。
修正が終わった段階で必ずチェックしてほしいのが、単体テストのテストケースです。
もし不正なデータによるバグだった場合、その不正なデータはテストケースに入れ込みましょう。
ユースケースとして役立つだけでなく、テストそのものの質を上げることで、ソフトウェアを高品質にする一助となります。すべてのテストケースを網羅することは、人間の脳みそだけでは追いつかないことも多々あるので、積極的に事例は拾っていきたいところです。
実際に修正が終わり、テストケースの追加をしても、本番デプロイには慎重になってください。リグレッションテストやデグレは当然のことですが、別口で実装されているコードの混入など、新たなバグを生むきっかけがデプロイに隠れている可能性があります。
もしレビュアーになれるエンジニアが不在であったり、個人開発のように一人で開発している場合は、GitHub ActionsのようなCI/CDツール上で可能な限り検査できるようにしておきましょう。
バグ修正を無事本番デプロイし、運用を再稼働し始めたら終わり、ではありません。
常時稼働アプリケーションや日次ワークフローが回っている場合だけでなく、新たなバグが生まれる可能性はゼロではありません。
可能な限り、継続的に注視できるような体制を整えましょう。監視ツールの導入や、ログベースの通知機能の強化などを検討してください。
あまり転職活動や商談で注目されないバグ対応能力ですが、これがあるだけで職場やプロジェクトで重宝されるスキルです。
ときどき、普段目立たないのにバグ調査のときに頼りがいがある、というエンジニアがいます。こういった縁の下の力持ち的なエンジニアは、上長や管理者から見たらありがたい存在です。
まずは、自分で書いたコードや設計を見直してみましょう。
「もしもバグが起きたら」を考慮したときに、足りない材料があればしっかり対応しておくことで、より高品質で安全なソフトウェア開発が可能となります。