← デバッグの作法 レビュー文化・設計 →

📑 この章の目次

title: 開発プロセス・品質 icon: 🛡️ card_desc: バグを未然に防ぎ・早く見つける仕組み — テスト・Lint・型チェック・レビューの役割分担と「早く見つけるほど安い」思想 slug: 12-quality

12 開発プロセス・品質 — バグを未然に防ぎ、早く見つける仕組み

前章(第11章)では「起きてしまったバグ」を論理的に直す作法を扱いました。本章ではその前段 —— そもそもバグを出しにくくし、出ても早く見つける仕組みを扱います。「直す力」と同じくらい「防ぐ力」が、開発の現場では問われます。


一言でいうと

バグは後になるほど直すコストが跳ね上がります(本番で発覚すれば手元の何倍・何十倍)。だから現場は「人間の目と記憶に頼らず、機械にチェックさせる」仕組みを何層も重ねます。本章では、コードの品質を保つ3つの自動検査 —— テスト・Lint・型チェック —— と、人間のコードレビューの役割分担、そして「早く見つけるほど安い」という工程の思想を扱います。


1. なぜ品質の作法が必要なのか

「後で直す」の罠

締め切り前。「とりあえず動いたから、テストは後で書こう」と検査を後回しにして進める。すると:

これが第1章で触れた技術的負債の正体です。「後で直す」は借金で、利息(後からの追加コスト)が雪だるま式に膨らみます。

バグの発見は「早いほど安い」

経験則として、バグの発見タイミング修復コストには桁違いの差があると言われます:

どこで見つかるか おおまかなコスト(比)
書いている最中(エディタ・型チェック) 1
コミット前(手元のテスト・Lint) 数倍
CI / PR(push 時の自動検査) 数十倍
結合テスト・QA 数百倍
本番のユーザー 数千〜数万倍(信用損失を含む)

※ 数値は文脈による目安ですが、「手元で直すのと本番で直すのとで桁が違う」はほぼ普遍的な傾向です。

だからこそ「できるだけ手前で」バグを見つける仕組みが必要です。第11章は「起きたバグを直す」、本章は「そもそも起きない・出ても早く見つける」の作法です。


2. 「品質を保つ仕組み」とは

4つの防衛線

現場で品質を保つ主な仕組みは、自動検査3つ + 人間の目1つです:

仕組み 何を見つけるか 誰が/何が見つけるか
テストtest 「期待通り動くか」を実行で確かめる 機械(自動)
Lint(リント) コードの書き方の問題・バグの種 機械(自動)
型チェックtype check/型検査) データの「種類」の矛盾 機械(自動)
コードレビュー 設計・可読性・見逃し 人間

CI(→ 第1章)は、これら自動検査を「push するたび機械に回させる」土俵です。中身の検査(テスト/Lint/型チェック)があるからこそ、CI の「緑」に意味が出ます。

共通の思想: 機械に任せる

4つすべてに共通する思想は「人間の目と記憶に頼らない」ことです。人間は忘れ・見落とします。「同じ規約を毎回手で確認する」は破綻します。だから一度ルールを書けば、何度でも機械が同じ基準でチェックする仕組みにのせる —— これが品質の作法の根幹です。


3. 🔑 バグを防ぐ3つの自動検査

テスト —— 正しく動くか「実行」で確かめる

テストは「この入力なら、この結果になるはず」を実際に動かして確かめる仕組みです(→ 第1章で既出、ここでは「なぜ書くか」を掘り下げます)。

テストの最大の価値は変更時の安全網です。コードを直した時、前まで動いていたものが壊れていないか(= 回帰regression/リグレッション)を自動で教えてくれます。テストがないと「直したつもりが別を壊した」に気づけません。

💡 テストしやすさも設計: 「テストが書きにくい」コードは、往々にして1つの関数に責務が混ざりすぎているサインです。テストを書きやすい設計は、結果的に読みやすく変更しやすい設計になります。

Lint —— コードの書き方の問題を「静的に」見つける

Lint(リント)は、コードを実行せずに(= 静的解析static analysis/スタティックアナリシス)、書き方の問題を見つける検査です。リンターlinter/→ 用語集)が担当します。

見つけてくれるもの:

Lint の強みは速さと完全性です。実行不要なので一瞬で、かつ「全部の行を見る」ので人間の見落としを補います。「インデントが揃っていない」等は人間が直すには退屈で、機械に任せるべき典型です。

型チェック —— データの「種類」の矛盾を見つける

型チェックtype check/型検査)は、データの**「種類(型)」**の矛盾を(これも静的に)見つける検査です。

例:

型の矛盾は実行時エラーやバグの代表格です。型チェックを通しておけば「この値は絶対に数値」と機械が保証してくれるため、その类别のバグが構造的に起きなくなります。静的型付き言語(TypeScript・Rust・Go 等)ではコンパイラが、動的型言語(Python 等)では型ヒント+検査ツール(mypy 等)が担います。

3つの役割分担

検査 得意 見つけられない
テスト 実際の動作・回帰防止 書いていない経路・仕様の誤り
Lint 書き方の問題・バグの種 実行時にしか分かる問題・仕様
型チェック データの種類の矛盾 正しい型だが中身が違う問題

どれ1つで完璧にはなりません。3つを重ねて「それぞれの隙間」を埋めるのが、品質を保つ作法です。


4. レビューと「早く見つける」思想

コードレビュー —— 人間が見る最後の砦

自動検査を全通過しても、まだ人間にしか分からない問題が残ります:

これを Pull Request(→ 第2章)で他のメンバーに見てもらうのがコードレビューです。レビューは単なるミス探しでなく、チームの知見を共有し合う場でもあります(詳細は第13章「レビュー文化・設計」で扱います)。

🔑 レフトシフト —— 手前で見つけるほど安い

前出の「バグは早く見つけるほど安い」を、工程の観点で言い換えたのが left shift(レフトシフト/左へずらす)という思想です。

開発工程を左から右へ進むと見立てます:

設計 → コーディング → テスト → リリース → 本番運用
 ←早く見つけるほど安い→          ←遅いほど高い→

問題をこの流れの**左(手前)**で見つけるほど、直すコストが安い。だから:

すべて「問題を右に運ばない」ための仕組みです。


5. 🔑 段階的な検査 —— 手元から本番まで何層も重ねる

同じ検査を「複数のタイミング」で

重要なのは、検査を1回しかしないのでなく何層も重ねることです。例えばテスト・Lint・型チェックは:

  1. エディタ: 書いている最中(リアルタイムに波線等で指摘)
  2. コミット前pre-commit): 履歴に入る直前にブロック
  3. CI / PR(→ 第1章): push のたび全体を自動検査
  4. 本番前ゲート(→ CD): 検査不通過なら本番に行かせない

なぜ何層も? —— 各層が別の目的を担うからです。エディタは速さ、CI は完全性、本番前ゲートは最終防衛。1層抜けても次で止まる多重防御が、品質を安定させます。

「検査を通す」でなく「検査に頼る」設計

落とし穴は「検査があるから大丈夫」と検査に丸投げする態度です。検査は書かれたことしか確かめません。テストが無い経路は検査されず、Lint も型チェックも「仕様が正しいか」は分かりません。だからこそ:

品質の作法は「検査をパスすること」でなく「検査に支えられた自信を持つこと」が目的です。


6. なぜ「品質の作法」が開発の作法なのか

作法として位置づけられる理由

面接・実務での意味


7. よくある落とし穴と対処

落とし穴 何が起きるか 正しい対応
テストを書かずに進める 回帰に気づかない・本番事故 最初からテストを書く。後回しは利息が膨らむ(技術的負債)
テストだけで安心する 仕様の誤り・型の問題を見逃す Lint・型チェックも重ねる。3つの役割分担を意識
Lint を無視/例外だらけ バグの種が残る・規約が形骸化 例外は最小に・意味のある指摘は直す。機械任せを徹底
検査を「通すため」に書く 通ったが中身が薄い・自信の根拠にならない 検査は仕様の明文化。重要な経路を意識して書く
人間の目に頼る 見落とし・属人化(担当者不在で止まる) 機械ができることは機械に。人はレビュー(設計・可読性)へ
早い段階の検査をサボる CI・本番まで運んで大コスト レフトシフト: エディタ・pre-commit で手前に止める

💡 カバレッジの罠: 「テストのカバレッジ(→ 用語集・何%のコードを実行したか)が高い = 品質が高い」は短絡です。カバレッジは「実行した割合」であって「正しさを確かめた割合」ではありません。「通っただけで正しい結果を見ていない」テストもカバレッジを稼ぎます。数値は参考値と割り切り、中身(重要な経路を確かめたか)で判断するのが作法です。


まとめ

💡 次のステップ: バグを防ぐ個別の検査と「早く見つける」思想が見えました。最後の第13章レビュー文化・設計」では、人間の目であるコードレビューの作法と、そもそも変更しやすいコードの設計(アーキテクチャ)の基本を扱って、本書を締めくくります。