開発プロセス●●○○○

技術的負債

Technical Debt ・ ぎじゅつてきふさい

短期の速度と引き換えに将来へ先送りした設計・実装の劣化。利子のように開発を遅くする。

✦ 30秒で試す — 航海借りたのはコードの「きれいさ」。返すのは毎週の時間6週続けて近道したら、合計は丁寧の18時間と比べて?予想してみる

概要

技術的負債は、「今すぐ出荷するための近道」と引き換えに将来へ先送りされた、設計や実装の劣化を指すメタファーです。お金の借金と同じく、借りること自体は悪ではありません。締め切りに間に合わせるために理想的でない設計で出荷するのは、合理的な経営判断でありえます。問題は、負債には利子が付くことです。歪んだ構造の上にコードを書き足すたびに余計な手間がかかり、その「余計な手間」が利子として、返済するまで毎回の変更に課され続けます。

利子が膨らんだコードベースでは、単純な機能追加に数週間かかる、1行直すと別の場所が壊れる、怖くて誰も触れないモジュールがある、といった症状が現れます。俗に「レガシーコード」と呼ばれる状態は、負債が長期間放置されて利払いが開発速度を圧迫している状態と言えます。エンジニアとビジネス側が開発速度の低下について対話するための共通言語として、この語彙は生まれました。

なぜ生まれたか

このメタファーは1992年、Ward Cunningham が金融システムの開発報告の中で使ったのが最初です。彼が伝えたかったのは「汚いコードを書いてしまった言い訳」ではなく、その逆でした。まだ問題を完全には理解できていない段階でも、現時点の理解でコードを書いて出荷することで学びを早められる — これは借金で事業を加速するのと同じで正当な戦略である。ただし、理解が進んだら、その学びをコードに反映して負債を返済しなければならない。返済せずに借り続ければ、いずれ利払いだけで手一杯になり開発が止まる、という警告です。

つまり原義における負債とは「意図的な借り入れと、学びによる返済」のサイクルでした。当時、非エンジニアの経営層に「なぜ動いているコードを書き直す時間が必要なのか」を説明するのは困難でしたが、金融の語彙に翻訳したことで、「元本」「利子」「返済」としてビジネス側と同じ土俵で議論できるようになったのです。後にこの言葉は「単に汚いコード」全般を指すように拡大しましたが、原義の「意図性」を区別することが、負債と付き合ううえで重要になります。

詳細

負債の4象限 — どんな借り方をしたか

Martin Fowler は技術的負債を「意図的か / 無自覚か」「慎重か / 無謀か」の2軸で4象限に整理しました。同じ「良くないコード」でも、どの象限の負債かによって評価がまったく異なります。

意図的(分かって借りる)無自覚(気づかず借りる)慎重無謀戦略的な借り入れ「今は近道して出荷し、結果への対処は後で行う」原義の負債。返済計画とセット学習による負債「今なら、どう設計すべきだったかが分かる」避けられない。気づいた時が返済時確信犯的な手抜き「設計する時間なんてない」利子の見積もりなしの借金。危険無知による劣化「設計って何のこと?」教育・レビューで防ぐしかないMartin Fowler の Technical Debt Quadrant を基に構成
技術的負債の4象限 — 慎重で意図的な負債だけが戦略であり、無謀な負債はただの劣化

左上の「慎重かつ意図的」だけが原義どおりの戦略的な負債です。トレードオフを理解したうえで借り、返済の当てもある。右上の「慎重だが無自覚」は、最善を尽くしても後から「ああ設計すべきだった」と分かるもので、学習する組織なら必ず発生します。危険なのは下段です。「慎重さを欠いた意図的な負債」は利子の見積もりなしの借金であり、「無自覚かつ無謀な負債」は基本スキルの不足による劣化で、そもそも借金している自覚すらありません。下段の負債はコードレビューやペアでの作業、教育によって発生自体を防ぐのが第一です。

利子の正体 — なぜ開発が遅くなるのか

負債の利子は請求書として届くわけではなく、日々の開発の中に紛れ込みます。具体的には、変更のたびに歪んだ構造を回避するコードを書き足す手間、影響範囲が読めず調査に費やす時間、修正が別の箇所を壊すリグレッション(デグレ)、そして「怖いから触らない」ことで選択肢が狭まる機会損失です。テストがないことも重大な負債の一形態です。テストという安全網がないコードは検証コストが高く、あらゆる変更の利子を押し上げます。また、負債はコードだけでなくアーキテクチャの水準でも発生します。たとえば境界設計を怠ったモノリスが「どこを触っても全体に波及する」状態に陥るのは典型的なアーキテクチャ負債で、慌ててマイクロサービスに分割しても、境界の混乱ごと分散させれば負債は減るどころか利子が上がります。

利子の怖さは、1回ごとの額ではなく、以後のすべての変更に毎回かかり続けることと、歪んだ構造の上でさらに近道をすると歪みの増え方そのものが速くなることにあります。下の部品で確かめてください。毎回1つの機能を「近道」か「丁寧」かで作り、負債がたまったら「返済」(リファクタリング)の回を挟むこともできます。柱の上に積まれる朱の積み木が、その回に払った利子です。

⚡ 体験: 近道か、丁寧か — 利子が積み上がる
近道で作る2h + 利子 0h負債が増える丁寧に作る3h + 利子 0h負債は増えない返済する負債 0個 × 1h機能は作れない負債ブロック 0個(毎回 0時間の利子)02468その回にかかった時間(h) 下: 作業 朱: 利子123456789101112いつも丁寧なら 3h次の機能 #1
回0 / 12出荷した機能0合計時間0.0h1機能あたり—負債0個

毎回、上の機能のカードをつかんで「近道」か「丁寧」の箱へ運ぶと、その機能を作ります。右の柱が、その回にかかった時間です。まずは近道を何回か続けてみてください。

近道を続けると、柱は回を追うごとに高くなり、「いつも丁寧」の線を早々に超えていきます。途中で返済の回を挟むと、その回は機能を出荷できないかわりに、次の回から朱の積み木が消えます。借りること自体ではなく、返さずに利子を払い続けることが開発を止めるのです。

返済戦略

負債の返済とは、構造の歪みを解消すること、すなわちリファクタリングです。現実的な返済戦略にはいくつかの型があります。第一に、全部を返そうとしないこと。利子は「よく変更する場所」でしか発生しないため、変更頻度の高いホットスポットに返済を集中させ、もう触らないコードの負債は放置してよいのです。ホットスポットは勘ではなく履歴から見つけられます。Git のコミット履歴からファイルごとの変更回数を数え(git log --format= --name-only の集計など)、それを複雑さ(行数や分岐の多さ)と掛け合わせると、「複雑なうえに頻繁に変更されている」=利子を最も払っている場所が浮かび上がります。Adam Tornhill が『Your Code as a Crime Scene』で広めた分析手法です。第二に、一括返済より分割払いを選ぶこと。「リファクタリング専用の1か月」を確保するのは承認も難しく失敗しやすいため、機能開発のついでに通り道を少しずつ直す方が持続します。第三に、新たな無謀な借金を止めること。レビューや CI/CD の自動チェックで品質の下限を守り、負債の増加速度を返済速度が上回る状態を作ります。

ビジネス側への説明

技術的負債の議論が失敗する典型は、エンジニアが「コードが汚いので直したい」と美意識の言葉で語ることです。ビジネス側に伝わるのは美しさではなく速度とリスクです。「この領域の変更に以前は2日だったが今は2週間かかっている」「次の機能はこのモジュールに乗るので、先に3日返済すれば実装が5日縮む」のように、利子を時間とお金の言葉に翻訳して初めて、負債メタファーは本来の力 — 技術とビジネスの共通言語 — を発揮します。逆にエンジニア側も、すべての負債返済が投資に見合うわけではないことを受け入れる必要があります。借金と同じで、問われるのはゼロにすることではなく、健全な水準で回し続けることです。

試問

毎回、次の機能のカードを「近道で作る(2時間。負債が増える)」「丁寧に作る(3時間)」「返済する(機能は作らず、負債1個につき1時間で消す)」のどれかの箱へ運びます。どの回も、それまでに残っている負債1個につき0.5時間の利子が上乗せされます。全部で12回です。

✦ 命題挑戦中

最初の3回の締め切りを守りつつ、12回を合計36時間以内・負債0で終えよ

  • 締め切り: 最初の3回で機能を3個、合わせて8時間以内に出荷
  • 12回を終えたとき、負債が0
  • 12回で機能を11個出荷し、合計 36時間以内
⚡ 体験: 近道か、丁寧か — 利子が積み上がる
近道で作る2h + 利子 0h負債が増える丁寧に作る3h + 利子 0h負債は増えない返済する負債 0個 × 1h機能は作れない負債ブロック 0個(毎回 0時間の利子)02468その回にかかった時間(h) 下: 作業 朱: 利子123456789101112いつも丁寧なら 3h次の機能 #1
回0 / 12出荷した機能0合計時間0.0h1機能あたり—負債0個

毎回、上の機能のカードをつかんで「近道」か「丁寧」の箱へ運ぶと、その機能を作ります。右の柱が、その回にかかった時間です。まずは近道を何回か続けてみてください。