"技術的負債"論の道案内 - アーキテクチャの資本コストと情報の非対称性 #技術的負債 - Qiita
分析結果
- カテゴリ
- IT
- 重要度
- 63
- トレンドスコア
- 27
- 要約
- "技術的負債"論の道案内 - アーキテクチャの資本コストと情報の非対称性 #技術的負債 - Qiita 705 いいねしたユーザー一覧へ移動 486 X(Twitter)でシェアする Facebookでシェアする はてなブックマークに追加する more_horiz 記事を削除する close 一度削除した記事は復旧できません。 この記事の編集中の下書きも削除されます。 削除してよろしいですか? キャンセル 削除する delete inf
- キーワード
"技術的負債"論の道案内 - アーキテクチャの資本コストと情報の非対称性 #技術的負債 - Qiita 705 いいねしたユーザー一覧へ移動 486 X(Twitter)でシェアする Facebookでシェアする はてなブックマークに追加する more_horiz 記事を削除する close 一度削除した記事は復旧できません。 この記事の編集中の下書きも削除されます。 削除してよろしいですか? キャンセル 削除する delete info この記事は最終更新日から5年以上が経過しています。 19日目 モチベーションクラウドシリーズ Advent Calendar 2019 @ hirokidaichi ( 広木 大地 ) in 株式会社Rector "技術的負債"論の道案内 - アーキテクチャの資本コストと情報の非対称性 技術的負債 705 最終更新日 2019年12月19日 投稿日 2019年12月18日 はじめに ソフトウェアと組織経営をめぐる問題で避けては通れないのが、「技術的負債」と言う言葉です。一般には、「早さ」を求めて構築されたシステムの構造的な課題が、徐々に蓄積し、債務であるように徐々に開発速度そのものを遅くして行くと言う現象のことを意味しているように捉えられます。 これは、技術組織を持つ経営者や、ソフトウェアエンジニアではない発注者にとっては理解しにくいものです。またソフトウェアエンジニアであっても「古くなってしまったコード」や「わかりにくコード」全般のことを技術的負債と呼び、それをもって何かを説明したかのように考えてしまうことはままあります。 これらに起因して、双方のコミュニケーションが破綻してしまうこともよく見られる景色です。 技術的負債の経済効果は毎年マイナス12兆円 このような構造的な問題をはらむ技術的負債は、老朽化したレガシーなシステムとして、事業の組織改革を遅らせてしまいます。 経済産業省 - DXレポート によると、2025年以降、毎年12兆円という負の経済効果をもたらすと試算されています。 これは、3兆円から4兆円と呼ばれる東京オリンピックの費用の3~4倍の金額で、毎年オリンピックを4回こなせるほどのムダが、レガシーなシステムによって生まれているということです。なかなかの衝撃的な数字です。 これらは耳目を集めるホラーストーリーではあるものの、「技術的負債」という言葉をめぐる議論は、前提や定義が揃っていなかったり、目的なそろっていなかったりと空論が展開されがちです。 本論では、まず巷にあふれがちな「技術的負債」論を整理するため、過去の議論をまとめていき、技術的負債に関する論についての出発点を揃えることを目的としています。 技術的負債をめぐる議論 技術的負債と言う言葉は、アメリカのコンピュータ技術者であるウォード・カニンガムによって、1992年に提唱された概念です。その言葉は瞬く間に流行し、システムとビジネスを繋げる用語としてもてはやされました。彼は、経験レポートの中で次のように語っています: 最初のコードを出荷することは、借金をしに行くのと同じである。小さな負債は、代価を得て>即座に書き直す機会を得るまでの開発を加速する。危険なのは、借金が返済されなかった場合である。品質の良くないコードを使い続けることは、借金の利息としてとらえることができる。技術部門は、欠陥のある実装や、不完全なオブジェクト指向などによる借金を目の前にして、立ち尽くす羽目になる これは、ソフトウェア開発が段階を得るに連れて、それまでの構造によって機能追加が徐々に困難になって行く様子を見事に言い表してくれました。 ソフトウェア開発において、初期設計通りにプロダクトが成長していくことは少なく、多かれ少なかれ、次第に初期設計からの逸脱を要求されるようになります。 このような状態のプロダクトへの追加開発は、中身を知らない人々から見たときの予想に反して、時間のかかるものになってしまいます。本来はこのくらいでできるはずだと予想しているのに、時間がかかってしまうというソフトウェアの中身を知らない人々の感覚と、実際にソフトウェアを書いている人々にとって必要な作業との時間感覚に差が生まれることになります。 このような認識の差は、しばしばエンジニアの能力的な問題ではないかとか、努力の不足ではないかと言う邪推を生み出し、多くのハレーションが現場レベルで引き起こしています。 そんな中で、カニンガムの提唱した「技術的負債」という概念は、現場で働くエンジニアにとって、「我が意を得たり」という気持ちにさせる表現だったことは間違いありません。そして、この言葉は、エンジニアと非エンジニアのコミュニケーションのための言葉として、あるいはその現象の説明として使われ始めました。 こうして、「技術的負債」という言葉は、システム開発を進めるにつれて引き起こされる開発時間の増大という「現象」を巡って、それらを議論するためのコミュニケーションの言葉として広く使われることになりました。 しかし、「技術的負債」という言葉は、会計上も経営指標においても、計上されるわけではない空想上の概念に過ぎません。 「技術的負債」という言葉の定義も曖昧で、何をもって技術的負債ということができ、何を持って測定され、どのような返済手段があるのかといった議論も尽くされることなく、広く用いられるようになっていきます。 その結果、「技術的負債」という言葉の存在で何かを説明したと思い込む人々や、ソフトウェア開発における経営上の問題について関心を抱かない経営者によって、「技術的負債」という言葉は、むしろコミュニケーションを断絶する言葉になってしまっているケースがあるように思います。 そもそも「負債」という言葉は、どのように解釈されているのでしょうか。経営者ではない多くの人々にとって、「放っていてはいけない」「定期的に返済すべきもの」として、負債という言葉が用いられています。これは、日常的な家計の理解における「借金」と同じようなものだと考える人が多いのではないでしょうか。 ところが、経営者にとっての「負債」という言葉には、資本としての意味合いもあります。事業拡大を考えるにあたって、利子率が低い借り入れであれば、事業拡大において有利になるので、できるかぎり多く借り入れたいという心理も存在します。経営者にとっては、負債を多く借り入れることができることは、信用度の高さを意味していて、決して「借金」という日常語的な理解よりもポジティブな意味合いを見出しています。 このように、負債というアナロジーから抱く印象はそれぞれによって大きく異なるため、コミュニケーションが分断される恐れがあります。このようなアナロジーによる誤解が存在する中で、「技術的負債」だから解消しなければならないという主張は、空転してしまうこともあるでしょう。 不可解な開発速度の低下 まず、論点を整理するために、「技術的負債」という言葉が説明しようとしている「不可解な開発速度の低下」という現象について考えていきましょう。 このような現象は確かに存在しています。これは、システム開発というものが、「何かをできる機能を作る」ということと同時に、「何かできないところを作る」という作業であると言う理解が必要不可欠です。システムを開発する過程で、「ここは変えることがあまりないだろう」という部分を固定的に作り、「ここはよく変わるかもしれない」という部分を変動的に作るというのが、システムの設計作業です。 これは、ソフトウェア開発をやったことがない人にとっては、なかなかイメージしにくいかもしれません。開発初期においては、今まで積み上げてきたシステムもなく、単純な機能であることが多いので、新機能の実装も比較的簡単に行うことができます。 しばらく開発を進めると、同じような要求をしているつもりでも、「時間がかかる」ようになります。今まで開発してきたシステムが、逆に制約となって考えないといけない範囲が広がるからです。 仮にソフトウェアの複雑性に関する式が、指数関数 C = A*exp(Kx) で表現できると仮定します。システムの構成要素が増えるほど、相互の関連性が増えていくため、あながちズレた表現でもなさそうです。ここに開発初期と開発後期で「同じ数」だけの機能開発を行うとします。実際には、ソフトウェアには同じ開発というのはありませんから、仮想的な数字です。たとえば、ファンクションポイントを想定してもらえるとよいかもしれません。そうすると、機能開発には「複雑性」と「機能数」がつくる面積だけの開発工数が必要になります。初期の開発工数に対して、後期の開発工数が大きくなっていることがイメージできると思います。 もう少し、想像をしやすく表現すると、システム開発が徐々に困難になって行く理由は、パーティゲームの「ジェンガ」のようなものです。 ゲーム初期段階でのジェンガは、簡単にブロックを抜き出したり、積み上げることができます。このとき、ゲームはスピーディに進んでいきます。ところが、ゲームをしばらく続けると、バランスを取るのが急激に難しくなっていき、テンポがゆっくりとなっていきます。慎重に抜き差しをしないと崩れてしまうためです。 様々な要件の変化によって形作られたジェンガは、徐々に不安定に、積み上げるのが難しく時間がかかるようになります。これが開発が遅くなる現象とよく似ています。 このように、システムを連続的にアップデートしながら作っていくときには、中身を知らない人からみると予想外のタイミングで、予想外の形で開発が進まなくなると言う現象が発生します。 中身を知っている人からすると、このようにシステムが徐々に新規開発をしづらくなっていくことが見え始めると、この複雑なシステムの構造を整理して、現状よりも高く積めるように変化させていきたいと考えるようになります。 そのためには、一度、機能を変化させない形で、中身の構造だけを将来像に合わせて再構築したいという風に考えます。このときに、経営者に対して、「技術的負債が溜まっていて、返済しないといけない」というようにコミュニケーションをとるのです。 しかし、技術的負債という現象のイメージを抱きにくい経営者にとっては、「機能を追加しないけど、障害が発生するリスクを背負って、時間を使いたい」という要求は、理解が難しく、また適正であるか判断することができないため、「とりあえず全て受け入れる」か「よくわからないので拒否する」かの二択になってしまい、フラストレーションを貯めることになりかねません。 コミュニケーションのための分類 このように「技術的負債」という言葉が、コミュニケーションの起点になったというところは評価をしつつも、具体的なレベルにおいて、技術者と経営者のコミュニケーションのツールとはなり得ませんでした。 その点から、高名なソフトウェアエンジニアのマーティン・ファウラーは、自身の記事「技術的負債の4象限」(TechnicalDebtQuadrant)の中で「何が負債であるか」という議論をするよりも、「技術的負債」になりうる要素がどのように生み出されたのかによって、マネジメントの手助けになるような議論を進めることに意味があると考えました。 「負債」の借入において重要なのは、元本どころか利息に関しても返済の見込みのない借入をしないことです。無鉄砲に、あるいは無意識のうちに借入をしてしまうことはマネジメントに悪影響を及ぼします。 (マーティン・ファウラー, https://martinfowler.com/bliki/TechnicalDebtQuadrant.html , 2009) このような観点から、「無鉄砲な/慎重な」「意図的な/無意識の」という2つの軸を掛け合わせて、技術的負債の4象限を定義しました。 重要な点は、慎重かつ意図的に作られた負債であれば、問題なく返済することができるだろうと考えた点です。一方、無知や無鉄砲さから生まれた技術的負債は、予想しない利息を支払うこととなり、問題が大きくなってしまうため、避けるべきであるとしています。 1つ1つの問題がなぜ生まれたのかを検討することで、避けられるべき問題を避け、解消すべき問題をあぶり出そうとしました。 このことは、次のような考えを生みます。後の負債になることを意識的に理解して、慎重に行えば「開発を早くすることができる」し、後の負債になることを避けようと思えば、「開発時間を長くすることで回避することができる」という考えです。 果たしてこの考えは、正しいのでしょうか。 クイック&ダーティの神話 「技術的負債」という言葉の背景に隠れた前提にあるトレードオフとして、コードを書く上で、「綺麗さ」と「速さ」は交換可能であるというものがあります。これは「速い」と「汚い」を合わせて、クイック&ダーティに作るというような慣用句と共に用いられます。 あるコードが、のちのち開発出力の遅滞を引き起こすような「技術的負債」になるかどうかを判別することは非常に難しいものです。ましてや、経営的な要求に合わせて、与えられた開発期間から柔軟に汚さと速さを選択すると言うような器用な芸当はほとんど不可能だと言えます。 これは、極めて基礎的なところであれば多少はできるかもしれませんが、実際には、ソースコードが汚くて遅い人もいれば、綺麗で速い人がいるということの方が多いと言えます。 そして、プロダクトの開発とは、継続的にさまざまな市場の不確実性を考慮して要件が変わって行くものです。それをあらかじめ予見して、このコードは負債になるとか、このコードは負債にならないとか、そのような点を設計に盛り込むというのは実質不可能です。 これは、負債として理解しておけば、汚いコードを書いても良いというわけではなく、その時できるかぎりの良いコードを書く重要さを表しています。 一般に考えられている綺麗なコードというものは、その要件を実現するのに適切なシンプルな構造をしているコードです。それに対して、汚いコードというのは、複雑で整理されていないコードのことを意味しています。 綺麗でシンプルなコードは、のちのち「技術的負債になりにくい」という性質を持っていることが多いのですが、汚いコードというものは、複雑であるがゆえに、全体を読み解くことがむずかしくなってしまい、「技術的負債になりやすい」という性質を持っています。 将来的に技術的負債になりにくいコードというものは存在していても、技術的負債にならないというコードが存在するわけではありません。予想外の機能追加や、ビジネス目的の方針転換、人員数の増加などさまざまな外的要因によって、技術的負債というものが蓄積されやすくなります。 開発者がその時点ですべきことは、YAGNI原則(you ain’t gonna need it )に代表されるように、「今必要な機能をシンプルに作る」ことで、あって将来的にシンプルであり続けると予測し、アーキテクチャを組むこと自体が、技術的負債の材料となる複雑性をシステムに組み込んでしまうことになります。 「シンプルに作るのか、複雑に作ってしまうのか」はトレードオフにはなりません。これはプログラマーの思考過程のシンプルさと複雑さの問題であって、時間をかけたからシンプルになるという性質のものでも、時間をかけなかったから複雑になるという性質のものでもありません。 このように、そもそも「クイック&ダーティ」というトレードオフというものが成立するのかというのは常に考えの中に入れておく必要があります。 技術的負債は「見ることができない」 このような「技術的負債」というアナロジーをめぐる議論の中で、フィリップ・クルーシュテンは、技術的負債をより具体的に定義するためにマーティン・ファウラーとは別の次のような4象限を定義しました。 「見える/ 見えないの軸」と「プラスの価値/マイナスの価値の軸」の2つによるマトリックスです。 (クルーシュテン、2012) これは、内部構造を見ていない人にとって理解することのできない要素のうち、プラスの価値のあるものをアーキテクチャーといい、マイナスの価値になるものを技術的負債と定義したものでした。 この観点は、技術的負債がアーキテクチャと対になる要件であることを示しており、その特徴をよく表していると言えます。 「見ることができない」という非対称性 クルーシュテンの指摘するところの、「見ることができない」とはどういう意味なのでしょうか。本当に見ることができないのであれば、アーキテクチャもまた見ることができないので、修正も構築も不可能だということになります。 ここでいう「見ることができない」は、表面的な機能から発見することができないということを意味しています。ソースコードの中をじっと然るべき人が見れば、読み解くことができるが、システムの表面的な機能だけを見ていては、知りうることができないということだと解釈できます。 システムに関して、エンジニアと非エンジニアの視点は違います。それは、CTスキャンされた図像で人体を見ているか、肉眼で表面的に見ているかというくらいに違います。非エンジニアは外側から見たシステムの様子しかうかがい知ることができません 一方、エンジニアからはCTスキャンを通すように内部の構造を理解しています。であるからこそ気がつく病魔の兆候も、非エンジニアには伝わりません。 「技術的負債」というアナロジーが、経営者とエンジニアのコミュニケーションのために有用だと考えられ、生まれたのにもこのような非対称性が背景にあります。 つまり、この「見える/見えない」という情報の非対称性が、技術的負債が問題になる最大の理由だと考えることができます。 理想システムの追加工数との差による表現 技術的負債をめぐるもう一つの重要な観点として、クラウス・シュミットによる数学的定義が挙げられます。それは次のような数式です。 これは、技術的負債は、機能追加時の2つのシステムの工数(コスト)の差で表現できるのではないかという考え方です。1つは現状のシステム、もう一つは「理想的なシステム」です。それぞれにある機能eを追加しようとしたときに、かかる工数に差が生まれ、それが技術的負債の単位だとするものです。 たとえば、ある機能を追加する時に50人日かかるシステムが、もし理想的な場合は20人日で済む場合、差の30人日という逸失コストが技術的負債を表しているというもので、技術的負債という言葉をあらたな観点で説明するものでした。 この考え方は、技術的負債が実体として何者であるかどうかというのを問わないという点で、画期的な考え方だと言えます。表面上表出するコストの差だけで表現できるため、経営的観点との結合のしやすさにも価値があります。 また、「技術的負債TD」というものを知るには、かならず「付け加えたい機能e」が必要であるという観点も重要な示唆を持っています。何も手を加える必要のないシステムの技術的負債は、「0」です。技術的負債とは、システム単独で成立しているわけではなく、新たに追加したい機能があって、初めて成立する観念だとわかります。 この考え方を使うと、「技術的負債の総量」は理想的なシステムというものを具体的にしないとわかりませんが、「技術的負債への対策」にどの程度のコストを費やしても良いのかということは考えることができます。 たとえば、あるシステムSに{ e1, e2, e3 }という機能追加をしていきたいと考えたとしましょう。このとき、機能追加の見積りをそれぞれおこなったところ、e1に30人日、e2に50人日、e3に60人日かかるということがわかりました。 ところが、あるエンジニアが技術的負債を返済したいと申し出、それには一定のコストが必要だということを提案してくれました。 このコストが適切であるか捉えるために、「技術的負債の返済策」を施したシステムS’に対して、{e1,e2,e3}の機能追加を行なった場合の見積りを依頼しました。 すると、e1に25人日、e2に35人日、e3に40人日であることが判明しました。図にすると以下のようになります。 それぞれに費やされるコストを足し合わせると とわかりました。 このように計算することで、「技術的負債の返済策」のコストが、40人日以下であれば、合理的な決断であると考えることができ、判断を行うことができます。 しかし、この考え方も限定的な合理性になる可能性があります。それは、プロダクトオーナーにとって「e1の機能追加後の仕様変更オプション」の価値が非常に高いというケースです。 この想定シナリオでは、技術的負債を返済するケースにおけるe1のリリースは、x+25人日を費やしたあとになります。一方、元々のケースであれば、35人日を費やした時点で、このオプションを行使することができます。 このようにトータルコストの削減が、最も合理的でないというケースはプロダクトマネジメントにおいては、発生しやすい問題です。しかし、具体的な数字を持って「技術的負債」に肉薄できるという点で、メリットも多い考え方です。 アーキテクチャの資本コスト シュミットの「工数の差」によって表現される「技術的負債」は、便利であったものの、その「負債」というメタファーが持つ、蓄積され、徐々に効率が悪くなるという特性をあまりうまく表現できてはいませんでした。 システムは、機能追加するごとに複雑性が増していきます。それにともなって、機能追加へのコストが増大します。このようなイメージを表現するために「これまでに費やされた工数」に対して、一定割合、負の価値を持つアーキテクチャが作られるとしましょう。 カニンガムの定義どおり、ソフトウェアの機能追加を「借入」として捉え、それに対する「資本コスト=利子」をシュミットの定義する「開発工数の差」として考えるとその関係がわかりやすくなります。システムは、開発するごとに複雑化していくので、その複雑さが利子として、「開発工数の差」を生み出していくとする考え方です。 たとえば、次のようなケースを考えてみましょう。開発人員を徐々に増やしていったチームがあったとします。それに対して、累積工数の4%が次の機能追加をするための利子として取り立てられ、それが開発出力を低下させます。 このシミュレーションにおいては、開発人員を追加していっても徐々に開発出力が伸びにくくなっていくことがわかります。 これは、「システムの複雑性の増加」と「開発出力」の関係性はうまく表現できています。しかし、この利子率ないし資本コストが何によってきまるのかはうまく表現できていませんでした。 シュミットの定義は、この穴を埋めてくれます。彼の数式の意味する技術的負債は、負債というよりもむしろ「資本コスト」として捉える方がわかりやすくなります。 アーキテクチャの資本コストは、現実には、様々な利子率の資本の組み合わせとしてポートフォリオを組んでいます。 具体的な例で考えてみましょう。ここに、4つのサブシステムA,B,C,Dによって作られているプロダクトがあったとします。 それぞれに対して、それまでに費やした累積工数を算出し、今後予定されている機能の見積りと、アーキテクチャのリファクタリングを行なった場合の見積りを算出します。その差分をとり、累積工数で割ると各サブシステムの利子率を得ることができます。また、全体の累積工数に対して、工数差分の合計の割合を見れば、全体の利子率が推定できます。 このようにすれば、今後やっていきたい改善とそれに対するざっくりとした見積りから、アーキテクチャの資本コストを把握することができ、どこからどれくらいのコストをかけて改善していけば良いのかという大まかな判断に使うことができます。 ところで、技術的負債というメタファーが必要とされた背景は、ただ単に「システムの複雑性が増加する」という現象を説明するためだけのものなのでしょうか。そうなのであれば、アーキテクチャの資本コストを決めるシュミットの定義を用い