技術的負債
技術的負債(technical debt)、または設計負債、コード負債とは、ソフトウェア開発における概念であり、時間がかかるより良いアプローチを使用する代わりに、今すぐ簡単な(限定的な)解決策を選択することで生じる追加の手直しの暗黙のコストを反映したものである。
金銭的な負債と同様に、技術的負債も返済されなければ、「利子」が蓄積され、変更の実施が困難になる。技術的負債を処理しないと、ソフトウェアのエントロピーが増大する。金銭的負債と同様に、技術的負債も必ずしも悪いものではなく、プロジェクトを前進させるために(概念実証として)必要な場合もある。一方で、「技術的負債」というメタファーは、その影響を最小限に抑える傾向があり、その結果、修正するために必要な作業の優先順位付けが不十分になると主張する専門家もいる。
コードベース上で変更が開始されると、コードベースの他の部分やドキュメントにも、他の調整された変更が必要になることがよくある。完了していない必要な変更は負債とみなされ、支払われるまでは利息が上乗せされて発生するため、プロジェクトの構築が煩雑になる。この言葉は主にソフトウェア開発で使われるが、他の職業にも適用できる。
技術的負債の一般的な原因は次のとおり。
継続的な開発:時間をかけてプロジェクトを強化していくと、古いソリューションは最適ではなくなる。
不十分な先行定義:開発中に要件がまだ定義されていない場合、設計が行われる前に開発が開始される。これは時間を節約するために行われるが、後になって手直しをしなければならないことがよくある。
ビジネス上のプレッシャー:必要な変更が完了する前に、ビジネスが何かをすぐにリリースすることを検討する場合、未完了の変更からなる技術的負債が蓄積される。
プロセスや理解の欠如。企業が技術的負債の概念に気付かず、その影響を考慮せずに意思決定を行う。
緊密に結合されたコンポーネント。機能がモジュール化されていないため、ソフトウェアはビジネスニーズの変化に対応できるだけの柔軟性を持たない。
テストスイートがないため、迅速でリスクの高い応急的なバグ修正が行われる。
文書化の欠如:コードが文書化されずに作成されている。ドキュメントを作成するための作業は負債となる。
コラボレーションの欠如:知識が組織内で共有されず、ビジネスの効率が低下したり、若手開発者が適切に指導されない。
複数のブランチで並行して開発を行うと、変更点を1つのソースベースにマージする作業が必要になるため、技術的負債が発生する。分離して行われた変更が多ければ多いほど、負債は大きくなる。
リファクタリングの遅延:プロジェクトの要件が進化するにつれ、コードの一部が非効率的になったり、編集が困難になったりすることが明らかになり、将来の要件をサポートするためにリファクタリングが必要になることがある。リファクタリングが遅れれば遅れるほど、また、コードが追加されればされるほど、負債は大きくなる。
スタンダードとの整合性の欠如。業界標準の機能、フレームワーク、技術が無視されている。最終的にはスタンダードとの統合が行われ、それを早く行うことでコストを削減することができる(「リファクタリングの遅延」と同様)。
知識の欠如:開発者がエレガントなコードの書き方を知らない場合。
オーナーシップの欠如:ソフトウェアの外注化により、社内のエンジニアリングが外注コードのリファクタリングやリライトを要求される場合。
技術的なリーダーシップの欠如:十分に考えられていない命令が指揮系統の下に伝えられること。
直前の仕様変更。このような変更は、プロジェクト全体に浸透する可能性があるが、文書化してチェックするための時間や予算がない。
ケニー・ルービンは、次のような状態区分を用いている。
ハプニング的な技術的負債:開発チームが、製品に対する通常の作業中に露呈するまで、その存在に気づかなかった負債。例えば、開発チームが製品に新機能を追加している最中に、何年も前に退職した人がコードに回避策を組み込んでいたことに気付いたとする。
既知の技術的負債:開発チームが把握している負債で、前述のいずれかの方法で可視化されたもの。
ターゲットにされた技術的負債:既知の技術的負債で、開発チームがサービスを提供する対象となっているもの。
"利子の支払い"は、ローカルで必要なメンテナンスと、プロジェクトの他のユーザーがメンテナンスを行わないことの両方によって発生する。上流のプロジェクトで継続的な開発を行うと、将来的に「負債を返済する」ためのコストが増加する。完結していない作業を完了させるだけで、負債を返済することになる。
技術的負債の蓄積は、プロジェクトが納期に間に合わなくなる大きな原因となる。技術的負債を返済するために必要な作業量を正確に見積もることは困難である。変更に着手するたびに、不確実な量の未完成の作業がプロジェクトにコミットされる。プロジェクトは、未完了の作業(負債)が完了するための時間よりも多いことに気付いたときに、期限を逃してしまう。予測可能なリリーススケジュールを実現するためには、開発チームは未完成の作業(または負債)の量を常に小さくするために、進行中の作業の量を制限する必要がある。
提出の障害にならない程度の作業が完了していれば、技術的な負債が相当量残っているプロジェクトがリリースされる。このソフトウェアが本番環境に到達した場合、技術的負債を解決するためのリファクタリングを実施するリスクは劇的に高まる。本番コードの修正には、サービス停止のリスク、実際の金銭的な損失、サービス水準合意(SLA)を伴う契約の場合には法的な影響を受ける可能性もある。このような理由から、技術的負債を本番環境に持ち込むことは、ほとんど金利の上昇と同じように考えることができ、この金利が下がるのは、デプロイメントが却下されてリタイアするときだけである。"進化するプログラムが継続的に変更されると、構造の劣化を反映して複雑さが増し、それを維持したり減らしたりする作業が行われない限り、複雑さが増していく」。
- Meir Manny Lehman, 1980マニー・リーマンの法則は、進化するプログラムは、維持するための作業を行わない限り、継続的にその複雑さと劣化した構造を増していくことをすでに示していたが、ウォード・カニンガムは、1992年の経験報告で、技術的な複雑さと負債の比較を初めて行った。"最初のコードを出荷することは、借金をするようなものだ。少々の借金は、書き換えによって速やかに返済される限り、開発を加速させる。危険なのは、その負債が返済されないときだ。正しいとは言えないコードのために費やされた1分1秒が、その負債の利息としてカウントされるのである。オブジェクト指向であろうとなかろうと、統合されていない実装の負債の負荷によって、エンジニアリング組織全体が停止してしまう可能性があるのだ。"
- 1992年、ワード・カニンガムJoshua Kerievskyは、2004年に発表したテキスト『Refactoring to Patterns』の中で、アーキテクチャの怠慢に伴うコストを「設計負債」と表現し、同様の議論を展開している。
後回しにされる活動には、文書化、テストの作成、TODOコメントへの対応、コンパイラや静的コード解析の警告への対処などがある。また、技術的負債には、組織内で共有されていない知識や、混乱していて簡単に修正できないコードなどがある。
2014年にPHPの開発について書いたJunade Aliはこう述べている。この技術的負債を返済しないことの代償は明らかである。最終的には、機能を提供するためのコストが非常に遅くなり、設計の良い競合ソフトウェア製品が機能面で設計の悪いソフトウェアを追い越すことが容易になる。私の経験では、設計の悪いソフトウェアは、エンジニアのストレスを増大させ、スタッフの離職率を高める(これは、機能を提供する際のコストと生産性に影響する)。さらに、コードベースが複雑になると、作業を正確に見積もることができなくなる。また、開発会社が機能ごとに料金を設定している場合、コードを納品する際の利益率が低下してしまう。
- Junade Aliは、Mastering PHP Design Patternsにこのように書いている。グラディ・ブーチは、都市を進化させることが、ソフトウェア集約型システムを進化させることに似ていること、そしてリファクタリングの欠如が技術的負債につながることを比較している。"技術的負債の概念は、システムにかかる力を理解する上で中心的なものであり、システムがどこで、どのように、そしてなぜストレスを受けているのかを説明するのに役立つ。都市部では、インフラの修理が遅れがちで、大胆な変更ではなく段階的な変更が行われる。ソフトウェア集約型のシステムでも同じことが言える。ユーザーは気まぐれな複雑さ、改善の遅れ、不十分な漸進的変化の結果に苦しみ、そのようなシステムを進化させる開発者は、常に追いつこうとしているために質の高いコードを書けないという苦しみを味わうのである。"
- グラディ・ブーチ、2014年オープンソースソフトウェアでは、ローカルな変更を上流のプロジェクトに送ることを先延ばしにすることが、技術的負債の一種である。