バグが減らない本当の原因 — 症状から根本原因を切り分ける技術診断フレームワーク
バグ報告が増えたとき、多くのチームは「テストを書こう」「コードレビューを強化しよう」という打ち手に飛びつきます。しかし、根本原因が「要求の曖昧さ」にある場合、テストをどれだけ追加しても「期待通りに動いているがユーザーの期待とは違う」バグは減りません。
症状に対して打ち手を選ぶことは、診断なしに薬を処方するのと同じです。本稿では、バグが減らない根本原因を5分類で整理し、どの症状がどの原因を示すかを診断フレームワークとして提示します。CTO不在のスタートアップ経営者・PM・エンジニアが自己診断で使えることを意識しています。
「バグが多い」は症状であって原因ではない
「バグが多い」という言葉は、複数の全く異なる問題を一括りにしています。
- 修正したバグが数週間後に再発する → テストがないから
- 直したら別の箇所が壊れる → 設計が密結合しすぎているから
- 「そんな仕様ではなかった」とユーザーから言われる → 要求定義が曖昧だったから
- リリースのたびに新しいバグが出続ける → レビュー・QAが機能していないから
- 特定の担当者が触ったコードにバグが集中する → 知識が属人化しているから
これら5つは、見かけ上は同じ「バグが多い」という症状ですが、原因も打ち手も全く異なります。「バグが多いからテストを書く」という対処は、最初の1つにしか効きません。残りの4つには別の対応が必要です。
また実際の開発現場では、複数の原因が重なっているケースが多いです。その場合は重篤度の高い原因から優先的に手をつけることが、限られたリソースの中での正しいアプローチです。
根本原因の5分類
① テスト不足
自動テストがない、または重要なコードをカバーするテストがない状態です。テストがない環境では、修正が別の箇所を壊したことに気づけないまま本番にリリースされます。
典型的な兆候は、「修正したはずのバグが数週間後に同じ症状で再発する」「機能Aを直したら機能Bが壊れた、という連鎖が頻繁に起きる」です。
テストがない状態では、変更に対する恐れ(チェンジフォビア)が開発チームに広がります。「触ったら壊れるから触らない」という判断が積み重なると、コードは劣化し続けます。スタートアップでは特に、初期フェーズで速度を優先した結果テストが後回しになり、この状態に陥りやすいです。
② 設計起因
コードの設計が密結合・複雑になりすぎている状態です。「機能Aを修正するとなぜか機能Bが壊れる」という状況は設計起因のバグのシグナルです。
具体的には、異なる機能が同じデータベーステーブルを直接書き換えている、関数が100行を超えていて「何をしているか」が一見では分からない、特定のモジュールだけ修正コストが高い——こういった状態です。
設計起因のバグは、テストを追加しても「直したら別が壊れる」問題が解消しないことが多いです。根本的には設計の見直し(リファクタリング)が必要ですが、一度に全部を直そうとするのではなく、バグが集中する箇所から局所的に着手するのが現実的です。技術戦略として「どこを優先的に改善するか」を判断することが重要になります。
③ プロセス起因
コードレビュー・テスト実行・本番リリース前のQAという開発プロセスが整備されていない状態です。
「レビューなしにコードがマージされる」「本番リリース前の確認が担当者の手動チェックのみ」という状態では、同種のバグが繰り返し発生します。なぜなら、バグを事前に検知する仕組みが存在しないからです。
特徴的な症状は、「ある担当者のコードは問題ないが、別の担当者のコードはバグが多い」という差が生まれることです。これはスキルの差ではなく、プロセスの不在によって生まれる差である場合が多いです。CTO不在のチームでは、組織構築の一部としてこのプロセス整備が後回しになりがちです。
④ 属人化
特定の担当者だけが理解しているコードが多く、その担当者が不在または退職すると対応できなくなる状態です。
スタートアップでは、初期メンバーが設計の背景を頭の中だけに持っていることがよくあります。このコードはなぜこう動いているのか、どのトレードオフを取ってこう書いたのか——その文脈が引き継がれないまま、後から加わったメンバーが「なんとなく」修正を続けると、バグの発生確率が上がります。
「その担当者がいない間は修正できない」「誰かが触ると必ずバグが出る」という状態が属人化のシグナルです。これは技術負債の一形態であり、組織の成長とともに深刻化します。
⑤ 要求の曖昧さ
実装は仕様通りに動いているが、ユーザーや依頼者の期待と合っていない状態です。技術的にはバグではないが、「バグだ」と認識されます。
「サービスへのログインができないと報告があったが、実装では正しくログインできている」「ユーザーが期待した処理と、実装した処理が違った」——こういった報告が多い場合、問題は実装の品質ではなく、要求の定義フェーズにあります。
テストを追加しても、「何を正しい動作とするか」の定義が曖昧なままでは意味がありません。受け入れ基準(アクセプタンス・クライテリア)を実装前に定義する習慣が根本的な解決につながります。
切り分けの決定木:どの兆候がどの原因を示すか
以下の質問に順番に答えることで、最も可能性の高い根本原因を絞り込めます。
この決定木は「最も可能性が高い原因」を絞り込むためのものです。実際には複数の「はい」に当てはまる場合も多く、その場合はすべての原因を把握した上で優先度を判断してください。
原因別の打ち手と優先順位
根本原因が特定できたら、対応の優先順位を決める必要があります。以下の基準で判断します。
| 根本原因 | 影響範囲 | 対応難易度 | 最初の一手 |
|---|---|---|---|
| ① テスト不足 | 全体 | 中 | 決済・認証・コアロジックにテストを追加 |
| ② 設計起因 | 部分〜全体 | 高 | バグが集中するモジュールの複雑度を計測し、局所的にリファクタ |
| ③ プロセス起因 | 全体 | 低〜中 | コードレビューのルール化とCIの導入 |
| ④ 属人化 | 部分 | 中 | バグの多い担当者のコードにペアプロとドキュメント化を適用 |
| ⑤ 要求の曖昧さ | 全体 | 低 | 要求定義時に受け入れ基準を書く習慣をつくる |
CTO不在のチームでは、プロセス起因(③)から着手するのがコストパフォーマンスが高いケースが多いです。コードレビューとCI導入は、技術的なスキルがそれほど高くなくても整備できる上に、テスト不足・属人化の改善にも波及するからです。
テスト不足への対処
「全部にテストを書く」は現実的ではありません。最初は以下の優先順位で着手します。
- 決済・認証・権限管理 — バグが出たときのビジネス影響が最大の箇所
- コアのビジネスロジック — 競合と差別化する機能の中心部分
- 修正のたびに壊れる箇所 — 過去に何度も問題が起きた部分
テストカバレッジ率(全コードに対してテストが実行される割合)の一般的な目安は80%以上ですが、重要な箇所を完全にカバーした60%の方が、薄く広く広げた80%より価値があります。
設計起因への対処
設計の問題を一度に全部直そうとすると、既存機能を壊すリスクが高まります。まず複雑度が高い箇所を特定することから始めます。関数・メソッドの行数が50行を超えているもの、1つの関数で複数の処理を担っているものが候補です。
次に、その箇所に先にテストを追加してから(安全網を作ってから)リファクタリングします。「テストなしのリファクタリング」は別のバグを生むリスクがあります。
技術負債としての設計起因のバグについては、「技術負債」の正体とスタートアップで問題になるパターンで詳しく整理しています。
プロセス起因への対処
最初のステップはコードレビューのルール化です。「PRには最低1人のレビュアーが承認してからマージ」というルールを決めるだけで、一定の品質ゲートが機能します。
次にCI(継続的インテグレーション)の導入です。GitHub Actionsなどを使い、コードがマージされるたびに自動でテストが実行される仕組みを作ります。テストがない状態でも、静的解析ツール(ESLint、Pylintなど)だけでも導入すると、基本的なバグ予防になります。
属人化への対処
まず「誰がどのコードを担当しているか」を可視化します。GitHubのコントリビューション統計で、特定のファイルやモジュールへのコミットが特定の担当者に集中していないかを確認できます。
集中が見られた箇所に対して、ペアプログラミング(2人でコードを書く)またはコードレビューの義務化を適用します。同時に、その担当者に「設計の意図と判断の背景」をドキュメント化してもらう依頼をします。これはスタートアップにおける組織構築の基礎的な取り組みです。
要求の曖昧さへの対処
実装前に受け入れ基準(アクセプタンス・クライテリア)を書く習慣をつけることが根本的な解決策です。
「ユーザーがログインできること」ではなく「正しいメールアドレスとパスワードを入力するとトップページに遷移し、誤った場合はエラーメッセージが表示されること」という粒度で書きます。Notionのissueテンプレートに受け入れ基準の欄を追加するだけで、実装者と依頼者の認識ずれが大幅に減ります。
CTO不在チームが最初に着手すべき1手
CTO不在の状態で上記すべてに同時に取り組もうとすると、どれも中途半端になりがちです。最初の1手としてバグの発生パターンを記録・分類することから始めることを推奨します。
過去3ヶ月のバグ報告を以下の観点で分類します。
- 再発バグか新規バグか(テスト不足 vs プロセス起因の判断材料)
- 特定のモジュール・担当者に集中しているか(設計起因・属人化の判断材料)
- 「仕様通りなのに」という反応があったか(要求の曖昧さの判断材料)
GitHubのIssueやNotionのデータベースにラベルを付けるだけで十分です。1〜2週間で傾向が見えれば、最初の打ち手を絞り込めます。
この「記録して分類する」というアプローチは、技術力がなくてもできます。PM・経営者でも実行でき、バリューアップ投資の優先順位判断の精度が上がります。VC のバリューアップ担当者がスタートアップの技術状態を診断する場合も、まずこのデータを確認することが出発点になります。
まとめ
バグが減らない問題を整理すると以下のようになります。
| 根本原因 | 代表的な症状 | 最初の打ち手 |
|---|---|---|
| ① テスト不足 | 修正済みバグの再発 | コアロジックにテストを追加 |
| ② 設計起因 | 直したら別が壊れる | バグ集中箇所の局所的リファクタ |
| ③ プロセス起因 | 毎回新しいバグが出る | コードレビューとCIの導入 |
| ④ 属人化 | 特定担当者のコードにバグが集中 | ペアプロとドキュメント化 |
| ⑤ 要求の曖昧さ | 「仕様通り」の修正依頼が多い | 受け入れ基準の事前定義 |
技術戦略として重要なのは、「バグをゼロにする」ことではなく、「バグが出たときに素早く特定・修正できる組織にする」ことです。CTO不在のスタートアップでも、根本原因を分類することで打ち手が明確になります。
技術負債とバグの関係については技術負債とは結局何か:投資家・経営者向けの再定義も参照ください。スタートアップの技術組織への支援についてはスタートアップ向けTiedProをご覧ください。
よくある質問
Q. バグの根本原因を特定するのにエンジニアが必要ですか?
分類と優先順位の判断は、非エンジニアでも一定程度可能です。「再発しているか」「どの担当者のコードに集中しているか」「仕様通りなのに修正依頼が来るか」は、開発に詳しくなくても確認できます。コードレベルの詳細分析(複雑度・テストカバレッジ)には技術専門家の関与が有効です。
Q. バグの根本原因が複数重なっている場合はどうすればよいですか?
影響範囲が広く、対応難易度が低いものから着手することが基本です。多くの場合、プロセス起因(③)から整備することで、テスト不足(①)や属人化(④)の問題にも間接的に効きます。一度に全部を解決しようとせず、1〜2つの根本原因に集中して3ヶ月改善を続けることを推奨します。
Q. バグが「ゼロ」になることはありますか?
複雑なソフトウェアにバグゼロはありません。目標は「バグをゼロにする」ことではなく、「バグが出たときに素早く特定・修正できる組織にする」ことです。根本原因を把握し、対処できる仕組みを持つことが品質管理の本質です。