世界を動かす技術を、日本語で。

怠惰の危険を失う

概要

  • Programming Perl の著者Larry Wallが提唱した 「怠惰・短気・傲慢」 というプログラマの三大美徳について解説
  • 怠惰 がもたらす抽象化の重要性とソフトウェア設計の美学を強調
  • LLM(大規模言語モデル)登場による 生産性と品質のジレンマ
  • LLMは人間の「怠惰」の美徳を持たず、 システムの複雑化を助長
  • LLMはあくまでツールであり、 人間の美徳に基づく設計思想が不可欠

プログラマの三大美徳と抽象化

  • Programming Perl でLarry Wallが提唱した 「怠惰・短気・傲慢」 という三大美徳
  • 怠惰 :面倒を避けるために抽象化や自動化を追求する姿勢
  • 短気 :すぐに結果を求め、効率化を図る動機
  • 傲慢 :自分の書いたコードが他者にとっても価値あるものだという自負
  • 多くの技術者が コピペ に頼る一方、本来は 高レベル抽象化再利用性 を優先すべき
  • 美徳としての怠惰は、 システムをできるだけ単純に保つ 努力を促す
  • 抽象化の設計 には多大な知的労力が必要であり、将来の自分や他人の時間を節約する投資
  • 成功した抽象化は、 後続の開発者にも恩恵 をもたらす

LLM時代の「偽りの勤勉」と生産性の罠

  • 近年、ソフトウェア開発者層が拡大し、「怠惰」の美徳が伝わりにくくなった現状
  • LLM(大規模言語モデル) の普及で、 コード量や生産性の過剰アピール が増加
  • 例:Garry Tanが 1日3万7千行のコード生成 を自慢
  • こうしたアプローチは 本質的な価値を見失う危険性
  • 実際の成果物には 不要なファイルや重複、無駄なデータ が混在
  • LLMは 「怠惰」の美徳を持たず、無限に作業を積み重ねる傾向
  • 人間の有限な時間 こそが、良い抽象化や設計を生む制約

LLMと人間の役割分担

  • LLMは 人間の美徳や制約 を持たず、自律的にシンプルさを追求しない
  • 最良のエンジニアリング は制約から生まれる
  • LLMは あくまでツール であり、設計思想や品質管理は人間の責任
  • 技術的負債の解消作業効率化 など、非本質的な部分でLLMを活用
  • 「美徳としての怠惰」 に基づき、よりシンプルで強力なシステムを目指すべき
  • 次世代のエンジニア にも恩恵を与える設計思想の継承が重要

Hackerたちの意見

一般的には、私たちのほとんどは、抽象化をもっと使うことを考えるべきだと思う。Programming Perlが書かれたときはそうだったかもしれないけど、今は逆のことが多い気がする。私はWET(Write Everything Twice)を支持してるよ(ここでのコメントからパクったけどね)。で、3回目には新しい抽象化を作ることを考えてみる。

WET - Write Everything Twice これは「三の法則」として聞いたことがあるな。

大学の頃から、すべてを2回書くことを推奨してるよ。

二回以上って、かなり低いハードルだよね。Programming Perlの引用とは矛盾しないと思う。

これには完全に同意するよ。ソフトウェアの美しさは、正しい抽象化が計り知れない影響を持つことにある。オペレーティングシステムやRDBMS、クラウドオーケストレーションみたいな大きな革新について話してるんだ。でも、世界の大多数のコードはそうじゃなくて、単純なビジネスロジックで、人間が人間の目的のために実行するアイデアやプロセスを表していて、抽象化に抵抗するんだよね。それでも人々は試みるけど、大手テック企業ではプラットフォームの創造が技術的な帝国主義やキャリア駆動の開発の一形態として広がってる。私のテックレビューのルールは、プラットフォームを持つには、三つの実証済みのユースケースが必要で、それらを結びつけることが共有システムの自律性制約によるネットマイナスにならないことを示さなきゃいけないってこと。

時間が許せば、二回書くのは理にかなってるし、機会があればそうすべきだよ。最初は少し探求的な感じ(もしかしたら捨てプロトタイプかも)で、二回目には問題をよりよく理解して、より良い仕事ができる。三回目は新しい抽象化を使う時で、ここが注意が必要なところ。フレッド・ブルックス(「神話のマン・マンス」)はこれを「第二システム効果」と呼んでいて、一度(本物で、ただのプロトタイプじゃなく)やったことに自信を持つことで、過剰設計で不必要に複雑な「バージョン2」を作りたくなることがあるんだ。抽象化や余計な機能を追加して「もっと良くしよう」と誘惑されるからね。

それでも、平均的なプログラマーよりも抽象化が進むことになるね。

同意するよ。1991年(『Programming Perl』が出版された年)から、どれだけ多くの抽象化の層が作られたか、ほんとに驚くよね。

200k locをLLMで書いたって大声で言うのはバカみたいだけど、他の人が書いたコードを見て「はは!こんなにバカだ!」って言うのもあんまり良くないと思う。君も同じ間違いをしてるよ、ただ逆の方向でね。コードの出力でソフトウェアエンジニアリングの職業を判断してるんだ。じゃあ、Garry Tanはその週に実際に価値のあるものを生み出したのかな?わからない、彼に聞いてみて。

そうだよね!コードの品質が負の価値や失われた命に関係ないわけじゃないよね?!さらに、> Tanがそんなにエネルギーをかけて作っていたアーティファクトについては、私は大体無視してた。でも、ポーランドのソフトウェアエンジニアのGregoreinがそれを分解して、結果は予想通りで面白くて教育的だったよ。Tanの「ニュースレター・ブログ・なんか」は、複数のテストハーネス(!)、Hello WorldのRailsアプリ(?!)、隠れたテキストエディタ、そして同じロゴの8つの異なるバリエーションが含まれてたんだ。その中の1つはゼロバイトだったけど。これらのソフトウェアに含まれている... /もの/ が攻撃の対象になりやすくする面積を増やしたと思う?

「価値生成」っていう言葉にはちょっと警戒してる。私にとって、この文脈では化石燃料で経済成長を促進するのと似てる。最終的にそれがネット利益につながるか(価値がそれに関わるコストや後で混乱を整理するコストより大きいか)は言うのが難しいと思うけど、短期的な価値だけで判断できるとは思わないな。

時間の無駄だね。200,000行のコードを読んで、短期間でこんなにコードを生成して本番環境に出すのが悪いアイデアだって証明するつもりはないよ。証明するのはそのコードを書いた人の責任だし。もしただのツイートのやり取りで、LOCを自慢してもっとLOC/秒を目指してる人を判断したいなら、もちろん判断するよ。バカみたいだし。

記事のフレーミングを考えると、逆の意見が出てくるのも理解できる。著者はプログラマーの「怠惰」とコードを美徳として同時に示唆しているから、混乱を招いてるよね。でも、彼らが価値の生成を無視しているとは思わない。むしろ、問題解決よりもコードの質に価値があると示唆しているように感じる。これは、最終製品よりもプログラミングの追求に興味がある多くの開発者に共通する態度みたい。

あなたは逆の方向で、他の人と全く同じ間違いをしているよ:コードの出力ではなく、価値の生成に基づいてソフトウェアエンジニアリングの職業を判断している。だけど、真の指標はどちらでもなく、コストを差し引いた価値なんだ。そのコストには、ソフトウェアを作るコスト、理解して維持するコスト、セキュリティを確保してデプロイし運用するコスト、そして、セキュリティホールの悪用によるコストや、偶発的な著作権や特許侵害、デジタル市場法やデジタルサービス法の違反による法的責任のコストなど、さまざまなコストが含まれる。AIの使用は、これらのコストの一部を劇的に減少させる一方で、他のコストを劇的に増加させる(期待値として)。でも、AIを持ち上げる人たちは、減少したコストにだけスポットライトを当てている。

さて、ガリー・タンはその週に実際に価値のあるものを生み出したのかな?わからない、彼に聞いてみて。ナイーブにならないで。ガリーは無名じゃないよ。彼は何行のコードが生成されたり削除されたりするかなんて全く気にしてない。彼はその投稿を広告として出したんだ。彼はYCのCEOだから、AIに依存しているんだよ。彼はただの広告を出してるだけ。

その演習から得られた主な価値はスクリーンショットだったね。これは一種の資格主義だよ。

いやー、こういうリーダーシップのもとで働くのってどんなに素晴らしいんだろう。

LLMが十分に怠けてないってのは確かに感じるね。でも、それが恒久的な問題なのか、次のモデルアップグレードで修正されるものなのか、ただ君のエージェントフレームワークやCICDフレームワークが対処するものなのかは不明だ。例えば、今はエージェントを使って機能が「完了」した後にコミットするとき、「バグやリファクタリングが必要かチェックして」ってプロンプトを出してるんだけど、「最後のN回のコミットを見て、コードが簡素化できるかリファクタリングできるかをチェックする」っていうCICDステップがあってもいいかもね。

それに対する終了基準を定義するのは難しいね。LLMに「X」を見つけるように頼むと、彼らは通常「X」として資格があると主張する何かを見つけてくる。

同意するよ。これはツールの使い方の制限であって、根本的な特性じゃない。これらに単純に足し算をさせると、無差別にそれをやっちゃう。結果的に巨大なゴミの山ができる。でも、レビュー段階でLOCとDRYを減らすようにLLMを使ったハーネスに指示すれば、それもできると思う。大きなタスクを委任してレビューしないと、巨大なゴミの山ができる可能性が高いと思う(自分でやるかエージェントと一緒に)。

LLMがシンプルなプログラムじゃなくて、フルのシングルページウェブアプリケーションを作る傾向があるのに気づいたよ。結果をターミナルに表示するだけのプログラムの方が簡単なのにね。LLMにspec.mdファイルを簡潔に保つのも苦労してる。別のタスクをしながらドキュメントを簡略化するのができないみたいで(例えば、「このドキュメントをxyzで更新して、周りの内容を簡単にして」)、簡略化や要約を特に指示しないといけないんだ。人間が読めるものが欲しいなら、自分で書いた方がいいかも。LLMの出力を編集するのは本当に面倒だし、実際に何かを書いて理解しておくと、自分も流れに乗れるしね。

ドイツの将軍クルト・フォン・ハンマースタイン=エクフォルト(ライヒスヴェア/ヴェアマハト時代の高官):「私は自分の将校を4つのグループに分ける。賢い、勤勉な、愚かな、怠惰な将校だ。通常、2つの特性が組み合わさる。賢くて勤勉な者は、参謀本部にいるべきだ。次のグループは愚かで怠惰な者たちで、彼らはどの軍隊にも90%を占めていて、ルーチン業務に向いている。賢くて怠惰な者は、難しい決断に必要な知的明晰さと冷静さを持っているので、最高のリーダーシップポストに適している。賢くて勤勉な者には注意が必要だ。彼には責任を持たせてはいけない。彼は常に厄介なことを引き起こすから。」

俺たち90%の仲間はどこにいるんだ?

LOCを自慢するのと似てるけど、計算流体力学の分野でも、いくつかのバイブコーダーがテストスイートの大きさや厳密さを自慢してるのを見たよ。問題は、テストを詳しく見てみると、彼らのテストは特に優れているわけでもなく、私が手動で作ったテストよりも厳密さに欠けていること。バイブコーディングされたテストには大きなギャップがあることが多い。1百万のテストがあっても、簡単なテストばかりだったり、コードの正しい部分をカバーしていないテストはあまり価値がないよ。

LLMに全く意味のないテストを生成させないのは本当に大変だよ。ソースコードから文字列をgrepするだけとか、assert(1==1, true)みたいな。書かないべきテストのキュレーションリストを持ってないと、無意味なテストが何百も出てきちゃう。

最近の数ヶ月で、明らかに問題に対する間違った解決策だと思ったPRをいくつか見て、まさにこの気持ちを抱いてた。あるPRでは、自分でパース関数を実装してたけど、JSONみたいな確立された解決策があったはず。非LLMプログラマーなら、これを思いついてもすぐに他を探そうとすると思う。人間の感情が働いて「これはやりすぎ(おそらく冗長)な作業だ、もっといい方法があるはず」ってなるから。でもLLMには感情がないし、怠け者でもないから、それが問題になることもある。間違ったことをするのがすごく簡単になっちゃうんだよね。

それに、プロジェクト内に何があるかをチェックすることもないし。ちょっとグレップしてみれば、ほぼ同じことをしてる formatTimestamp 関数が3つ見つかるよ。

LLMたちと雰囲気コーダーたちに、ソフトウェア開発の不変の教訓の一つを教える時が来たね。

最初の前提には大反対だな。抽象化はシステムをシンプルにしないよ。ちなみに、普通はそうだけど、今回は本当に「常に」そうだと思ってる。

抽象化について言えるのは、漏れのある抽象化である可能性があるってこと。未来のバグハンターにとっては、抽象化がない方がマシかもしれないね。