🤑

技術的資産としての良いコード - 蓄財のメンタルモデル

2024/11/10に公開

最近、良いコードに関する記事を書いていて、 コードはレバレッジの効く資産である という考え方をうまく言語化できていないように感じたので、この辺の考え方を整理します。「良いコードとはなにか」の一つの結論になっています。
(たまに、時間に関する微分積分の概念を使いますが、わからなくても概ね理解できると思います。)

コードを書く仕事の目的は作業ではない

コードを書く仕事は、構造的に 作業が目的ではありません。まず、これについて説明します。
一般論として、作業が目的の仕事は多数あります。例えば、掃除や洗濯は、その作業および作業を達成した結果自体が目的です。もちろん、それらの作業をする際にも、(自分自身を含む)人に喜んでいただけるような仕事をするというマインドセットは大事だと思いますが、例えば仕事としてそれを依頼する場合には、単純に掃除をしてもらう、洗濯をしてもらう、という結果を得ることが大きな目的です。
では、コードを書く場合はどうでしょうか。コードを書くという行為自体は作業ですが、コードを書く仕事においてコードを書くというのはあくまでも手段であって、ソフトウェアを作る、サービスを提供する、といった目的の中の一部としてコードを書くという作業が存在しています。

特に、ソフトウェアやサービスというものは、コードが蓄積していくような構造をしており、ソフトウェアやサービスが単位時間あたりに提供できる価値はコードが蓄積するほど増大 していきます。もちろん、例えば法律の変化などによって、コードの量が増えても提供価値が増大しないケースもあります。あるいは、リファクタリング等によってコードを削減しても提供価値が変わらなかったり、むしろ増大するといったケースもあると思います。しかし、原則としてはコードの量や作業時間に対して単位時間あたりの提供価値が増大する という構造があります。
掃除や洗濯の場合は、そうではありません。個人のスキルの上昇などはあるかもしれませんが、基本的には時間に比例する成果が得られる構造となっています。
概念を簡単に説明するために、常に一定の品質で作業を行う場合のグラフを描いてみました。
実際には、ソフトウェアの提供価値の上昇幅が単位時間あたりで一定とはならないケースも多く、もっと複雑なグラフになりますが、ここでは ソフトウェアは掃除のような構造と異なり、累積提供価値と比例しない という事が見てとれれば良いと思います。

※念の為の補足ですが、作業としてコードを書くことで直接的に対価をもらうことへの否定は全くありません。また、それを生業として深いプロになる道もあります。

コードを書いて蓄財する - 蓄積する仕事

これは、仕事が蓄積するとそれだけで価値を生み出し続ける、いわゆる資産としての構造があることがわかります。仮に、ある時点でコードを書かなくなったとしても、それまでに書いたコードはソフトウェアやサービスとして適切に運用される限りにおいて価値を生み続けるということです。
したがって、コードを書くときには蓄財するという感覚を持って、仕事が蓄積していくような方法を選ぶという事が重要になります。

戦略性を持って、複数の選択肢から書くコードを選ぶ

ソフトウェアにおいて、ある機能を実現したいと思うとき、その手段として書くコードには複数の選択肢があり得ます。この選択肢の数はその人の持つ知識によって変わってきますが、ではどのように選択するとよいのでしょうか?
まず前提として、そのような選択が今後の蓄財に影響するという発想が必要です。その上で、蓄財していくにあたって適切と思える選択肢を戦略的に選ぶという気持ちを持ちましょう。
まずは思いつく選択肢をすべて挙げてみる。その上で、蓄財において適切な選択肢はどれかを考える。
このようなメンタルモデルを持って、以下で述べるようなレバレッジが効く選択肢を選びます。

蓄財においてレバレッジが効くポイント

蓄財という観点で、レバレッジが効くポイントを挙げていきます。
なお、これまでもそうでしたが、ここで述べるレバレッジは開発者自身というよりはそのコードの提供価値(より正確にはソフトウェアやサービスの提供価値)という部分で話を進めます。

「将来にわたって」コストが少なくて済む

先に述べた通り、コードを書くことはその瞬間の提供価値だけの問題ではなく、将来にわたって価値を提供していく事に影響します。ここでは、まずコストが少なくなるという観点で整理をしてみます。

人間その他が動くコストが少なくて済む

あるコードの書き方(実装)をしたときに、人間その他が動くコストがどうなるか、という観点です。
わかりやすいのがバグったデータが出来上がる場合で、バグったデータが出来上がってしまった場合には、それを人間が修正しないといけません。その他、仕様の不備や行き届かない部分で運用工数が増加したり、あるいはインフラコストが増加したり、といった事が考えられます。
これは、ざっくり単位時間あたりの提供価値に比例するような観点と思ってよいです。

コードを書かないで済む(微分)

こちらは、あるコードの書き方(実装)をしたときに、例えば新しい要件・要望への対応が必要になったときに、どれぐらい追加実装をしなくて済むか、という観点です。
これは、開発者のコストという意味では人間その他が動くコストの議論と同じように見えるかもしれませんが、そうではありません。この記事の冒頭で少し説明したように、開発者の作業は単位時間あたりの提供価値の微分に比例する概念と捉えることができますが、ではこの比例定数をどれぐらい大きくできるか というような話のうち、特にコードを書かずに済ませられるか、という観点です。(コードを書く必要があれば、それだけ比例定数が小さくなります。)
これは、単位時間あたりの提供価値の微分に関する話です。

「将来にわたって」富を生み出す

コストを少なくするという観点での説明をしましたが、ソフトウェア・サービスの真価は、そもそも価値・富を生み出すという事にあります。したがって、その富を生み出す能力をどこまで増大できるか、という事は最も重要な観点と言っても過言ではありません。

単純に富を生み出し続ける

あるコードの書き方(実装)をしたときに、それがどれぐらい富を生み出し続けるか、という観点です。
これは特に、要件Aを実装する方式として実装Xと実装Yがあったとして、実装Yでは要件Bもカバーできるが、実装Xでは要件Bをカバーできない、といった場合に観点として必要になります。

ここで、「それは、そもそも要件Aだけに対応しようとするという要件の時点で適切ではないので、要件Bも含むものとして整理する要件定義の能力がないだけでは?」と思った方はいますか?
その考え方も正しい部分はあると思いますが、以下のような理由で、私はコードを書く人も積極的に要件を考え、また提案をするべきだと考えています。

  • コードを書く(あるいは基本設計などの)タイミングで実装方式をより具体的に検討したタイミングで、初めて各実装で要件Bもカバーできる・できないという事がわかる場合がある
    • 特に、実装Xと実装Yの違いが開発者でないと判断できない場合があり、ここで要件Bの事を一切会話せずに開発者判断で実装Xを選んでしまうと今後のコストに無意識で大きな影響を与える場合がある
    • ビジネス的に今のタイミングでは要件Aしか必要でないという場合でも、実装Xと実装Yのコスト差によって要件Bをカバーするか否かという判断が変わってくるが、そのコストが開発者にしかわからない

これは、カバーできる要件の範囲という意味で、ざっくり単位時間あたりの提供価値に比例するような観点です。

より大きな価値を生むコードを作りやすくなる(微分)

上述の議論の類似で、開発者の工数に影響する場合などです。特に再利用性などの面で影響が大きく、例えば類似の別要件にうまく転用できる汎用的な実装を目指すか、そうでないか、といった事の積み重ねで劇的に対応工数が変わってしまう場合などもあります。
ちなみに、この話と関連するアンチパターンについて、設計レベルで具体的に説明した記事を以前に書いたので、もし興味があれば参考にしてください。

https://zenn.dev/339/articles/c5277131c50117

他にも、ある概念をコーディングによって実現した結果、それをさらに抽象化したり繰り返したりする実装に手が届くようになる、といった事もあります。これは、以下のポスト(ツイート)で言及されているようなことです。

https://x.com/sugimoto_kei/status/1672078453804511233

こちらは、単位時間あたりの提供価値の微分に関する話です。

※なお、なんとなくMECE風に書いていますが、例えばコードを書かないで済むことで大きな価値を生むコードを作りやすいという側面もあるので、必ずしもMECEな要素ではないと思っています。複雑に絡み合っている事象について、メンタルモデルとして分かりやすくするために無理矢理観点を分離したというのが適切でしょうか。

稼働する環境まで含めてサービス

ところで、コードやソフトウェアは必ずしもサービスではありません。ソフトウェアは誰かに利用されることで、はじめてサービスとして成立します。したがって、ソフトウェアを通じてサービスを提供する場合には、その稼働する環境や運用も含めて、はじめて価値を提供できるという事になります。サービスにかかるソフトウェアを開発している場合にはその観点も重要で、特にレバレッジを考える上で、ソフトウェア単独で見たときよりも一層広い範囲の影響を考える必要があるからです。例えば、コードのレベルだけで考えて最適な事が、サービスとして考えれば最適でないという事も発生します。
これは開発者の目線で考えるのは難しいことですが、難しいから考えなくてよいという事ではなくて、常に考え続ける必要のあることです。

「認知を合わせる」ことがなぜ大事なのか

サービスの開発においてレバレッジを考えるために重要なことは、「認知を合わせる」という事です。つまり、そのサービスを支える様々な立場の人、例えば利用者であったりオペレーターであったり営業であったり、そうした人々とサービスに対する「認知を合わせる」ようにします。具体的には、例えばDDDでいうユビキタス言語のような共通言語を用いるという事もそうですし、単純にサービスについての会話をして空気感を共有するという事もそうですし、考え方や向き合い方を揃えるということです。
もちろん、すべてを理解できるわけではないし、いつも正解を引けるわけでもない、それでもできる限り認知を合わせます。それをしなければ、レバレッジを考えて戦略性を持って書くべきコードを選んでいくという事なんてできるはずがありません。サービスの開発において蓄財していく、技術的資産を生み出せる開発者になるうえで、非常に重要なことです。
以下、うまく認知が合わない場合に生じる構造的な課題について言及します。

コードの価値は「所有していない」開発者への"利益"にならないことがある

例えば、再利用性の高いコードを書いても、それによるリターンが開発者に直ちに発生しない場合があります。というのは、新しい機能を車輪の再発明的に実装することは、それ自体開発者にとって特にマイナスではないので、再利用性が高い実装をすることで得にならない場合があるからです。
このような場合、再発明をしなくて済むようになることで、例えばより深い機能が実装できるようになるとか、そういった面でのインセンティブを考えられるケースもありますが、本質的に時間に対して給与が発生するという形式だけだと、再利用性の高いコードを書く事が直ちにインセンティブになりません。

保守性だけを目的にすると、将来にわたって価値を削ることがある

一方で、例えば読みやすいコードを書くということは、それを修正する際に壊れにくくするという意味で開発者にとっても利益があります。しかし、読みやすいコードを追求するあまり、例えばカバーする要件の範囲が狭くなったり、追加改修がしにくい構造のコードになったり、といったケースがあります。これは、仮に現時点でのコード・提供価値のみで評価すれば差がなかったとしても、長期的に見ると提供価値を損なってしまい、そうすると単純にコードのレベルで最適化をしてもそれがサービスとして見たときの最適化になりません。

いずれのケースも、単純なコードのレベルでレバレッジを効かせるという事ではなく、サービスのレベルでレバレッジを考える必要があります。

むすび

この記事では、コードはレバレッジの効く資産であって、またその資産を形成する・蓄財していく上でソフトウェアやサービスにおけるレバレッジを考える事が不可欠であること、そのためには開発者の認知を関係者と合わせることが重要であることを述べました。
このレバレッジの部分、特に再利用性のような部分について、私の中では自明に重要ぐらいの気持ちがあったのですが、他の人において全く評価されていない場合があったりするので、それを深堀りしたことでこの記事が生まれました。
また、世間でよく技術的負債という言葉が使われる一方、資産としてのコード・ソフトウェア・サービスという事に開発者の目線で正面から言及している場面が少ないように感じたので、資産的な部分にスポットライトを当てることを目標としました。
コードがレバレッジの効く資産であることや、自身が所有者として行動しなければレバレッジを最適化しないことへの指摘は、例えばシリコンバレー最重要思想家ナヴァル・ラヴィカントという書籍の中にもありますが、あまり世の中に浸透していない気がするのと、従業員・開発者としてどうすれば良いのかという答えにはなりきらない部分があると思っていたのですが、個人的な最近のテーマである「認知を合わせる」ことでレバレッジにつながるという整理ができました。
単に「良いコード」というとき、最も大切な要素は、ここで述べたような事だと思っています。それがレバレッジの効く資産になっていれば「良いコード」であり、もっとレバレッジを効かせる方法があるならば、相対的に改善点のあるコード(場合によっては、悪いコード)となります。 レバレッジが効きにくくなる要因は様々で、例えば品質特性でいうと、機能適合性は提供価値に直接影響するし、再利用性は将来的な提供価値に影響するかもしれない、セキュリティは提供価値を減じるリスクへの対策の一つだが確率的な議論になりがち、といったことになります。これらを直接比較するのは難しいですが、レバレッジが効くという観点で仮説を立てて戦略的に実装を進めることで良いコードを目指していくのが、理想的な開発のあり方 と思います。

合わせて読むと面白いかもしれない記事たち

https://zenn.dev/339/articles/ecc4986473ca88

https://zenn.dev/339/articles/e3c174fdcc083e

https://zenn.dev/339/articles/2f3f22e9d0acaf

Discussion