- コードと自然言語による説明を一つの叙述として編み上げる**リテラルプログラミング(Literate Programming)**は、コードと説明の二つを並行して保守しなければならない負担のため広く使われてこなかったが、AIコーディングエージェントがこの中核的な労働を取り除ける
- Emacs Org Mode の
org-babel を通じて多言語リテラルプログラミングが可能だが、大規模プロジェクトではソースコード抽出(tangling)の煩雑さが限界となる
- エージェントにOrgファイルベースの**ランブック(runbook)**作成を指示すれば、説明で意図を書き下し、コードブロックを対話的に実行し、その結果を文書に保存するワークフローが可能
- エージェントが説明・コード間の同期と tangling を自動処理するため、コード変更時に説明を書き直す手間が消え、LLMが最も得意とする翻訳・要約能力を活用できる
- エンジニアの役割がコード記述からコード読解中心へ移行する流れの中で、エージェントが維持する叙述型コードベースの実用性が重要な問いとして浮上している
リテラルプログラミングの概念と限界
- リテラルプログラミング(Literate Programming) はコードと自然言語による説明を混在させ、事前知識のない読者でもコードベースを一つの叙述として読み、動作の仕組みを理解できるようにするアイデア
- 魅力的な概念ではあるが、実際にはコードそのものと説明という二つの並行した叙述を維持する負担が生じ、これが採用を妨げてきた根本原因
- 実務で最も一般的な形はデータサイエンスコミュニティのJupyterノートブックで、説明と計算、結果がWebブラウザ上に一緒に表示される
Emacs Org Mode とリテラルプログラミング
- Emacs Org Mode は
org-babel パッケージを通じて多言語リテラルプログラミングをサポートし、任意の言語を実行して結果を文書にキャプチャできる
- ただしこの方式は、少数の熱心な利用者にだけ残っているニッチなパターン
- 大規模ソフトウェアプロジェクトでOrgファイルをソースの真正本(source of truth)として使うと、ソースコードは事実上コンパイルされた出力物となり、編集のたびにコードを抽出("tangle")して目的地に配置しなければならない
- 自動化は可能だが、ユーザーやエージェントが実際のソースを編集した後、次の tangle 時に上書きされる問題が起きやすい
エージェント以前の活用パターン
- 個人設定の管理にリテラルプログラミングを使って十分な成果があったため、LLM登場以前からこのアイデアを捨てていなかった
- 手動テストとノート作成に Org Mode を使うパターンとして、コマンドラインの代わりにエディタでコマンドを書いて実行し、各ステップが正しい状態になるまで編集したうえで結果をその場に保存する
- 「ノート作成とテスト実行を組み合わせれば、テスト完了時にノートが無料で生成される」
エージェントとともに生まれる新しいワークフロー
- Claude、Kimi などのコーディングエージェントはOrg Mode の文法をよく理解しており、Org は寛容なマークアップ言語なので LLM が非常に扱いやすい
- Org Mode の膨大な文法は人間にとっては欠点だが、言語モデルにとっては問題ではない
- 機能テスト時にエージェントへOrgランブックの作成を依頼すると:
- 説明には各ステップの意図に対するモデルの省察が含まれる
- コードブロックはレビュー後に一つずつ、または全体をスクリプトのように対話的実行できる
- 結果はコードの下に Jupyter ノートブックのように保存される
- 説明を編集してモデルにコード更新を求めたり、コードを編集してモデルが説明に意味を反映したり、エージェントが両方を同時に変更することもできる
エージェントが取り除く中核的な労働
- tangling 処理をエージェントに任せれば、コード抽出の問題も解消される
AGENTS.md ファイルによって、エージェントに Org Mode ファイルをソースの真正本として扱い、常に説明を書き、実行前に tangle するよう指示できる
- エージェントはこれらすべての作業に習熟しており、コード修正後に説明を書き直すことに決して疲れない
- リテラルプログラミングが広く使われなかった根本的な追加労働をエージェントが取り除き、これは LLM が最も得意とする翻訳と要約の能力を活用するものでもある
期待される利点
- コードベースをさまざまな形式へ**エクスポート(export)**して、読みやすい形で利用できる
- エンジニアの主要な役割が書くことから読むことへ移行しているなら、特に重要
- データで裏づけられているわけではないが、各コードブロックの意図を説明する叙述がコードとともにコンテキストに現れるため、生成されるコードの品質も向上する可能性があると推測される
- 現時点では大規模で本格的なコードベースでは試しておらず、テストと手動プロセスの文書化ワークフローで活用している
Org Mode の限界と代替案
- Orgフォーマットは Emacs と密接に統合されているため制約要因であり、Org は Emacs の外に出るべきだという長年の信念がある
- 代替として Markdown を勧めたいが、Markdown にはメタデータを含める機能が不足している
- Org Mode の Properties という概念は、文書を Emacs Lisp でプログラム的に操作できるようにし、今では LLM がその文書専用のカスタム機能をfile variables セクションに Emacs Lisp で記述してくれる
- Markdown には、コードブロックの実行詳細(どこで実行するか、リモートマシンかなど)を指定する Org Mode の header arguments のような機能がない
- 興奮を覚えるのは Emacs の具体的実装ではなく、アイデアそのもの
核心の問い
- 「エージェントを通じて、叙述のように読める大規模コードベースを持ち、コード変更と説明の同期状態を疲れを知らない機械が維持することは、実用的になり得るのか?」
2件のコメント
Hacker News の意見
LLMに自分でコメントを書かせる方式がいちばんシンプルだと思う
こうするとLLMがあとでコードを読み返すとき、自分のコメントを参照できて、一種の**即時型長期記憶(just-in-time memory)**として機能する
<summary>には要約を、<remarks>には理由と文脈を、<params>には制約事項を書かせ、インラインコメントは最小限にするこうすればPRレビュー時にLLMの思考過程を
<remarks>で直接確認でき、意図と異なる理解をした箇所を見つけやすい結局は自分のコンテキストを無駄な情報で汚し、理解力まで落としてしまう
まだ人間レベルの**リテラシー(literacy)**にはほど遠い
でもLLMが同じコードを読み返すときに引っかかるのはまさにこういうコメントなので、むしろ価値ある情報なのかもしれない
だからこうしたコメントがその記憶を保存する役割を果たす
自然言語は曖昧だからこそプログラミング言語が生まれたのだと思う
だからコードコメントも結局は曖昧になるし、実行されないのであっという間に古くなる
LLMはコード翻訳には強いが、自然言語のプロンプトをコードに変えるのは依然として難しいと感じる
良いコードは意図を明確に表現すべきで、コメントが多いのはコード品質が低いサインかもしれない
しかし良いソフトウェアには良いドキュメント化も含まれるべきだ
文学的プログラミングは実装の詳細よりも説明を中心にした文章である
コードでは「どのように」を狭く定義するが、自然言語では「何を」を中心に表現できるため、LLMがより良い方法を提案する余地がある
冗長な情報があってこそ、誤りを検出し修正できる
ただ解釈の自由度を狭めるルールを置いているだけだ
ときには比喩や曖昧さのほうが適切な表現になることもある
サンプルコードと文書をテンプレートとして与えると、**ハルシネーション(hallucination)**が減る
文学的プログラミング風のコメントが人間のコード理解を助けるという研究がある
Googleの研究者たちが、LLMがこうしたコメントを更新できるか、またそれが人間の理解に役立つかを実験した
結論は、意図を説明するブロックレベルのコメントが最も効果的だということ
(参考: 2024 arXiv 論文 "Natural Language Outlines for Code")
最近の興味深い現象として、以前は人間のためにREADMEやアーキテクチャ文書を書くのを面倒がっていたのに
いまはLLMのために書くと言うと、人々がずっと積極的になるという点がある
しかしLLMは作業のたびに文書を参照するので、文書化の動機がはるかに強くなる
コミットメッセージやADRのような記録は人間は見なくても、LLMは全部読む
結局こうした習慣は人間の新人にも役立つことになる
コンピュータと話す方法を学ぶことに気を取られ、人間と話す方法を身につけ損ねた人たちは、卒業後にさらに遅れを取ったという話だ
コードが動くのに文書の正確さは必要ないからだ
だから文書よりコードを直接見るほうが良いと感じることがよくある
私は軽量な文学的プログラミングと規約中心の言語の組み合わせが、エージェント時代によく合うと思う
Goのように高速コンパイルで明確なスタイルガイドがある言語がよい
エージェントにコードを書かせるとき、Google Go Style Guide を参照させるとかなり良い結果が出る
(参考: Rob Pike に関する逸話)
LLMは言語モデルなので、明確な文章への投資には大きな価値がある
必ずしも文学的プログラミングまで行かなくても、良い名前、docstring、型シグネチャ、「なぜ」を説明するコメントが重要だ
結局のところ重要なのは、人間とLLMの両方に向けたコミュニケーションパターンを作ることだ
ファイル・ディレクトリ・プロジェクト単位の上位構造を説明する文書が特に重要だ
ただしこうした概念は複数ファイルにまたがるため、どこに書くかと文書とコードの同期が常に問題になる
この10年間、ほぼすべてのコードを文学的プログラミング方式で書いてきた
nbdevを作り、ノートブックベースでコード、文書、テストを一緒に管理している
最近はLLMを統合した Solveit というツールを作り、会社全体で使っている
(Solveit リンク)
文学的プログラミングはプログラミング以外の業務にも有用だ
短いデモやスクリーンショットを追加するとよいと思う
LLMを使ってコメントとコードの不一致を自動検出するアイデアは興味深い
文書は時間がたつと必ずコードとずれていくが、それを自動で検出できれば大きな価値がある
こういうものでスタートアップを作れるかもしれない
変更は文書PRから始め、開発者がコードに反映する
レビュー時には文書とコードを並べて表示し、検証できるようにする
文書間リンクによって文脈探索も可能にする設計だ
例: GitHub gh-aw, Continue.dev
テストコードと本番コードの対構造は、会計における複式簿記のように有用だ
テストがコードの意図を説明し、コードがテストの意味を補完する
レビュー時に片方がわかりにくければ、もう片方を見ればよい
欠点はコード量が増えることだが、可読性の向上にはそれだけの価値がある
私も最近、意図ベースのコーディングについて記事を書いたが、この議論と通じるものがある
(ブログリンク)
コードベースをさまざまな形式に読みやすく変換できる点が重要だ
今後は非専攻者もコードにもっと近づくだろうし、自然言語の取り込みが彼らの生産性と学習に大きく役立つだろう
Wikipedia - リテラルプログラミング
> リテラルプログラミング(literate programming)はプログラミング方法論の一つであり、プログラミングを行う際に、コンピュータでコンパイル可能なコードを作ることよりも、人が理解しやすいコードを作ることに重点を置く手法である。言い換えれば、人が見て理解できるように文書を作るようにプログラミングすることが目的である。「まるで文学作品を読むようにプログラミングを読めるようにすること」が目標であるため、「リテラルプログラミング」という名前が付けられた。