ハクソク

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

十分に詳細な仕様はコードである

概要

  • 仕様書からのコード自動生成に対する誤解と現実を解説
  • OpenAI Symphonyプロジェクトを具体例に批判
  • 仕様書とコードの複雑性・労力の本質を整理
  • コード生成の信頼性・実用性の課題を指摘
  • 仕様書作成とコーディングの本質的な難しさを再考

仕様書駆動のコード生成に対する誤解と現実

  • agentic coding(エージェント型コーディング)推進派は、仕様書から直接コード生成が可能だと主張

  • しかし、実際にはこの主張には2つの誤解が根底に存在

    • 誤解1:仕様書は対応するコードよりも単純である
    • 誤解2:仕様書執筆はコーディングよりも深い思考を要する
  • 仕様書を「外注の次世代」として扱い、エンジニアが仕様書を書きエージェントに実装を任せる発想

  • 仕様書経由で品質が向上するという幻想

Symphonyプロジェクトの実態と課題

  • OpenAI Symphonyは、「仕様書(SPEC.md)からプロジェクト生成可能」と宣伝

  • しかし、このSPEC.mdは実質的に擬似コードやコード断片をMarkdownに書き起こしただけの内容

  • 例:データベーススキーマやアルゴリズムの詳細な記述、コードそのものを含む

  • 仕様書と呼べるものの、実質はコードに極めて近いものになっている事実

    • 仕様書が十分に厳密であればあるほど、コードに近づく必然
    • Dijkstraの「狭いインターフェース」の議論を引用し、形式的記述の限界を指摘
  • SymphonyのREADME通り、仕様書から実装(例:Haskellでの実装)を試みてもバグや動作不良が多発

  • 仕様書が長大化すれば、**Borgesの「正確さについて」**の寓話のように、地図と現実が一致して無意味化

仕様書作成とコーディングの本質的な難しさ

  • 仕様書作成は本来、コーディング以上に困難であるべき作業

  • 仕様書作成の目的は、全体像を俯瞰し批判的思考を促すため

  • しかし、「仕様書作成はコーディングよりも容易」と考える産業的風潮により、本質的な思考が省略されがち

  • SymphonyのSPEC.mdのように、AI生成の粗雑な仕様書が生まれる背景

    • 例:Section 10.5のような中途半端な仕様記述
  • 結果として、仕様書とコードの境界が曖昧化し、どちらの品質も保証できない状況に陥る

まとめ

  • 仕様書からのコード自動生成は、仕様書自体が実質的なコード化を要求
  • 仕様書の厳密さ・詳細さを高めると、人間がコードを書くのと同等の労力を要する
  • 仕様書作成やコード生成の信頼性・品質の限界を認識し、安易な自動化幻想を持たない姿勢が重要

Hackerたちの意見

人々が自分たちのより技術的な英語の方言(LLMSpeakとか)を作り始めて、モデルのパフォーマンスやトークンの使用を最適化しようとするのは、時間の問題だと思うよ。非常に圧縮された語彙を使うことで、あいまいさやトークンの使用を減らせるし、非常に具体的な概念が一つの単語に詰め込まれる感じ(モナドはエンドファンクターのカテゴリにおけるモノイドに過ぎない、何が問題なの?)。文法的には、あいまいさを減らすためにオックスフォード・カンマみたいなものが出てくるだろうし、エージェントとのやり取りでの確認作業も減るはず。初心者は同じ概念を不器用に100倍のトークンを使って表現し続けるだろうけど、彼らはプロンプトの精度が足りないからね。LLMの生産性を最大化したい人は、このあいまいさのない、情報密度の高い方言で話し始めるだろうし、それがトークンの使用やLLMのコストを最適化することになるんだ。
あいまいさのない言語を使おうよ。Lojbanを提案してもいいかな? [1] https://en.wikipedia.org/wiki/Lojban [2] 誰かが話してる動画: https://www.youtube.com/watch?v=lxQjwbUiM9w
> 自分たちのより技術的な英語の方言を作ることで ああ、リスプの呪いだね。また始まった。偶然にも、80年代のAIバブルが崩壊したのは、リスプの方言が互換性がなかったからでもある。
> トークンの使用やLLMのコストを最適化する 文脈の汚染がもっと大きな問題だよ。例えば、あのSKILL.mdファイルみたいに、何十キロバイトもあるようなもの。無駄に冗長で長ったらしいから、LLMが賢くなるわけじゃないからね。(賢くならないし、ただ無関係なもので文脈が薄まるだけ。)
自分のモデルをトレーニングしていない限り、この方言を常に文脈に送らなきゃいけないんじゃない?モデルはインターネット上の人間の言語テキストでトレーニングされてるから、君の専門的なものじゃないし。結局、人間の言語を使って定義する必要があるってことだよね?それを定義したら、あいまいさを減らすことはできるかもしれないけど、その仕様を持ち歩く必要があるみたいだね。
Codexにはすでにそんな言語があるよ。私のために書いてくれた仕様には「dedupe」や「catch-up」が満載で、もっと冗長な言葉を使うようにフィードバックすることが多いんだ。そういうのが私の言葉遣いにも少しずつ入ってきてる。私の同僚が突然「今日」という言葉をいつも使うようになったけど、彼がClaudeをよく使ってるからだと思う。今日、つまり、コードの現在の状態のことね。
今日、hnのどこかで言及されてたけど、なんでトークンの使用が気になるの?私は日夜AIにコーディングや他のことをプロンプトしてるけど、Claude Code Max 200やMistralを使ってて、何ヶ月も問題がないよ。
それにしても、LLMはこの方言でトレーニングされる必要があるんじゃない?もしトレーニング素材がほとんど曖昧だったら、どうやってそれを明確にしてトレーニングするの?私の中では、これは異なる問題を解決することだと思ってる。私たちは、曖昧な意味から意図を読み取ってほしいんだ。だって、それが人間の考え方や話し方だから。自分がそう思ってない人は、自分を理解してないだけだよ。もしLLMのために簡潔で明確な言語を作ったら、彼らは人間とじゃなくて、お互いに使うことで一番利益を得るんじゃないかな。さらに、彼らはすでにプログラミング言語を使って、コンピュータとやり取りするための簡潔で明確な表現をしているよね。これをどうやって意味のある形で改善するのか、十分なトレーニングデータがあっても難しいと思う。これは本当に真剣に聞いてるから、私が理解しているわけでもないし、もっと知っているわけでもないから。
> 十分に詳細な仕様はコードだ これはまさにブルックスの「ノー・シルバー・バレット」の主張だね。今でもその考えは変わらないけど、多くの人がそんなに詳細な情報を必要としていないのが現実だと思う。AIに「To-Doリストアプリを書いて」とプロンプトを出すとき、実際には「今まで考えた中で一番いいTo-Doリストアプリを書いて」という意味なんだよね。だから、詳細な仕様は本当に必要ない。
でも、もしそのタスク管理アプリを売るつもりなら、ルールは違ってくるし、その仕様書は必要だね。お金を稼ぎたいのか、他と競争したいのかによると思う。
> AIに「タスク管理アプリを作って」と頼むとき、実際には「今まで考えた中で一番いいタスク管理アプリを作って」という意味なんだよね。だから、詳細な仕様は必要ない。もし誰かが真剣にタスク管理アプリを作ってほしいと頼んでいるなら、既存の数多くのアプリとは違うことをしたいと思っているはず。それを説明する必要があるけど、それが可能かどうかは分からない。
そうだね。これは、トレーニングデータに無数の最先端「タスク管理」アプリが含まれているから起こる現象だ。この議論は他の種類のソフトウェアにはうまく当てはまらないよ。
みんな、ボタンを5px右にしたり左にしたりしたいっていう人の話は聞いたことがあるよね。次の会議では、今度はそれを隅の方に持っていきたいとか言って。機能的には全然違いがないのにね。でも、そういうのって技術的な理由からじゃなくて、ただあなたを試したいからなんだよね。「できるからやる」って感じ。後で再交渉したり、文句を言ったりして、もしかしたら安く済ませたいから。技術的な理由じゃないいろんな理由があるんだ。
自然言語は流動的で曖昧だけど、コードは堅固で決定的だ。仕様書主導の開発は、両方のいいとこ取りのように見えるけど、実際には両方の悪いとこ取りなんだ。LLMは言語モデルで、彼らの画期的な能力は自然言語を扱うことにある。コードは明確で決定的であるべきものだし、仕様書は流動的でも決定的でもない。
認知的不協和は、管理のための仕様書とエンジニアリングのための仕様書の間の緊張から生じる。著者が言う通り、支持者たちは前者を売り込んでいるけど、実際に機能するのは後者だけなんだ。マネージャーにとって、仕様書は誰かに任せるためのチケットみたいなもので、割り当てて終わり。でも、ビルダーにとっては、コードと共に進化する思考ツールとして存在して、理解や思考を深めるためのものだと思う。ビルダーの中には、楽だからマネージャーのように考え込まされている人もいるけど、すぐに気づくと思うよ。
これが本当なら、私たちは - コードを削除して、仕様書からやり直せるはずだよね。でも、誰もそんな準備はできてないと思う。 - ソフトウェア製品やビジネスを買って、ただフォルダにマークダウンファイルがあるだけで満足できるはずだ。
毎日コードを削除することを試している人の話は聞いたことがあるけど、マークダウンファイルだけで構成された製品にお金を払って満足している人の話は聞いたことがないな。エージェントのスキルファイルにはお金を払う人がいるかもしれないけど、スキルはリニアとは違う製品だからね。
これは「コードがデザインだ」として説明されているよ - https://www.developerdotstar.com/mag/articles/reeves_design_... by jack reeves。彼らが言うように「すべてはまた巡ってくる」ってね。
こんな風に国を表現するのは好きじゃないけど、北米やヨーロッパの国々に比べて、ちょっと発展途上の国々はAIに対してよりポジティブな見方をしているように感じる。
ビジネス要件と技術要件を切り離すのは大事だよね。完全に分けるのは難しいことも多いけど、余計な技術的詳細が中心の価値提案や顧客の懸念を完全にかき消してしまう会議には何度も参加したことがある。仕様書には「誰が、何を、どこで、いつ、なぜ」を書くべきで、コードは「どうやって」を示すべきなんだ。コードは仕様の不完全な投影であり、それが特徴でもある。ある程度切り離さないと、全てがすごく脆くなっちゃうよ。ビジネスアナリストが最終製品でどのSQLiteプロバイダーを使うかを心配する必要はないんだから。コードを仕様と同じにしようとすると、みんなが常に全てを知っていなきゃいけなくなる。小さなテックスタートアップではうまくいくかもしれないけど、他の場所ではうまくいかない。
この1ヶ月くらい、CodexとClaudeのコードを試してみたんだ。重要な変更をするために最終的にたどり着いたワークフローはこんな感じ。 - 自分でコード内のデータ構造を定義する。各struct/enum/fieldが何をするのかコメントを追加する。 - 使用するクラス/トレイト/関数/インターフェースの定義を書く。定義をそのままにするか、小さかったり重要だったりする場合は自分で書く。 - テストのシグネチャを書いて、何を検証しているのかコメントを付ける。理想的には自分でテストを書くべきだけど、短い場合は空のままでもいい。 - その後、エージェントを関与させて、ほとんど何も指定せずに変更を完了するための計画を立てさせる。計画を実行して、すべてのテストとリンティングがグリーンになるまでエージェントに繰り返し作業させる。 - エージェントの変更を確認して、クリーンアップを行う。大抵は細かいところの修正や自分のスタイルに合わせるための変更だけど。変更が小さければ、あまり曖昧なプロンプトを書くのと同じくらいの時間でCopilotだけで終わらせられることが多い。変更が大きければ、エージェントに全部やらせるか、自分で楽しい部分をやって、エージェントに退屈な部分を仕上げさせるか。だから、タイトルや投稿の要点には賛成だけど、ちょっと違う理由でね。
これは、作っている機能のいくつかの領域には確かに当てはまるという主張もできるかもしれない。でも、どんなタスクにも、仕様がコードよりも説明が少なくても十分な場合があるんじゃないかな。多くの解決策が「十分良い」から。例えば、私にとっては、プロダクションアプリケーションの統合テストがそう。単一行で仕様を記述できて、コードよりもずっと密度が低いし、LLMsのコードは十分良い。どのようにアサートするかは気にしないけど、要点さえあればいい。真実はその間にあるのかもしれないね。