効率を上げて最速でバグを潰す方法
プロダクトにバグが発生して帰れなくなったり、深夜なのに対応したりの経験はありますか?
私には数え切れないほどあります。
私には数え切れないほどあります。
バグ対応は精神的にダメージがありますし、必要な工数が読めないためにスケジュールへの影響も予想しづらいので、極力避けたいですよね。
とはいえバグや不具合が発生してしまうのは、ある程度は避けられないので、発生した際にどうやって解決すればいいかの考え方や取り組み方をお伝えします。
バグ対応は経験を積むほど効率が上がり、初心者とベテランでもっとも差がつく領域の一つです。
「あまりバグ対応の経験がないな、、」という方がこの記事を読んで効率的にバグを潰せるようになり、終電に乗り遅れることが少なくなれば、これほど嬉しいことはありません。
「あまりバグ対応の経験がないな、、」という方がこの記事を読んで効率的にバグを潰せるようになり、終電に乗り遅れることが少なくなれば、これほど嬉しいことはありません。
以下の流れに沿って、やるべき対応を1つずつ説明していきます。
着手する前に
バグが見つかると「すぐに対応しないと..!」と焦ってしまいがちですが、まずは立ち止まり「この問題は本当に解くべきなのか」を考えてください。
解くべきバグなのか見極める
出てくる問題すべてに対応するのは現実的ではありません。
リソースに制限がある中では、どの問題に取り組むかが非常に重要でしょう。
リソースに制限がある中では、どの問題に取り組むかが非常に重要でしょう。
その際の判断軸は影響の大きさ、シェア、頻度、予想工数などです。
- 影響の大きさ
- プロダクトのメイン機能が使えなくなるなのか、それとも少し表示が崩れる程度なのか
- シェア
- 不具合が発生するOSやブラウザのシェアはどれぐらいか
- 頻度
- 一般的な使い方で発生するのか、珍しい使い方でのみ発生するのか
- 予想工数
- (この時点では判断が難しいですが)どれぐらいの工数をかければ解決ができそうか
場合によっては仕様変更も検討するべきでしょう。
「想定していた仕様と違うけど、これでも問題はないね」となれば、対応する必要はないわけです。
仕様を絶対視するのではなく柔軟に検討して、対応するバグを減らしていきましょう。
「想定していた仕様と違うけど、これでも問題はないね」となれば、対応する必要はないわけです。
仕様を絶対視するのではなく柔軟に検討して、対応するバグを減らしていきましょう。
バグを再現する
バグに対応優先度を付けて、取捨選択が出来たところで、バグの再現に移ります。
バグ潰しにおいては再現が非常に大事で、再現さえできれば半分ぐらいは解決できたと言っても過言ではありません。
バグ潰しにおいては再現が非常に大事で、再現さえできれば半分ぐらいは解決できたと言っても過言ではありません。
情報を細かくヒアリングする
自分の手元で発生したバグではない場合、どのような環境や状況で発生したのかをヒアリングする必要があります。
状況によってヒアリング項目は変わりますが、例えば以下の情報を聞くべきでしょう。
- OS(バージョン含む)
- 例:iOS13.1
- ブラウザ(バージョン含む)
- 例:Chrome88.0.4324.150
- アプリのバージョン
- アプリの設定画面などから確認できるようにしておきましょう
- 端末
- 例:iPhoneX Plus
- 発生した事象
- できるだけ具体的に聞きましょう
- 再現方法
- 何をすると発生するか
- 発生日時、発生頻度
- そのタイミングでのみ起きていた不具合なのか、継続的に起きている不具合なのかを確認するために必要な情報です
- 画面キャプチャー
- 動画でもらえるとなお良い
- エラーログ
- ウェブの場合はconsoleに出ているエラーなどをもらえるとスムーズです。
同僚や家族であればヒアリングは難しくないですが、ユーザーからの報告の場合は追加ヒアリングは簡単ではありません。
そのため、報告フォームに上記の項目を入力できるようにしておき、最初の報告の時点で出来るだけ情報をもらっておく、などの工夫が必要になります。
そのため、報告フォームに上記の項目を入力できるようにしておき、最初の報告の時点で出来るだけ情報をもらっておく、などの工夫が必要になります。
環境を再現するには
必要な情報が集まったら、実際にその現象が発生するか(再現できるか)を試していきます。
しかし特定の端末やブラウザのバージョンでしか発生しない場合はどうすればいいのでしょうか?
可能であればその環境と同じ実機を用意するのがベストですが、バグが発生する度に端末を準備するのは現実的ではありませんよね。
可能であればその環境と同じ実機を用意するのがベストですが、バグが発生する度に端末を準備するのは現実的ではありませんよね。
そんな時に使えるのがエミュレーションや仮想環境です。
例えばGoogleChromeの検証モードでは、各種デバイスの画面サイズやユーザーエージェントのエミュレーションができます。
また、More Tools → Network conditions → User agent からブラウザの細かい指定も可能です(残念ながらIEのレンダリングバグなどはほぼ再現できませんが、IE向けの処理出しわけがうまくいっているかなどは確認できます)
また、More Tools → Network conditions → User agent からブラウザの細かい指定も可能です(残念ながらIEのレンダリングバグなどはほぼ再現できませんが、IE向けの処理出しわけがうまくいっているかなどは確認できます)
仮想環境を使うのも有効です。
自分は、違うOSをローカルに仮想的に再現できるParallesや、クラウド上の仮想環境で各種OSやブラウザの挙動を検証できるBrowserStackなどのツールを活用しています。
自分は、違うOSをローカルに仮想的に再現できるParallesや、クラウド上の仮想環境で各種OSやブラウザの挙動を検証できるBrowserStackなどのツールを活用しています。
バグを再現できない場合
バグを再現できなかった場合はどうすればいいのでしょう?
自分の検証環境や手順に違いやミスがある可能性もあるので、同僚や家族に試してもらうのも良いでしょう。
自分の検証環境や手順に違いやミスがある可能性もあるので、同僚や家族に試してもらうのも良いでしょう。
それでも再現できない時の選択肢は以下の通りです。
- 再現できるまでさらに試す
- 再現できないままでコード内を調査する
- 諦める
バグの重大度に応じて取るべき選択肢は変わりますが、時には諦める勇気も重要でしょう。
問題を整理し共有する
再現が出来たところですぐに調査に入りたくなりますが、ここでも一度立ち止まりましょう。
バグ対応は計画を立ててから取り組まないと間違った方向に進んでしまいがちな領域です。
それを避けるために、改めての情報整理をオススメします。
それを避けるために、改めての情報整理をオススメします。
- 分かっている事実
- 分かっていないこと
- バグの原因として怪しいところ
- どこからどうやって調査していくと良さそうか
これらの情報を整理すると、「先週から起きているようだから、あのリリースが怪しいな。リリース前後の差分を確認するか」といったアクションを効率的に実施できるようになります。
また整理する過程で、「そうか、あそこのロジックが間違っているんだ!」と閃くことも多いでしょう。
情報を整理すれば、同僚に相談したり、ネットの技術系QAサイトに投稿したりも容易になります。
問題の原因を特定する
エラーメッセージを調べる
幸運にもどこかにエラーメッセージが出ている場合は、その内容の精査が最も重要です。
英語に躊躇してしまいがちですが、多くのケースではわかりやすい指摘なので、頑張って解読してみてください。
エラーメッセージで検索すれば同じ課題で苦労している人や解決策が見つかることも多いでしょう。
発生している事象で検索する
「IE11 flex 突き抜ける」「JS offset ズレる」など具体的な発生事象で検索すると、情報が得られることもあります。
特定の技術に関する問題であれば、そのコミュニティのサイト内で検索することも有効です。
同じことで困っている人や、すでに報告されているバグレポートを見つけることができるかもしれません。
例:Chromiumのバグ報告一覧
同じことで困っている人や、すでに報告されているバグレポートを見つけることができるかもしれません。
例:Chromiumのバグ報告一覧
うまくいっているものと比較する
「以前は問題なく動いていた」、「同じような挙動の競合サイトはうまくいっている」といった成功サンプルがある場合はそれとの比較が効率的です。
Gitで前後比較をしたり、エディタの差分比較機能を使ったりして、成功例とバグが起きている例の違いを特定しましょう。
要素を切り分ける
「このJSを読み込むとなぜかバグが発生する」ぐらいの曖昧なレベルだと対応策の検討は困難です。
「このJSのn行目のこの処理があるとバグが発生する」ぐらいの具体的なレベルまで原因を特定していく必要があります。
「このJSのn行目のこの処理があるとバグが発生する」ぐらいの具体的なレベルまで原因を特定していく必要があります。
そのために、怪しい要素を切り分けていきましょう。
シンプルな手法としては、怪しいところを片っ端からコメントアウトや削除していくアプローチがおすすめです。
バグが発生しなくなったタイミングで削減していた処理や記述が犯人です。
バグが発生しなくなったタイミングで削減していた処理や記述が犯人です。
問題を解決する
原因の詳細が分かってきたので、ついに解決に向けてどうすれば良いかを考えていきます。
解決するより回避する
一番オススメの手法は「解決するのではなく回避する」です。
解決するためには調査や分析が必要になりますが、回避であれば工数をかなり削減して実現できるケースも多くあります。
一例を挙げてみます。
- このパッケージを使っているとエラーが出る...
- 同じような機能を実現できる別のパッケージに変えよう
- 要素をCSSのflexで並べるとIEで崩れるな...
- inline-blockで並べるようにしよう
- 非同期で処理を実行するとネットワーク速度次第でバグが発生するな...
- 同期処理にしよう
実現したいロジックや表現と大きく差異がないのであれば、回避は非常に有効な解決策になることも。
試したことはテキストに残す
長時間同じバグの対応をしていると、気づかないうちに同じことを試してしまいがちです(自分だけだったらすみません)
そのような事態を避けるため、試したことを整理しておくのが非常に有効です。
同じことを試して時間を無駄にしなくて済みますし、まだ試していないことを炙り出すためにも使えます。
問題から離れてみる
いろいろ試したけれど問題が解決しないときは、一度その問題から離れてみるのもおすすめです。
ずっと同じ問題に取り組んでいるとどうしても視野も発想も狭くなり、俯瞰的な視点や大局的な視点を失っていきます。
そんな時は、別の仕事をしてみる、散歩する、昼寝するなどで、突然解決策を思いつくかもしれません。
自分の場合は、煮詰まった際の休憩でトイレまで行く途中で解決策を思いつき、トイレに行かずに作業に戻った、なんて経験が何度かあります。
問題を解決できた後は
さまざまな調査や工夫を経て問題の解決ができました!
しかし、「解決できたね。めでたしめでたし」で終わっては勿体ないので、次の問題に備えて以下のような取り組みを検討しましょう。
同じ問題が発生しそうなところに対応しておく
コードの一部にバグの存在が判明した場合、同じような書き方をしているところでも問題が発生する可能性があります(すでに発生している可能性も)
忘れないうちに、怪しい場所を洗い出して対応すると、未来への負債を減らせます。
問題と解決策をアーカイブしておく
今回発生した問題は、今後もあなた自身や同僚が出くわすかもしれません。
そんな時に備えて問題の概要とどう解決するかを記録しておきましょう。
メモは10分で済みますが、解決策を忘れて同じ問題に遭遇したら何時間と取られてしまう恐れがあります。
テスト項目やプルリクのテンプレートを修正する
必要に応じて、テストでチェックする項目や、プルリクエストのテンプレートの内容の修正も検討するのが良いでしょう。
同じようなバグを発生させるリスクを減らせますし、どんなリスクがあるのかを他の人にも認識してもらうために役立ちます。
まとめ:バグ潰し全体の流れ
ここまで紹介してきたバグ潰し全体の流れは以下の通りです。
全体を通して言えるのは、俯瞰して物事を捉えることの重要性でしょうか。
立ち止まって客観的にそのバグを見ることで、効率を上げてバグを潰すことができると思います。
立ち止まって客観的にそのバグを見ることで、効率を上げてバグを潰すことができると思います。
バグに遭遇してしまった時は、このフローをぜひ思い出してみてください!