👻

技術的負債の受け入れ方

2023/11/11に公開

技術的負債について考えるとき、その歴史的経緯や定義を考えていくことも面白いですが、実務的な観点では「それは対応すべき問題なのか?」に答えられるかどうかが大事だと思います。

以降、「この内容は負債にならないか?」を考えるときに気をつけていることを書きたいと思います。

利子は高くつくか?

ソフトウェアの技術的負債の利子には、2種類あるようです。

  • 後続の開発の生産性が下がる(開発効率の負債)
  • 追加のランニングコストがかかる(計算効率の負債)

開発効率の負債は分かりやすく、要は「負債のせいで作りにくくなる」ということです。ここで注目したいところは、その部分が将来の開発において無関係であれば利子は発生しないところです。したがって、技術的負債を解消するかどうかは、その内容ではなく、影響範囲の大小のほうが重要であると思います。酷い負債であっても、将来に渡ってその部分を気にかける必要がないのであれば、許容できるということです。

計算効率の負債は、たとえば「きちんと連想配列を使えば1分で処理が終わるのに、線形探索するから120分かかり、その分の費用が発生する」というものです。計算効率負債は受け入れたり、困ったときは「お金で殴る」解決が取られることがあるかと思いますが、将来データ増大でデッドラインを超えるので改修必須になったり、並列処理ができなくてお金で殴れない場合、負債と向き合うことになります。

返済の必要があるか?

当たり前ですが、技術的負債は自然に消滅しません。ただしミクロな観点では、です。

というのも、事業計画や製品戦略など上位の判断をうけて、技術的負債が存在する部分(モジュール)がまるごと不要になることがあります。YAGNI とか KISS などの原則が教えているとおり、これは想像より発生します。

その場合は負債を返す必要はなく、ソースコードごと捨ててしまうだけです。

この点は技術的負債に対する意志決定で難しいポイントになります。返済しないと利子が発生しつづけるかもしれないが、将来破棄された場合には返済自体が不要な投資になってしまう。したがって、技術的負債を解消すべきかどうかは、それが将来も存続するかどうか(ビジネス的な展望)とセットで検討することが大変重要になります。

返済しやすいか?

技術的負債の解消しやすさは様々です。現実では、単純な金銭の借り入れであれば返済も容易ですが、赤字の不動産であれば売却も容易ではない、といったところでしょうか。

返しやすさについて考えるポイントには2つあります;

  • 影響範囲
  • 前方互換性

影響範囲は自明だと思われつつ、難しいのはシステムの進展を考えて将来の影響範囲を想像しなければならないことです。

技術的負債が生み出されるときの多くは、その部分を新規にコーディングしていますから、それに依存する要素は大した数ではありません。また、まさに注力してコーティングしてときは対象をよく理解しているはずです。これらのことは、将来影響を過小評価しやすくします。

しかし、それが将来の追加機能の基礎要素として使われるようなものであれば、すぐに影響範囲が拡大し、利子が増大しつづけることになるでしょう。このため、影響範囲の想定は仮定に頼らざるをえず人によって見解が異なってしまい、合意形成が難しくなりがちです。

私の経験では、そのようなときソフトウェアエンジニアリングのような原則や専門知識による判断が(外れることがあっても他と比べて)もっとも信頼できると感じますが、それ自体の妥当性が広く受け入れられているとはいえない状況ですので、やはり合意形成の難度は高くなります。

前方互換性については、その負債を解消するときに互換性を確保しやすいか、検証がしやすいかということを考えます。互換性が確保しやすく "返済版" の動作検証が容易であれば、その技術的負債について気にかける必要はありません。

追加の負債を呼ばないか?

金銭的な負債にはない性質ですが、技術的負債が基礎レイヤーに埋め込まれた場合は、それによる二次的な負債が次々と発生します。したがって、その技術的負債が存在するアーキテクチャ上の位置を考慮することが必要不可欠です。

返済規模は許容できるか?

金銭的な負債は100円ずつ返済できる(と思います)が、技術的負債は原則としてまとめて返す必要があります。それ自体とともに、影響を受ける部分も同時に直さなくてはなりません。

このとき、返済期間が1ヶ月を超えるようだと実務としての意志決定が非常に難しくなり、3ヶ月を超えた場合にはビジネス上の理由で返済不能になるような感覚があります。最近は「それは後で直せばいい」という判断を見る頻度が増えていると思いますし、それで合理的である場合もありますが、慎重に判断すべき場面も依然として存在します。

もし返済不能になった場合には、たいていはシステムごと再構築することになるイメージがあります。リファクタリング、ピボット、マイクロサービス化、など聞こえの良いフレーズで飾られることも多そうですが、作ったものは直さず動き続けるのが一番です。


以上、技術的負債について検討するときのポイントを上げてみましたが、そもそも「技術的負債は最初から負債の姿をしているのか」は忘れてはいけないポイントです。

瑕疵は負債ではない

後になってダメだとわかることは誰でも経験があると思いますが、その "ダメ" には負債と瑕疵の両方があります。瑕疵は、要はミス(誤ち)です。

  • 当時、この実装が問題になるとは思わなかった。 → 瑕疵
  • 当時、この実装以外に方法があるとは思わなかった。 → 瑕疵
  • 当時、いまの実装の方が良いと思ったが、結果的に良くなかった。 → 負債
  • 当時、いまの実装は悪いと思っていたが、解決策が分からなかった。 → 負債

負債になる認識が事前にできていれば、(是非は別にして)リリース日と品質のどちらを取るか、どのような制約が将来起きそうか、などを比較検討の上で「負債を抱える」という意志決定を行うことができます。

一方、出来上がったら負債になっていた、いざ変更しようとしたら負債に感じた、というのは技術者としての単なる未熟さではないかと思います。"技術的負債" は、考慮不足や技能不足が原因であることをオブラートに包んで言い換える言葉ではないと思っています。

負債の予見可能性

もちろん、なんでも未来を見通せるわけではありません。ポイントは、当時に問題が予見できて当然だったか(予見可能性があったか)です。

予見可能性の判定は技能水準とセット、つまり「これくらいの技能水準であればこれは予見できるはず」です。たとえばアーキテクトであればアーキテクチャ上の善し悪しについて将来も含めて検討できることが当然だと思いますが、それを2年目のエンジニアに求めるのはナンセンスでしょう。ですから、開発で実際に予見できるかどうかは、人員構成によって大きく変わります。

ただ経験上、基本・王道に反する意志決定は将来ほぼ必ず負債になり、これらを避けるだけで厄介な負債は減少します。たとえばクリーンアーキテクチャのコンセプトは「SOLID原則を満たす」で、それだけで避けられる負債は多数あります。重要な指針は、個別方法論を超えた普遍的な価値観として知られていますから、チームがそれを実践できるかどうかはソフトウェアとシステムの寿命を大きく左右します。

Discussion