プログラミング
コードベースを理解していないことへの擁護
In defense of not understanding your codebase (seangoedecke.com)
要約
この記事は、ソフトウェアエンジニアが自身のコードベース全体を完全に理解する必要はないという考え方を擁護しています。特に大規模システムやチームの入れ替わりが激しい環境では、部分的な理解で効果的に作業を進めることが可能であり、むしろそれが現実的なアプローチであると論じています。Peter Naurの「プログラミングは理論構築である」という考え方に対し、現代の巨大なコードベースでは完全な理論構築は不可能であり、部分的な理解に基づいた実践が重要であると主張しています。
全文翻訳
ソフトウェアエンジニアとして、あなたは自身のコードベースをどれだけよく理解する必要がありますか? 小規模なコードベースで、離職率の低いチーム(例えばRedisやThe Witnessのようなゲーム)で働く人々は、「もちろん、完全に理解しなければ良い仕事はできない」と言うでしょう。また、大規模なコードベースで、離職率の高いチーム(例えばGoogleのウェブ検索バックエンドやGitHub)で働く人々は、「もちろん、完全に理解することはできない、自分の担当範囲で最善を尽くすしかない」と言うでしょう。これらは、異なる方法論、プラクティス、文化を持つ、大きく異なる2つのプログラミングのあり方です。しかし、最初のグループはソフトウェアエンジニアリングに関するオンライン議論で過剰に代表されています。私は、後者のグループを前者に対して擁護したいと思います。多くのソフトウェアエンジニアリング環境では、部分的な理解の状態でいることは何も問題ありません。実際、大規模システムでは、部分的な理解が最善の策です。
「プログラミングは理論構築である」という考え方に対して
「コードベースを理解しなければならない」という側の最も優れた表現は、Peter Naurの有名な論文「Programming as Theory Building」です。私はこの論文を気に入っていますが、その方向性が行き過ぎていると思います。Naurの核心的なポイントは、プログラマーがプログラムに取り組むとき、コードは単なる副産物であり、彼らが取り組んでいる主な産物は「プログラムの理論」であるということです。それは、コードやドキュメントでは部分的にしか捉えられない、何が起こっていてなぜそうなるのかについての直感的な感覚で構成されています。もしコードを失っても、プログラムを簡単に書き直すことができるでしょう。もし彼らの理解を失った場合(例えば、チームの離職率が100%になった場合)、コードを理解するのに苦労するでしょう。ここまでは良いのですが、Naurはさらに進みます。彼は、理論はコードから再構築されるべきではないと言います。Naurによれば、プログラム全体を破棄して、新しいチームにゼロから再構築させ、その過程で新しい理論を構築する方が良いのです(注3):ドキュメントからプログラムの理論を再確立することは、厳密には不可能である…したがって、既存のプログラムテキストは破棄され、新しく編成されたプログラマーチームは、その与えられた問題を新たに解決する機会を与えられるべきである。
大企業で効果的なソフトウェアエンジニアだった人なら誰でも、Naurはこの点に関して全く間違っていることを知っています。少なくとも2つの理由があります。第一に、大規模なソフトウェアシステムをゼロから再構築することは不可能です。十分に大きなシステム(ユーザーがいる場合)には、再実装できない何千もの奇妙なケースや癖が含まれています。システムを深く理解しているチームでさえ、それをすることはできません。あまりにも多くのことを同時に処理しなければならないからです。成功した書き換えは常に、既存のコードベースを小さな独立したチャンクに分割し、一度に1つのチャンクを書き換えることから始まります。言い換えれば、ソフトウェアシステムを書き換えるということは、古いシステムに多くの変更を加えることを意味します。古いシステムを変更できないのであれば、それを新しいシステムに置き換えることも certainly できません。第二に、放棄されたシステムは常に復活します。何億行ものコードと何千人ものエンジニアがいるテクノロジー企業では、コードベースに精通している人が誰もいなくなることは珍しくありません(注4)。数人の人が不適切な時期に辞めたり、コードベースが1年間メンテナンスされなかったりするだけで済みます。私は他のチームがこれを行うのを見たことがあるだけでなく、個人的に放棄されたコードベースを引き継ぎ、それを理解し、効果的に作業できるようになるまでになりました。時間がかかりますが、コードベースの新しい理論を構築することは可能です。まず、1つのフローをエンドツーエンドで理解することから始め、そこからゆっくりと枝分かれさせ、慎重に変更を加えながら進めます。十分に大きなコードベースでは、誰もが不完全なプログラム理論で作業しています。現代のソフトウェアシステムの決定的な特徴は、誰か(あるいはチーム全体)がそれをすべて頭に入れるには大きすぎるということです。誰もがそれをすべて理解しているわけではありません。効果的であるためには、不完全な理論で作業する方法を見つけなければなりません。だからこそ、私は立場を取ることと自信について繰り返し言及するのです。何かが確信できない場合、完璧な理解を持つ誰かが来て答えを与えてくれるのをただ待つことはできません。あなたが有能なエンジニアであれば、その人はあなた自身です。歯を食いしばり、最も教育的な推測をして、その結果に対処しなければなりません。
Naurに寛大に言えば、1985年頃のプログラムの平均サイズは今日よりも数桁小さかった可能性があり、Naurが「大規模プログラム」について書いているとき、それは数千万行のコードを指しているわけではないかもしれません。Naurの最初の大規模プログラムの例は20万行の産業用監視プログラムであり、2番目の例はコンパイラです。1987年、コンパイラGCCの最初のバージョンは約10万行のコードでしたが、2015年にはGCCは1400万行を超えました。10万〜20万行のコードの書き換えは比較的簡単であると信じることができます。特に既存のテストを再利用できるのであれば。しかし、100万〜200万行となるとそうはいきません。
理論構築は多くのトレードオフの一つ
LLMは、理論構築の通常のプロセスを妨げる悪いツールとしてしばしば引用されます。私はこれが単純化しすぎていると思います。多くのソフトウェアツールと同様に、LLMは諸刃の剣です。ソフトウェアの詳細なメンタルモデル(理論)を構築することをより困難にしますが、部分的な理論を迅速に構築することを可能にし、その部分的な理論をより効果的に活用するのに役立ちます。これは私がまだ考えている複雑なトレードオフです。LLMを脇に置くと、ソフトウェアに対するあなたの理論を妨げるものは何であれ悪いと言うのは愚かであると確信しています。
理論の維持を困難にする他のものの部分的なリストを以下に示します。
あなたのコードベースに他の人がコードを書くことを許可すること
アクセシビリティやデータ保護のような法的に要求される機能の実装
同僚が仕事を辞めたり、チーム間を移動したりすること
セキュリティパッチのためにソフトウェアバージョンをアップグレードする必要があること
ライブラリやその他の依存関係を持ち込むこと
ソフトウェアのほとんどのことと同様に、「コードベースの理論を維持すること」は、多くの価値観のうちの一つです。時にはそれが最も重要な価値観であり、他の価値観を犠牲にしますが、時にはスピード、法的遵守、あるいは政治的な理由(注5)のためにそれをトレードオフします。ほとんどすべてのエンジニア、特に「純粋な」エンジニアは、ソフトウェアの正確なメンタルモデルを維持することを好みます。それはより楽しく、ストレスが少なく、「本物のエンジニアリング」のように感じられます。だからこそ、多くのエンジニアは、コードベースの正確なNaur理論を維持できる小規模なコードベースで単独で作業するために、余暇にオープンソースプロジェクトに取り組むのです。それに何も問題はないと思います。
しかし、仕事では、あなたは仕事をするために支払われています。言い換えれば、彼らはあなたのエンジニアリング価値観のセットを採用するためにお金を払っています。パフォーマンスについて個人的にどれだけ気にかけていても、時には遅いコードを書かなければならないことは(例えば、プロジェクトを期日までに完了させるため、あるいは厄介な要件に対応するため)、おそらくよく理解されているはずです。コードベースの理論を維持することも、同じ種類のものです。
編集:この投稿はlobste.rsでいくつかのコメントを得ました。興味深いコメントの1つは、コードについて「局所的に」推論する能力(つまり、部分的な理解で)が、最初からCSのコア目標であったことを指摘しています。これは、私が「How good engineers write bad code at big companies」で述べようとしていたことの良い説明でもあります。また、LLMに関する1つのさりげない段落のために、この投稿がvibecodingとしてタグ付けされたのは面白いです。私はまだこの投稿を私のブログでAIとしてタグ付けしないでしょう。私は「Pure and impure software engineering」でこのことについて詳しく書きました。ソフトウェア業界で繰り返される多くの議論は、純粋な完全理解文化が、不純な部分理解文化と衝突することによって引き起こされていると私は考えています。