LLM にコード生成をさせる前に、まず理解しておくべき前提がある。
それは、LLM は常にステートレスであり、あなたのプロジェクトのことを何も知らないという事実だ。
本記事では、私が最近取り組んでいる
**LLM を用いた開発支援(主に Cursor を通じた利用)**についての思考と、ある程度体系化できた実践内容をまとめる。
最初に結論を述べる。
LLM を「非常に賢いが、プロジェクト背景を一切知らない新人エンジニア」として扱うとき、
その前提条件や暗黙のルールを、どのように伝えるべきか。
まず認識すべき事実:LLM は「記憶を持たない」
HumanLayer の
《Writing a good CLAUDE.md》
に影響を受け、自分の LLM の使い方を改めて見直した。
そこで改めて強く認識した前提がある。
- LLM には長期記憶がない
- プロジェクトの履歴や背景を理解していない
- チーム内の「暗黙の共通認識」を知らない
- すべての対話は、毎回ゼロから始まる
多くの開発者が、次のような錯覚を持ちがちだ。
「何度もやり取りしていれば、だんだんプロジェクトを理解してくれるのでは?」
結論から言うと、それは起きない。
これは能力の問題ではなく、
LLM のモデル設計上の基本的な性質である。
もし LLM に安定して規約通りのコードを書かせたいなら、
次の問いに向き合う必要がある。
人間の開発チームでは、どのような情報が「コード以外」で共有されているのか?
問題の本質:大量の「暗黙的な設計ルール」は LLM には見えない
実際のプロジェクトでは、重要な制約の多くがコードに書かれていない。
- 直接依存してはいけないモジュール
- 特定の Service 経由でしか操作してはいけないテーブル
- 歴史的経緯で存在しているが、もはや使用禁止のフィールド
- このプロジェクトでは採用されなかった設計パターン
これらは通常、
- 個人の経験
- 口頭での申し送り
- Code Review の文化
- ベテランが新人に教える過程
によって共有されている。
人間にとっては低コストだが、
LLM にとっては完全なブラックボックスである。
その結果、よくある現象が起きる。
LLM が生成したコードは
文法的にも構造的にも正しい。
しかし、このプロジェクトでは「不適切」。
これは LLM が劣っているからではない。
背景を一切与えずに、新人エンジニアに自由設計させているのと同じ状況だからだ。
間違った第一歩:「巨大な AI_README.md」を作る
この問題に気づくと、多くの人が次の発想に行き着く。
「すべての規約を 1 つのドキュメントにまとめて LLM に読ませればいいのでは?」
私も実際に試した。
そして、すぐにやめた。
理由は明確だ。
- 文書が大きすぎて注意が分散する
- ルールが混在し、優先順位が分からない
- 更新コストが高すぎる
- 多くのルールが、そのタスクでは 関係ない
これは現実の開発と同じである。
どんなエンジニアでも、
API を 1 本書く前に
会社の技術規約をすべて読むことはない。
問題はルールの量ではなく、LLM へのロードの仕方だった。
エンジニアリング経験を「オンデマンドで読み込める制約」にする
最終的に私が採用したのは、
「大きな一枚岩ドキュメント」ではなく、
構造化され、分割され、組み合わせ可能な制約ドキュメント体系だった。
目的はただ一つ。
正しい文脈で、正しいルールだけを LLM に守らせること。
コア定義ドキュメント(常時ロード・極小)
このドキュメントは、
LLM にコードの書き方を教えるものではない。
次の 3 点だけを明確にする。
- どのような種類のシステムか
- 技術スタックは何か
- 絶対にやってはいけないことは何か
内容は意図的に最小限にする。
- レイヤー境界(Controller / Service / Domain / Infra)
- レイヤー越境の禁止
- 既存フローを無視した直接データ更新の禁止
- 私個人が強く重視している設計思想・コードスタイル
このドキュメントは毎回 LLM にロードされる。
感覚としては、LLM に対して次のように伝えている。
「君はすでにチームの一員だ。これは最低限守るべき基本ルールだ。」
モジュール単位の規約(必要なときだけロード)
ここが、実際の「エンジニアリング経験」が最も集約される部分である。
例としては、以下のようなものがある。
- Service 設計原則
- 承認フローおよびステートマシン設計規約
- DTO / VO / Entity の責務分離
- データ整合性および冪等性の扱い方
特徴は明確だ。
- デフォルトでは LLM にロードしない
- 要件提示時に、明示的に指定する
例えば、次のように指示する。
本タスクでは、以下の規約を同時に遵守すること。
- Service Layer Contract
- 承認フロー設計規約 v2
これは人間に例えるなら、
「この処理は、あのときの承認フローのやり方で進めて」
と伝えるのと同じである。
シナリオ特化ルール(1 つの問題だけを解決する)
さらに、私はルールを極端に小さく分割している。
- 定期ジョブを追加してよい条件
- 特定のレガシーフィールドを使用してはいけない理由
- 一見正しそうだが、過去に事故を起こした設計
これらのルールの特徴は次の通りだ。
- 適用範囲は狭い
- しかし 命中率が非常に高い
- 誤用されにくい
本質的には、
過去の失敗から得た結論を、LLM 向けに固定化したものである。
LLM は「設計者」ではなく「制約下の実行者」
この仕組みが安定してから、
LLM に対する期待値は明確に変わった。
- 自由に設計させない
- 「どう思うか」を判断させない
- 境界とルールを先に与える
結果は、むしろ良くなった。
- レイヤー違反がほぼ消える
- コードスタイルが揃う
- 「高度そうだが、プロジェクトの現実に合わない設計」が激減する
適切に制約された LLM は、次のような存在になる。
理解力には限界があるが、
制約を守って高速に実装する、文句を言わない新人エンジニア。
品質の最終防衛線:テストと人間のレビュー
ここは正直に書いておく。
LLM が生成したコードを、そのまま信頼してはいけない。
私は、次の 2 つを絶対ルールにしている。
- テストがなければ生成しない/採用しない
- 人間のレビューは、実装詳細ではなく「設計やレイヤーを越境していないか」だけを見る
これにより、安定した品質ループが成立する。
- ドキュメントが境界を定義
- LLM が境界内で実装
- テストが振る舞いを検証
- 人間が設計と構造だけを統制
現時点で、これが私にとって
最もリスクが低く、現実的な LLM 活用方法である。
まとめ
LLM にコードを書かせることの本質は、
Prompt Engineering ではない。
人間のエンジニアリング経験を、
構造化し、分割し、LLM が読み込める制約として設計することである。
新人を育てるように、
- ルールを定め
- 権限を制限し
- 境界を明確にする
そうすれば、LLM は
安定し、再現性があり、予測可能な存在になる。