https://martinfowler.com/articles/is-quality-worth-cost.html

ソフトウェア開発プロジェクトでよくある議論は、ソフトウェアの品質向上に時間を費やすか、より価値のある機能をリリースすることに集中するかというものです。通常、機能を提供しなければならないというプレッシャーが勝り、多くの開発者がアーキテクチャやコードの品質に取り組む時間がないと不満を持つようになります。

Betteridgeの見出しの法則というものがあります。これは、見出しやタイトルが疑問形になっている記事は「ノー」で要約できるという格言です。私のことを知っている人であれば、私がこのような法則を覆したいと思っていると確信しているでしょう。しかし、この記事はそれ以上のものです、つまり私はこの記事で質問自体を打ち砕きます。この記事のタイトルになっている質問は、品質とコストの間にはトレードオフがあることを前提としています。この記事で私は、このトレードオフはソフトウェアには適用されないことを説明します。つまり品質の高いソフトウェアは実際にはより低いコストで生み出せるのです。

私の文章のほとんどはプロのソフトウェア開発者を対象としていますが、この記事では、ソフトウェア開発の仕組みについての知識を前提とするつもりはありません。私の願いは、この記事が、ソフトウェアの取り組みについて考えることに関わるすべての人、特にビジネスリーダーのような、ソフトウェア開発チームの顧客として行動する人にとって価値のあるものになることです。

私たちは品質とコストはトレードオフであるという考えに慣れている

冒頭で述べたように、私たちは品質とコストはトレードオフであるという考えに慣れています。私がスマートフォンを買い換えるとき、私は高価なモデルを選ぶことでより速いプロセッサ、より良い画面、より多くのメモリを手に入れることができます。もしくは、より安価に手に入れるためにいくつかの品質を諦めるという選択もできます。これは必ず成り立つ法則ではありません。高品質のものが安く手に入ることもあります。多くの場合、私たちは品質に対して異なる価値観を持っています - ある人は、あるスクリーンが別のものよりも優れていることに気づかない人もいます。しかし、ほとんどの場合、高品質なものほどコストがかかるという前提が成り立ちます。

ソフトウェアの品質は多くの意味がある

ソフトウェアの品質について話をする際には、品質とは何であるかを説明する必要があります。ここに最初の複雑さがあります - ソフトウェアの品質として捉えられるものはたくさんあります。ユーザーインターフェースの品質を考慮することができます:すべきタスクをより効率的に簡単に進めることができ、フラストレーションを取り除いてくれるか?また、信頼性について考慮することもできます:エラーやフラストレーションの原因となる欠陥が含まれているか?他の側面としてはアーキテクチャもあります:ソースコードが明確なモジュールに分割されていて、プログラマーが今週作業する必要があるコードの箇所を簡単に見つけて理解できるようになっているか?

これら3つの品質の例は網羅的なリストではありませんが、重要なポイントを説明するには十分です。私がソフトウェアの顧客やユーザであるとして、先に品質として挙げたもののうちの幾つかは評価することができません。ユーザーは、ユーザーインターフェースが良いかどうかを見分けることができます。経営者は、ソフトウェアが社員の仕事をより効率的にしているかどうかを知ることができます。ユーザーや顧客は不具合、特にデータが破損したり、システムがしばらく動作しなくなるようなものに気づくでしょう。しかし、顧客やユーザはソフトウェアのアーキテクチャの良し悪しを知ることはできません。

そこで、ソフトウェアの品質属性を 外部(UIや不具合など)と 内部(アーキテクチャ)に分けてみましょう。ユーザーや顧客はソフトウェア製品の外部品質が高いかどうかはわかりますが、内部品質が高いか低いかの区別はできません。

一見、内部品質は顧客には関係ないように見える

内部品質は顧客やユーザーが見ることのできるものではないので、それは重要なのか?と思うかもしれません。レベッカと私がフライトの遅延を追跡して予測するアプリケーションを書いたとします。私たちのアプリケーションはどちらも本質的な機能は同じで、どちらも同じようにエレガントなユーザーインターフェースを持ち、どちらもほとんど欠陥がありません。唯一の違いは、彼女のソースコードはきちんと整理されており、私のはぐちゃぐちゃであるという点です。もう一つ違いがあります。私はそれを6ドルで販売し、彼女は10ドルで販売しています。

顧客はこのソースコードを見ることはなく、アプリの動作に影響を与えないので、レベッカのソフトウェアに余分な4ドルを支払う人はいるのでしょうか?もっと一般的に言えば、より高い内部品質のためにもっとお金を払う価値がないことを意味しているはずです。

別の言い方をすれば、外部品質のためにコストをかけるのは意味があるが、内部品質のためにコストをかけるのは意味がないということです。ユーザーは、ユーザーインターフェースが余分なお金を払う価値があるほど十分に良いかどうかを評価できるので、より良いユーザーインターフェースを得るためにもっとお金を払いたいかどうかを判断することができます。しかし、ユーザーはソフトウェアの内部モジュール構造を見ることはできませんし、より良いと判断することもできません。何の効果もないものに、なぜお金を払うのでしょうか?それなのに、なぜソフトウェア開発者は自分の仕事の内部品質を向上させるために時間と労力を費やす必要があるのでしょうか?

内部品質はソフトウェアの変更を容易にする

では、なぜソフトウェア開発者は内部品質を問題にするのでしょうか?プログラマーはコードの修正にほとんどの時間を費やしています。新しいシステムであっても、ほとんどすべてのプログラミングは既存のコードベースの文脈の中で行われます。私がソフトウェアに新しい機能を追加したいとき、私の最初の仕事はその機能が既存のアプリケーションのフローにどのように適合するかを把握することです。次に、私の機能がフィットするように、そのフローを変更する必要があります。私は多くの場合、すでにアプリケーションにあるデータを使用する必要があるので、そのデータが何を表しているのか、それが周りのデータとどのように関係しているのか、そして私の新しい機能のためにどのようなデータを追加する必要があるのかを理解する必要があります。

これらはすべて、私が既存のコードを理解するためのものです。しかし、ソフトウェアは容易に理解しにくいものとなります。ロジックが絡み合ったり、データが分かりにくかったり、何かを参照するために使われている名前は、半年前にはトニーには意味があったかもしれませんが、私には彼が会社を辞めた理由と同じくらい謎めいたものであったりします。これらはすべて、開発者が「クラフト」(できの悪いもの)と呼ぶものの一形態であり、現在のコードと理想的なコードとの間の違いです。

内部品質の主な特徴の1つは、アプリケーションがどのように動作するかを簡単に把握できるようにして、どのように機能を追加するかを容易に確認できるようにすることです。ソフトウェアが個別のモジュールにうまく分割されていれば、50万行のコードをすべて読む必要はなく、いくつかのモジュールの中の数百行をすぐに見つけることができます。命名を明確にすることに力を入れていれば、コードの様々な部分が何をしているのか、細かい部分を探らなくてもすぐに理解できます。データがビジネスの言語と構造に感覚的に従っていれば、カスタマーサービスの担当者からのリクエストとどのように関連しているのかを簡単に理解できます。クラフトは、変更の仕方を理解するのにかかる時間を増やし、ミスをする可能性を高めてしまいます。もし私がミスを発見した場合、何が問題なのか、どのように修正するのかを理解しなければならないので、より多くの時間が失われてしまいます。もし私がミスを発見することができなければ、本番環境で不具合が発生し後で修正するのに更に多くの時間が必要となります。

私の変更は将来にも影響します。この機能を入れる手っ取り早い方法があるかもしれませんが、それがプログラムのモジュール構造に逆らったルートだったとしたら、クラフトを追加することになります。もし私がその方針を採用すると、今日の私にとってはより速く開発できますが、数週間や数ヶ月の間にこのコードを扱わなければならない他の人たちの動きを鈍らせてしまいます。チームの他のメンバーが同じ決断をすると、簡単に変更できるアプリケーションは、小さな変更のたびに何週間もの努力が必要になるほど、すぐにクラフトを蓄積してしまいます。

顧客は新機能がすぐに搭載されるかどうかを気にする

ここでなぜ内部品質がユーザーや顧客にとって重要なのか、そのヒントが見えてきます。内部品質が良ければ、新機能の追加が容易になり、その結果より速くより安価になります。レベッカと私がそれぞれ作っているアプリケーションは今は同じかもしれませんが、数ヶ月後にはレベッカは高い内部品質のおかげで毎週のように新機能を追加することができます。その間私は新機能を1つ開発するためにクラフトをどうにかしようとして行き詰まっていることでしょう。私はレベッカのスピードには太刀打ちできず、すぐに彼女のソフトウェアは私のものよりもはるかに機能的になります。その後、私の顧客は皆私のアプリを削除し、代わりにレベッカのを手に入れ、彼女は価格を上げることができます。

https://martinfowler.com/articles/is-quality-worth-cost/cruft-impact.png

内部品質の影響を可視化する

内部品質の基本的な役割は、将来の変更のコストを下げることです。しかし、良いソフトウェアを書くためには余分な努力が必要で、短期的にはそれなりのコストがかかります。

これを可視化する方法として、私は次のような擬似グラフを用います。このグラフでは、ソフトウェアの累積の機能性とそれを生産するためにかかる時間(コスト)をプロットしています。ほとんどのソフトウェアの場合、次のようなグラフになるでしょう。

https://martinfowler.com/articles/is-quality-worth-cost/poor.png

内部品質が低いとこのグラフのようになります。最初は進歩が速いのですが、時間が経つにつれ、新しい機能を追加するのが難しくなります。小さな変更であっても、プログラマーは大きな領域のコード、つまり理解しにくいコードを理解する必要があります。変更を加えると、予期せぬ破損が発生し、テストに時間がかかり、修正が必要な不具合が発生します。

高い内部品質に集中することは、このような生産性の低下を防ぐことにつながります。実際、製品によっては逆のことが起きることもあります。そこでは、以前の作業を活用して新機能を簡単に構築できるため、開発者のスピードが向上します。これを実現するためには熟練した規律あるチームが必要なので、このような幸せな状況は稀です。しかし、私たちは時折このような状況を目にすることがあります。

https://martinfowler.com/articles/is-quality-worth-cost/both.png

ここでの微妙な点は、内部品質が低い方が生産性が高い時期があるということです。この間、品質とコストの間にはある種のトレードオフがあります。もちろん、問題は、線が交差するまでの期間はどのくらいなのかということです。

ここで、これが疑似グラフである理由がわかるかと思います。ソフトウェアチームが提供した機能を測定する方法はありません。このようにアウトプット、つまり生産性を測定することができないため、内部品質の低さ(これも測定が困難です)が招く事態をはっきりとした数値で表すことは不可能です。アウトプットを測定することができないというのは、専門的な仕事の間ではよくあることです。果たしてどうやって弁護士や医師の生産性を測ることができるというのでしょう?

私は、熟練した開発者の意見を聞くことでどこで線が交差するかを評価しています。その答えは多くの人を驚かせました。開発者は、質の悪いコードは数週間以内に著しく遅くなることに気づいています。つまり、内部品質とコストのトレードオフが適用される期間はほとんど無いのです。小さなソフトウェアの取り組みであっても、優れたソフトウェアプラクティスに注意を払うことで利益を得ることができます。これは確かに私の経験とも合致しています。

どんなに良いチームでもクラフトを生み出してしまう

多くの開発者でない人々は、クラフトは開発チームが不注意でミスをしたときだけに発生するものだと考えがちですが、どんなに優れたチームであっても、仕事をしているとどうしても何らかのクラフトを発生させてしまいます。

私はこの点について、最高の技術チームのリーダーの一人と話をしていたときの話で説明したいと思います。彼は、大成功を収めたと広く考えられているプロジェクトを終えたところでした。クライアントは、納品されたシステムの能力、構築時間、コストの両面で満足していました。当社の社員は、そのプロジェクトでの経験を前向きに評価していました。そのテックリードはおおむね満足していましたが、システムのアーキテクチャはそれほど良くないと告白していました。私は「どうしてそんなことがおきるんだ?あなたは当社の最高のアーキテクトの一人でしょう?」と反応しました。彼の返事は、経験豊富なソフトウェアアーキテクトにはおなじみのものでした。「我々は良い決断をしたが、今になって初めて、どのように構築すべきだったのかを理解することができた。」

ソフトウェア業界の一部の人を含め、多くの人はソフトウェアの構築を大聖堂や高層ビルの建設に例えています - なんせシニアプログラマのことを「アーキテクト」と呼ぶくらいですから。しかし、ソフトウェアの構築は、物理的な世界には無い不確実な世界に存在しています。ソフトウェアの顧客は、製品にどのような機能が必要なのかについて大まかなアイデアしか持っておらず、ソフトウェアが構築されていくにつれてより多くのことを知ることができます - 特に初期のバージョンがユーザーに提供されるとより多くの必要な機能が明らかになってきます。ソフトウェア開発の構成要素である言語、ライブラリ、プラットフォームは、数年ごとに大きく変化します。これを物理的な世界で例えると、建物の半分が建設された段階でユーザーは利用を開始し、更に顧客は新しい階の追加や間取りの変更を要求するようなものです。しかも、コンクリートの基本的な特性も1年おきに変化するのです。

このようなレベルの変更を考えると、ソフトウェアプロジェクトは常に新しいものを生み出していると言えます。これまでに解決されてきた問題に取り組むことはほとんどありません。当然のことながら、私たちはソリューションを構築しているときにその問題についてほとんどのことを学びます。そのため、私がよく聞く話では、チームがソフトウェアのアーキテクチャのあるべき姿を最もよく理解しているのは、1年ほどかけてソフトウェアを構築した後だということです。どんなに優れたチームでも、ソフトウェアにはクラフトがあるものです。

違いは、最高のチームはクラフトをあまり作らないだけでなく、作ってしまったクラフトを十分に取り除き、機能を素早く追加し続けられるようにしていることです。自動テストの作成に時間をかけて、問題を素早く表面化させバグの除去に時間をかけないようにしています。また、頻繁にリファクタリングを行うことで、バグが蓄積して邪魔になる前に取り除くことができます。継続的インテグレーションは、チームメンバーがお互いの立場に立って作業を行うことで、問題の蓄積を最小限に抑えることができます。よくある例え話では、キッチンの作業面や機器をきれいにするようなものです。キッチンを汚さずに料理をすることはできませんが、素早く掃除しないと汚れが乾いて落ちにくくなり、次の料理を作るときに邪魔になります。

高品質なソフトウェアはより低コストで開発できる

以上をまとめます:

  • 内部品質を疎かにすると急速にクラフトが蓄積されていく
  • このクラフトが機能開発を遅らせる
  • 優れたチームであってもクラフトを発生させるが、内部の品質を高く保つことによってそれを制御することができる
  • 内部品質が高いとクラフトが最小限に抑えられ、チームはより少ない労力、時間、コストで機能を追加することができる

悲しいことに、ソフトウェア開発者は通常この状況をうまく説明してくれません。私はこれまでに何度も開発チームと話をしてきましたが、「彼ら(経営陣)は時間がかかりすぎるから、品質の良いコードを書かせてくれない」と言っていました。開発者はしばしば適切なプロフェッショナリズムの必要性を正当化することで、品質への注意を正当化します。しかし、このモラルに訴える議論では、品質にはコストがかかるということを意味してしまいます - そして彼らの議論を破滅させます。厄介なことに、その結果として生じる粗雑なコードは、開発者の生活を苦しくさせ、顧客のお金を犠牲にすることになります。内部品質について考えるとき、私は経済的な議論としてのみアプローチすべきだと強調しています。内部品質が高ければ、将来の機能のコストが削減されます。つまり、良いコードを書くことに時間をかけることで、実際にコストが削減されるのです。

だからこそ、この記事の冒頭の質問は的外れなのです。高い内部品質のソフトウェアの「コスト」はマイナスです。私たちが日常の生活で決定を行う際に使い慣れているコストと品質はトレードオフであるという考え方は、ソフトウェアの内部品質について考える際には意味をなしません(この考え方は丁寧に作られたユーザー体験などといった外部品質については意味をなします)。コストと内部品質の関係は、普通では考えられない、直観的ではない関係であるため、理解しにくいものです。しかし、この関係を理解することは、ソフトウェアを最大限の効率で開発するために非常に重要です。