技術負債ってなんだろう

InfoQに、「技術的負債を解剖する」という記事が出ています。

翻訳したのは、Domain Driven Design Quickly を翻訳した徳武聡さん。
徳武さんとは一緒に仕事をしていますが、頭が速くて手も速く、good senseです。
SEマネージャからみて、とても頼りになるエンジニアです。

数ある翻訳候補の中から、「技術的負債を解剖する」を選ぶところも、なかなかgood senseです。

—-

そもそも、「技術的負債」というのはワード・カニンガムがメタファーとして作ったものだとのこと。
マーチンファウラーのBlikiから引用すると

「技術的負債」とは、Ward Cunningham が作ったメタファーである。上記の問題について考える際に、この言葉が役に立つ。このメタファーを使うと、早いけれど汚い解決方法は(ファイナンスの負債と同じく)技術的な負債が発生する、ということになる。 通常の負債と同じく、こちらの負債も利子を払う必要がでてくる。 早いけれど汚い設計を選んだせいで、将来の開発において余分な労力をさかねばならなくなる、というわけだ。 これからずっと利子を払いつづけていくことも可能だし、 リファクタリングによって良い設計に修正し、元本を減らしてしまうということも可能だ。 もちろん元本を減らすのにはコストがかかる。だが、それによって将来かかる利子が減るため、結果的には得なのである。

ということです。SEであれば、多少なりとも身に覚えがあると思います。

これについて、マーチンファウラーの分類では技術負債は4つに分類されるとのことです。

  1. 無鉄砲 - 意図的 – チームには設計をしている時間がない。品質を犠牲にして、汚くても素早くソリューションを提供する必要がある。
  2. 良識的 - 意図的 – チームは今すぐ製品を出荷しなければならないが、その製品には既知の欠点がある。発送した結果が招く問題についても先手を打っておく。
  3. 無鉄砲 - 偶発的 – チームは基本的な設計原則について意識していない。なので混乱状態が生まれつつあることにも気付いていない。
  4. 良識的 - 偶発的 – 確かに優秀な設計者がいて、その設計者はビジネス価値を生み出すソリューションを納品する。しかし、ソリューションが完成した後になって、最良の設計手法が何だったのかを理解する。

このような内容になっています。
これらについて、経験から少しどんな時こうなるのかを考えてみます。

「無鉄砲で意図的」な技術負債

「設計なんてしないで、品質を犠牲にして素早くソリューションを提供する」状態とはどんな時なんでしょう?
例えば、「納期が間近に迫っているが、どうしてもやらなくてはいけない」時。このような場合には、それまできちんととやっていれば、技術負債はそこだけで済む。
しかし、「プロジェクト自体がそもそも無理」な場合にも、このような事態は発生する。
マネージャ自身が「設計なんていいから、とにかく、コードを書け」なんて方針になってしまって、結果的に技術負債のかたまりのようなソフトウェアを作ってしまう。
そんなパターンですね。ここまでいくと、正しく動く方が奇跡?のような状態になるので、そのためにまた汚いコードを上塗りすることになってしまいます。

「良識的で意図的」な技術負債

「その製品には既知の欠点がある。発送した結果が招く問題についても先手を打っておく」っていうのはどういうことでしょう?
例えば、既知の欠点について、マニュアルに記述し回避方法を示しておくとか。(マニュアルで逃げるというやつですね。)
「既知の欠点があるが、十分によくできていて、運用可能だから出荷する」と言う状態です。
この場合はやはり「良識的」なので、既知の欠点があっても、よく品質は確保されている状態です。
既知の欠点が山ほどあって、直しても直しても減らないような状態ではありませんね。

「無鉄砲で偶発的」な技術負債

「チームは基本的な設計原則について意識していない。」というのはさすがに無謀ですね。
たとえば、レイヤリング方法や、ネームスペースの名前付け方針、ライブラリの使い方や準備、そういった開始前の準備タスクを怠ってスタートしている場合が該当しそうです。
「混乱状態が生まれつつあることに気づいていない」ということは、メンバー間のコミュニケーションもあまり取らずに勝手に作業を進めている感じですね。
正直、かなりワルですね。

「良識的で偶発的」な技術負債

「ソリューションが完成した後になって、最良の設計手法が何だったのかを理解する。」は、ファウラーが書いたDDDの序文にあることだと思います。

Another lesson you’ll learn from this book is that domain models aren’t first modeled and then implemented.
Like many people, I’ve come to reject the phased thinking of “design, then buld.”
But the lesson of Eric’s experience is that the really powerful domain models evolve over time, and even the most experienced modelers find that they gain their best ideas after the initial releases of a system.

他の教えでは、あなたはドメインモデルは初期モデルで実装されることはないことをこの本から学ぶでしょう。
大多数の人のように、私は「設計し、そして構築しなさい」という段階的な考えを拒絶するようになっている。
しかし、エリックの経験からくる教えは、長い時間をかけて、本当にパワフルなドメインモデルを考え出す。
そして、熟練したほとんどのモデラーでさえもが、システムの初期リリースの後に彼らの最良の考えを発見する。

この辺ですかね。実際、熟練したエンジニアが設計しても、リリース後にもっとよい設計手法が見つかるものだということです。

エンジニアは最初からドメインのプロであるわけではありません。

スペシャリストからの知識を噛み砕き、ドメインモデルを構築し、システムを構築する。
そしてファーストリリースをした後に、そのドメインについての知識が深まったことに気づき、最良の考えが他にあったことに気づくわけです。

—-

こうして見てみると、「良識的なもの」と「無鉄砲なもの」で、かなり差がありますね。
「良識的なもの」は、最後つじつまをうまくあわせるために、技術負債で穴埋めする場合もありますよという感じです。
あるいは、「技術負債なし」で作ってきたつもりでも、実はドメインの知識が深まると、技術負債に気づく場合もありますよ、ということでしょう。
「無鉄砲なもの」は、まさに「無知は罪」という感じです。こんな仕事をするのは、本当に罪深いことです。
後の面倒を見るエンジニアは、本気で「自己破産」を考えなくてはなりません。

徳武さんとも話したのですが、「無鉄砲」の元の単語’reckless’は、かなり「悪い」においがします。
「無鉄砲」というよりも「無茶」とか「滅茶苦茶」とか、もっと「悪い」単語の方が感覚的には合う気がします。
もっとも、この文書の翻訳ではそんな単語はちょっと使えそうにはないので、他にいい言葉は見つかりませんでしたね。
(お行儀の悪い言葉なら、いくらもありますが。ファウラーも’reckless’が精一杯だったのでしょう。)

私の現場は、冒頭に書いたように徳武さんがgood sense(良識的)なおかげで、変な技術負債は少なくて済んでいます。

でも、徳武さんが来る前にこさえた借金はたんまりあるんですけどね。
いつも借金払わせてばかりで、どうもすみません。

模様替えしてみました

ブログのテーマを変えてみました。
やっぱりこういうシンプルなものが好きですね。

「オブジェクト指向発想」の目覚め

増田さんの「手続き的な発想、オブジェクト指向的な発想」を読みました。
オフィスでも、勉強会でこのことについて話しました。

話をして思い出したのは、昔金融コンサルと組んで、金融機関の収益シミュレーションシステムを作っていた時のこと。

—-
最初はスプレッドシートでマクロを組んでやっていた。
でも、結構壮大なシミュレーション仕様で、一回実行すると一時間以上返ってこなかったりした。
当時のPCとスプレッドシートでは荷が重いことがわかった。

で、UNIXサーバでCで組むことになった。

このころは増田さんが言っているような、

ネットワーク(ノードとエッジ)構造を扱うプログラムを、C 言語でうまくかけて実践できたときは、「オレすげー」と思ったのを思い出します。

そのために、ループ構造、関数呼び出し、再起呼び出しなどを駆使して、メモリ上のデータ操作の手続き記述に、どっぶりはまっていた。

なんて時代です。「オブジェクト指向」という言葉はありました。
たとえば、技術評論社のSoftwareDesignなんかでは、「オブジェクト指向って何がいいのか」なんて記事が書かれていたような時代。
日経コンピュータあたりでは、「業務アプリにはオブジェクト指向なんて不要。データ中心アプローチでやり直しちゃったよ」なんて記事が書かれていたような時代。
まだ、実際の開発現場で市民権を得る前の話ですね。

何せ、仕様の元がスプレッドシート+マクロなので、構造体を使って大きなメモリイメージを作り、それに対して手続きを書いてまたメモリに壮大に展開していくようなプログラムを書いていた。

シミュレーション仕様は金融コンサルとエンジニアで一生懸命考えた。
金融コンサルの頭の中は基本スプレッドシートで考えられていて、私たちもそのイメージを一緒に共有して考えた。
当然、オブジェクト指向なんて考えはどこにもなくて、すごく手続き的に考えられていた。

で、実際作ってみると、思ったような「いい数字」が出ない場合が多かった。なにせシミュレーションなので、実際の動きをモデルに、ある程度簡略化した計算をしていた。
そのため、実際こうはならないだろうという数値が出る場合がある。そんな時は、また金融コンサルと一緒に新仕様を考えた。
また、実際のデータとシナリオが合わない時や、ユーザの計画方法が無茶な場合もいい数字は出なかった。
そんなときも、実際にプログラムで「いい数値が出るように」合わせに行った。

大変なのはこういう時で、時折とんでもない仕様変更になる場合がある。もとのデータ構造が変わり、精度が変わり、計算方法がガラッと変わる。
当時の作り方では、こんな変更に耐えられるだけの保守性は持ち合わせていなかった。「ほとんど書き直さないとダメなんですけど。。」という感じだ。

仕事としてやりがいはあったけれども、このころはやっぱり大変だった。夢でメモリイメージと手続きが出てきたのもこのころだ。
UNIXサーバのメモリ一杯に広げられたデータと手続き記述の海で溺れていましたね。

—-
これをブレイクスルーできたのは実は何年かたった後。

収益シミュレーションは、実は商品と経済イベント(ex:金利更改があった、手形の書き換えを行う、とか。)と、そこで起こることだけを書いておけばいいんじゃないか?
あるべき結果(いい数字)に向かって処理を羅列していくのではなくて、プログラム的にそういう整理をすれば、保守性高く、スマートにできるんじゃないか?

という発想がやっていくうちに出てきた。

で、実際にそのように書いてみたら、以前よりもずっとわかりやすく、スマートな作りになった。
一緒にプログラムを書いていたC言語の師匠も、その設計に手ごたえを感じていた。

おそらく、これが私にとってはじめての「オブジェクト指向発想」だったと思う。

でも、まだ難関が残っていた。

—-
一緒に仕事をする金融コンサルと、この考えは共有できなかった。
説明もしてみたが、どうやら分かってはもらえなかった。
そのあとも、スプレッドシート+手続きイメージでしか、仕様を考えてはくれなかった。

実は、上司の理解も得られなかった。「イベント?何だそれ」「何でそんな作り方になるの?」と、かなり否定的だった。
当時の私たちには、ここで戦うだけの武器を持ち合わせてはいなかった。

この後は、金融コンサルと考えたスプレッドシート+手続きイメージを、自分たちの経済イベントモデルに置き換えて実装していった。

—-
もう十年以上前の話だが、おそらくこれからもそういうことが起き続けるのだと思う。

業務領域を考える人たちは、ほとんどの人がやはり「手続き的」なものの考え方をしている。
そして、我々にもそういうように伝える。我々はそれを深く理解して、オブジェクト指向発想で設計する。
そして、変更に強いソフトウェアを作り上げる。

ビジネスルールや業務手順なんていうものは、実はあやふやなものなんだとも思う。
エンジニアはそのあたりを誤解していて、すごく固いものだと思っている。(実際に固いところもあるとは思いますが。)

今どきのビジネス書なんかには、「イノベーション」「ルールを変えた者が勝つ」なんて書いてあるわけだから、
むしろ、成長・発展するにしたがって、「変わって当然」「変わらなきゃダメ」なものになってきている。

「オブジェクト指向発想」を使って、保守性高い業務アプリを作ることはすごく価値があることだと考えている。