BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ アーティクル 技術的負債を管理する

技術的負債を管理する

ブックマーク

原文(投稿日:2013/05/06)へのリンク

技術的負債は避けるべきであり、出来るだけすぐに返済すべき悪いことだと広く考えられています。

そうでしょうか? 私たちはそうは思いません。ここでは、まず財政上の負債と技術的負債を比較し、戦略的デザインとの類似性を説明します。そして、驚くべきことに技術的負債の持つテークホルダについて述べます。それから、おそらくどうにかしなければならない、コードの中の技術的負債を見分けるさまざまな可能性を紹介します。

最後に、プロジェクトが技術的負債を返済できるさまざまな方法と、返済したほうがよいか、負債を転換するか、利息を支払うだけかを決めるために、熟考しなければならないことを説明します。

技術的負債とは何か

開発者は、新しい機能を2つの異なる方法で実装することを選択できます。1つは素早くいい加減に実装します。この場合、将来の変更がとても難しくなります。もう1つは、クリーンでスマートな解決策であり、実装に時間がかかりますが、将来、簡単に変更できます。(Martin Fowlerをご覧下さい。) しかし、機能をクリーンな実装にして、より多くのコストをかけることを、プロジェクトのスポンサーが受け入れるでしょうか? いい加減な解決策で同じ機能を、同様の機能性を持たせたまま、より少ないコストで提供できるのです。また、自動テストのカバレッジのためにお金を払うでしょうか? テストは機能ではないので、ビジネスの価値は提供されません!

顧客が望むビジネスの価値を提供できれば、汚いコードやテストのないコードでも顧客は満足しますが、手に負えないコードベース、極端に専門化した開発者、そして、融通のきかないソフトウェア製品を作り出します。大量の汚いコードは、エンジニアリング部門全体を停滞させるかもしれません。

‘技術的負債’のメタファ - ‘財務的負債’との類似性と相違性

1992年にWard Cunningham氏が、技術系ではないステークホルダにこの問題を伝えるために、初めて「技術的負債」というメタファを使いました。品質の低いコードと自動テストによるカバレッジがないことは、財務的負債と比較されます。このようなコードは、開発者だけでなく、すべてのステークホルダが負う財政的な重荷になり、将来的に利息が課される負債になります。元本額は、コードベースを将来簡単に変更できるようにリファクタリングするコストです。利息は、チームがよいコードではなく、汚いコードに取り組まなければならない場合に、将来支払う余分なコストです。

財務的負債とは違い、技術的負債は返済しなくてもよい負債です。時には、返済するのが無駄なこともあります。ある部分のコードを読んだり、変更したりすることはめったにないか、決して起こらないかもしれません。そのため、技術的負債も、どのくらい起きそうかを考慮する必要があります。将来、その汚いコードに触ることがどのくらいあるでしょうか? 財務的負債と違うもう1つの点は、技術的負債を作り出した人が自分で負債を返済する必要がなく、後でコードベースをメンテナンスする開発者がその負債を返済しなければならないことです。

財務的負債のように、技術的負債は必ずしも悪いことではありません。家を買うために負債を負うには、返済方法を知っていなければなりません。自分ですべての請求を支払えないと分かっているのに、クレジットカードでぜいたくな品々を買うと、普通は大きな災難になります。ソフトウェアの技術的負債に気を付ければ、早くリリースできる有利な点となり、技術的負債を返済するためのコストよりも組織に利益を与えるかもしれません。財務上は、利息と元本が投資の利回りよりも低ければ、負債は良いことです。ソフトウェアには同じことが当てはまります。最初に市場へ出るために内部品質を犠牲にしたとしても、より良い内部品質で後から市場に出た場合よりも、この決定によって得た金額が高ければ、利益を生み出します。しかし、ある程度不確かなことがあるため、そのような利益を予め見積もるのは難しいので、ここにはリスクがあると言えます。

技術的負債と戦略的デザイン

Eric Evans氏の戦略的デザインの概念は、技術的負債の扱い方についてアイデアを与えてくれます。戦略的デザイン では、システムはシステム全体で品質を高く保つことはできないと言われています。そのため、システムに良い品質と悪い品質があるようしておくか、積極的に品質をコントロールするかをチームは選べます。めったに読んだり、触ったりせず、重要な要求を実装しないような汚いコードは、完璧である必要はありません。だから、その汚いコードを素晴らしいコードにリファクタリングするために、大きな労力をかける必要はないのです。そこで、疑問なのは、コードのどの部分が高品質であるべきかということです。実装の一部で、品質は悪くないが、設計が悪いこともあります。その実装の一部に、良い設計は必要とされていないのです。この主張には、もちろん疑問が残ります。コードがそれぞれ特定の部分で良い品質を必要としないならば、手短に言えば、あなたはメンテナンス不能なシステムを作っているのかもしれません。

戦略的デザインと技術的負債を理解していれば、プロジェクト内でのコミュニケーションが良くなり、そのソフトウェアプロジェクトのステークホルダからより良い決定を得られるでしょう。非常に労力がかかるならば、要求すべてを素晴らしいコードで実装しなくても良いことを開発者たちは理解しているかもしれません。また、素早くて汚い解決策は負債となり、結局、プロジェクトが返済しなければならないことを顧客は理解しています。技術的負債は隠れた品質問題から成り、氷山のように表面に現れたらプロジェクトを失敗に導くでしょう。例えば、バグが多すぎる場合、費用効果があるように品質問題を修正するには、たぶん遅すぎるのです。

技術的負債のステークホルダ

技術的負債はソフトウェアプロジェクトのステークホルダに関係します。

  • 生産性が低ければ、顧客たちはバグや機能不足に悩ませられます。
  • ヘルプデスクに余分なコストがかかり、ヘルプデスクの人たちも悩ませることになります。
  • 開発時間の増加と品質問題は、マーケティング上の問題にもなります。
  • バグのために頻繁なパッチが必要になり、運用チームに迷惑をかけます。
  • 多くの悩ましい出来事は、絶対に経営陣を喜ばせることはありません。バグのために悪い評判が立ったり、遅延やセキュリティ問題が発生したりする時は、特に経営陣を困らせます。
  • 大事なことを言い忘れていましたが、開発者も苦しみます。誰もひどい作業を納品したい人はいませんし、誰も他人のひどい作業を引き継ぎたくはないでしょう。

技術的負債は避けられない

では、なぜ多くのチームが最初にうまくやって、技術的負債を避けようとしないのでしょうか? 開発者がなまけているのではなく、関連する技術やパターンを経験しているとしても、技術的負債は、ほぼ必ず時間のプレッシャーによって強いられることになります。開発者たちは、素早くて汚い実装が将来のリリースで低い生産性と高いコストの原因になるとよく分かっていながら、短期間の生産性を上げて、目の前のリリースでコストを下げようとします。しかし、チームは目の前のリリースで高い生産性と低いコストを実際に実現できたかどうか、本当に確信できたことはありません。おそらく、近道した分は予想よりも早く返って来て、チームは予想よりも早くその利息を支払わなければなりません。

しかし、開発者としての私たちは、普通、近道したり、品質に妥協したりするのを望んではいません。時々、外部的条件は、ただリリース内のことは素早く終わらせなければならないということです。そうでなければ、次のリリースはないでしょう。または、コードが読まれたり、変更されたりすることはあまりないとチームは仮定します。少し前に議論した「戦略的デザイン」は、確実に品質に妥協することを許しています。その場合、よいコードはやり過ぎの「金のメッキ」なのかもしれません。

このように、技術的負債のメタファがすべてのステークホルダに低い品質の問題を伝える役に立っていることが分かりました。そうでなければ、問題に気づいた時には遅すぎているでしょう。コード品質が悪く、品質がますます低下するために、引き続き起こる損害は、よく利息に例えられます。しかし、そのメタファは、少しだけ足りないところがあります。すべての技術的負債を常に返済しなければならない訳ではありません。負債がいくらか、いつまでに返済しなければならないかを、チームは知りません。負債を負う人が返済する人である必要はなく、通常は別の人になります。現実世界はおもしろいですね!

技術的負債を見分ける

技術的負債の主な問題は、それが明らかではないことです。誰でも利用明細の負債の額は見ることができます。しかし、どのようにチームが技術的負債を実際に認識できるのでしょうか? 指標は何でしょうか?

  • チームメンバ自身から明らかにされる通常の「におい」は、「このコードを変更できるのはCarlだけだ」、「このコードをだだコピー&ペーストしよう」、「私がコードを触れば、すべて壊れるだろう」という言葉や、コードの中にあまりにも多くのTODOやFIXMEがある(Nico Zazworka氏が上手に解説しています) ことで分かります。
  • スクラムチームはベロシティを使います。チームが変わらず、外部環境も変わっていないけれども、ベロシティが減る場合、ソフトウェアシステムにおそらく沢山の技術的負債があります。
  • ソフトウェアは古くなります。技術的負債の1つの指標は、もうメンテナンスされていないか、新しいバージョンの方がずっと生産性が高いような非常に古いライブラリを使う時です (例えば、EJB 2 対 EJB 3)。 最悪なのは、ライブラリがすでに古すぎて、ライブラリの開発者たちがそのライブラリをもうサポートしていない時です。
  • 自動的に技術的負債を計測することは部分的に可能です。正確に設定されたSonarやSonarJ、Structure101などのツールは、最良のコーディングプラクティスの重要な違反を見つけ出します。このブログの投稿が示すように、これは究極の解決策ではありませんが、とても良いものです。Sonarを使えば、クラスやメソッドの適切なサイズやサイクロマティックな複雑さの低さのような重要なコードメトリクスに開発者が従うようにできます。Structure101のようなツールは、構造上の問題を見つけます。これらには、循環依存を含みます。2つの要素がお互いに依存している場合、これらの要素の1つに変更を加えると、もう1つの要素に影響を与える可能性があります。これらの2つの要素は、同時に変更できます。ただし、本来ならば2つの要素は分かれているべきであり、個々に開発されなければなりません。さらに、Structure101は複雑なコードを見つけます。ここで複雑だというのは、要素間の依存関係のことです。クラスやパッケージが他のクラスやパッケージへ依存しすぎると、システムは本当に理解するのが難しく、メンテナンスができなくなります。開発者が変更したいと思ったら、沢山のクラスやパッケージを理解し、沢山の依存関係を考慮しなければなりません。これらの問題は、アーキテクチャへの重要なチャレンジを示しています。
  • コードカバレッジツールは、自動テストで実際にカバーしているコードがどのくらいあるのか検出できます。この測定基準は一般的なガイドラインがないので、注意して使うべきです。通常、90%以上のカバレッジは、十分なテストケースがあるという良い指標になります。逆に75%以下のカバレッジは、重大な問題を示しているかもしれません。
  • しかし、システムが技術的負債を抱えていながら、コードから直接計測できない多くのケースがあります。扱いにくい解決策や技術選定の間違い、実行可能でありながら、解決策の間違った設計、単にツールでは検出できない不正侵入などです。これらの場合、技術的負債は、別々の方法で計測しなければなりません。リリース毎のバグが急激に増えたり、ベロシティが変わることなく減っていったり、チームがリリース終盤に多大なストレスにさらされたりします。
  • 非常に悪い指標は、作成時に頻繁に問題が発生することです。これは、システムの問題が広範囲に渡るため信頼できる運用は不可能であることを意味しています。

これらの指標はすべて計測できますが、常に直接コードの中にあるのではありません。これらの問題がすぐに解決されるほど、コストは低くなります。開発者たちが技術的負債を見分け、それを伝え、何も起きないとしても、遅かれ早かれビジネス部門の人たちはこれらの問題を感じるでしょう。ここではっきりさせたいのは、技術的負債は、美しいコードがほしい開発者たちの企みではありません。技術的負債は、明確なコスト要因であり、プロジェクトのリスクになります。そのため、技術的負債は、目に見えて、管理できるものでなければなりません。現実世界では、負債は必ずしも悪いことではありませんが、自覚して適切に使わなければなりません。つまり、ソフトウェアプロジェクトにとって技術的負債を返済することは、純粋なビジネスの決定事項だと言えます。単なる開発者の決定ではありません。

技術的負債の管理

私たちは技術的負債が無視できないことを見てきました。クライアント側の技術者ではない管理者でさえ、短期的、中期的、そして、長期的成功の間でもっとも良いバランスをとるためにできるだけ抜け目なく、技術的負債を管理することに興味を持たなければなりません。重要ではないコードを美しくすることで時間を無駄にするのを避け、コード品質を改善する有意義なビジネス上の決定をするために、チームは何ができるでしょうか?

「何もしない」や 「コードがこれ以上メンテナンスできないならば、新しく開発する」というような粒度の粗い主張は役に立ちません。

私たちは、この記事で、複数のプロジェクトですでに役に立つと認められている、2つの見込みあるアプローチを考えています。

  • 技術的バックログ
  • 要求の見積もりに技術的負債のコストを含む
  • それ以前に、あるプロジェクトの内容ではおそらく当然だと思われる他の2つの重大なプロセスについて議論したい
  • リファクタリングのためのバッファタスク
  • クリーンアップリリース

技術的負債の議論で常に扱われる質問が1つあります。技術的負債は必ず支払わなければならないのでしょうか? Frank Buschmann氏は3つの戦略を述べています。これについては後で取り上げます。

  • 負債の返済
  • 負債の転換
  • 利息支払いのみ

バッファタスク

チームは、例えば、使用可能時間の10%をリリース毎に1バッファタスクにします。チームメンバは、まだスケジュールされていないリファクタリングに、そのタスクを当てて時間を記録できます。つまり、バッファタスクは、将来現れるかもしれない未知の問題のために使われます。そのようなバッファは、とても簡単にスケジュールを決めて、利用できます。しかし、重要ではない作業のために、時間を無駄にするリスクを引き起こすこともあります。このバッファは、時間が役に立つリファクタリングに使われるかどうかをよく考えるように誰かを強制するものではありません。開発者たちは、ただバッフアタスクに自分たちの時間を記録します。本当はビジネス的な決定であるけれども、特にどのリファクタリングをするか決めることに関して、おそらくバッファの時間は最適な状態で活用されていないかもしれません。バッファタスクを使うことは、残念ながら何をすべきか、本当に決められてはいないことを意味しています。

クリーンアップリリース

時々コードベースを改良するために、純粋な技術的リリースをするチームがあります。このアプローチは、本当に必要なリファクタリングのリストがすでにある場合にのみ役に立ちます。それ以外は、チームは重要ではないリファクタリングのために時間を無駄にするリスクを負います。このアプローチは新しい機能が遅れるかもしれないので、ビジネス側のサポートを得られなければなりません。それには、もちろん、ビジネスの人たちが技術的負債を理解している必要があります。大きな労力が必要になるならば、コードベースをクリーンにして、アーキテクチャを再構築するために、純粋な技術的リリースを考えるべきです。例えば、コードの同じ部分が、開発中や運用中にいつも問題を引き起こすかもしれません。今のアーキテクチャは、今の要求にもう合っていないのかもしれません。そのような問題は小さなリファクタリングでは解決できません。クリーンアップリリースは大きな変更を可能にします。

沢山の技術的負債を作り出した、非常に慌ただしく、緊急を要するリリースの後で、クリーンアップリリースをすることは考えにくいことです。新しいコードベースにわずかな経験しかなく、コードのどの部分を改善する必要があるのか誰も言うことができせん。それほど改善の必要がないコードを変更するのは危険です。

技術的バックログ

技術的バックログは、純粋に技術的作業のパッケージを定義するのに、確立されたもっとも良いプラクティスです。この目的のためのタスクは、タスクトラッカーや要求管理ツールで作られます。各タスクは、なされるべき技術的変更や、この技術的変更がプロジェクトにとって重要な理由や、コードのどの部分に技術的変更をするべきかについて、簡単に記述されています。他のタスクと同様に、私たちは、十分良い解決策を開発するのにどのくらい時間がかかるのか見積もる必要があります。さらに、私たちはこのコード本来の利息を評価しなければなりません。正確な見積もりは難しいでしょう。それでも、「小」、「中」、「高」のような粗い見積もりは、決定を導く役に立ちます。最後に、それほど遠くない将来にこのコードを読んだり、変更したりすることがあるのか、私たちはその確率を知る必要があります。

このアプローチはいくつか有利な点があります。

  • 技術的負債が目に見えて、誰にでもはっきり分かるようになります。見積もられた労力と将来のコードの変更の影響に基づいて、リファクタリングタスクを実施すべき場合は、満場一致で決定されます。
  • タスク毎のコストは簡単にトラッキングできます。
  • 技術タスクと機能タスクが混ざることはありません。
  • しかし、このアプローチはいくつか不利な点があります
  • 顧客はバックログを決めて、タスクの優先順位付けをしなければなりません。顧客はソフトウェアについて詳しい知識を持っていないので技術タスクの価値を決められません。そのため、技術的なことに関して、顧客はある程度のことしかできません。
  • さらに、顧客は、純粋な技術タスクに関するビジネスの利益を本当に理解していないかもしれません。多くの場合、顧客に関係する機能がない技術タスクが、本当に必要なのか疑っています。

私たちの意見では、特別な状況下でのみ、顧客はソフトウェアアップデートのようなことを決定できます。時代遅れのソフトウェアが問題を引き起こすことを、大抵の顧客は知っています。アップデートするべきかどうかは、コスト、リスク、そして、アップグレードの必要性に基づいて個別に決められなければなりません。Javaランタイム環境やO/Rマッパーのようなコンポーネントのアップデートは、通常それほど労力がかからず、定期的に実施していればそれほどリスクもありません。ウェブフレームワークの置き換えやリレーショナルデータベースからNoSQLソリューションへの変更など費用のかかる変更は、かならずビジネス上の理由がなければなりません。アプリケーションのパフォーマンスやユーザエクスペリエンスを改善しなければならないというような理由です。この目的のためにも、技術的バックログは適切でしょう。しかし、そのようなタスクには、どのくらいの労力が必要かによって、別々のプロジェクトにしたほうが良いかもしれません。

技術的バックログは、新しい要求をあるコードベースの中で実装する場合、そのコードベースが新しい要求に合うようにデザインされていなければ、それほど優れたものではありせん。そのような場合、要求を実装する前に、リファクタリングが必要かもしれません。そうするためには、要求の見積もりに対して、リファクタリングの余分な労力を追加しなければなりません。

技術的負債のために労力が必要な要求の見積もり

戦略的デザインは、コードベースすべてをとても良い状態にしなくてもよいことを私たちに教えてくれました。変更することでビジネスの価値をもたらしたり、他の理由で頻繁に変更が必要だったりする部分だけ、良い状態にすればよいのです。だから、技術的負債に関して、めったに変更されないか、決して変更されない場所のコード品質は無視できます。もう1つ重要なのは、コードが正当な理由もなくリファクタリングされるべきではないことです。新しい要求が具体的なビジネスの価値を提供する場合、ひどく書かれたコードに基づいて、この新しい要求を実装するべきではなく、事前にリファクタリングする必要があります。そうすれば、本当に重要な要求が、「十分な」基準で実装されるのです。次のリリースの重要な機能を実装するようにチームに割り立てられたら、リファクタリングの予算をとって、実装すべきです。もちろんそこには、「支払うべきか、支払わざるべきか」のセクションで議論する例外があります。

この手続きにより、不必要な美化作業はなくなり、常にリファクタリングは、直接、要求に関連するようになります。このため、顧客はチームとリファクタリングについて議論して、優先順位を決められます。また、要求が負債と利息に基づいて、実装されるべきかどうか、顧客が決められます。市場に出すまでにかかる時間のように考慮すべき他の要因もあるかもしれません。顧客は、これらの要求に基づいて、コードの将来の変更をすでに知っているでしょう。そこで、将来のコストを省くために、きれいなコードベースへとリファクタリングすることを決めるかもしれません。

チームが実装中にコードベースの問題を見つけた時に、問題は起こります。その時、チームは何をすべきか決めなければなりません。たぶん、約束した機能をすべて持ち、納品日に間に合わせることがとても重要です。それから、技術的負債と利息の支払いがあることを受け入れなければなりません。さもなければ、ひどく書かれたコードに基づいた開発すべてを無駄だと考え、実際の締め切りのプレッシャーをなくします。それから、チームは後でリリースすることになるリファクタリングをスケジュールするべきです。これは、状況に応じ、顧客の必要に合わせて決定されます。

支払うべきか、支払わざるべきか

コードの重要な部分だけを本当にクリーンにしなければならないことを、私たちは見てきました。結局、コードは、必要な時だけリファクタングするべきなのです。しかし、特定のシナリオでどのような解決策が最もふさわしいのかを決めるのは大変です。Frank Buschmann氏は3つの戦略を述べています

  • 負債の払い戻し: 技術的負債だと思われるコード、フレームワーク、プラットフォームをリファクタリングするか、置き換える。
  • 負債の転換: 現在の解決策を「完璧ではないけれども良い」解決策と置き換える。新しい解決策は、より低い利率であり、完璧な解決策を構築すると非常に高価になるならば、よい選択肢かもしれない。
  • 利息のみ支払う: コードとともに生きる。リファクタンリングは、それほど良くないコードに取り組むよりも高くつくから。

開発者と顧客は、コスト、リスク、緊急性に基づいて、このことを決めなければなりません。まとめると、本質的なリファクタリングは、常にビジネス上の決定であるべきです。利息を支払うもう1つの重要な要因は、ソフトウェアの"サポート終了" です。システムがすぐに再開発されるか、終了するならば、リファクタリングする価値があるのでしょうか?

結論

技術的負債は、今日のチームの時間、労力、お金を省く、近道のように見えますが、将来コストを増やすことになるかもしれません。技術的負債は、ソフトウェアプロジェクトで完全には避けられません。しかし、適切に扱えば、必ずしも悪いことではありません。

ただし、適切に扱うのは難しいでしょう。悪いコード品質が将来の要求に与える影響を予測するのは、難しいか不可能でしょう。しかし、技術的負債を完全に無視すると、ソフトウェアに対して大変悪い影響がありえます。チームと顧客が技術的負債のリスクを適切に扱えば、管理できる状態でいられるでしょう。私たちは技術的負債に対応する様々な方法を示してきました。これらの選択肢はそれぞれ、特定の状況化で使われるべきです。そして、重要なのは以下のことを受け入れることです。

  • 技術的負債が常にあること
  • 技術的負債が常に悪い訳ではないこと
  • そして、技術的負債はすべての場合に完全に支払わなければならないものではないこと

どんな支払いでも、ビジネス上の決定であるべきです。支払いがあまりにもわずかで、顧客との相談が必要ないように思えても、コードの改善が本当に投資した時間と労力を正当なものにするかどうか、開発者は常に自分自身に問いかけなければなりません。

著者について

Sven Johann氏はTrifork Amsterdamでソフトウェア開発者として働いています。Sven氏は、ペアプログラミング、TDD、スモールリリースなどのXPプラクティスを熱心に使っています。現在は、TriforkのQTIエンジンを用いて、スイスとオランダの学校でオンライン評価ソフトウェアを開発しています。

 

 

Eberhard Wolff氏は、ドイツのadesso AGのアーキテクチャとして、また技術マネージャとして働いています。Eberhard氏が注目しているのは、Java、クラウド、そして、ソフトウェアアーキテクチャです。また、国際会議に定期的に関わり、何冊もの本や記事を発表しています。

この記事に星をつける

おすすめ度
スタイル

BT