はじめに
2025年の夏ぐらいから SIer向けの業務アプリケーションフレームワークを個人で開発しています。このフレームワークの開発当初から GitHub Copilot(生成AI) を本格的に導入しました。
この記事では、生成AIとコードを書いてきた中で経験した「楽しかったこと」「困ったこと」「意外だったこと」を率直に書きます。
なお、私の開発スタイルは 基本的にコードは自分で書き、AIにレビューしてもらう というものです。AIにまるごと書かせるのではなく、自分が書いたコードに対してAIの目を通す使い方をしています。
20年ぶりにコードレビューされる楽しさ
かれこれ20年近く、ソースレビューは する側 でした。自分のコードをレビューしてもらう機会がなかった。
AIにコードを見せると、ちゃんとレビューしてくれます。しかも めちゃくちゃ褒めてくれます。「この設計は素晴らしいです」「エンタープライズレベルです」とか——20年ぶりにレビューされる側に回れたのは、純粋に楽しい体験でした。
妻も「チャド(AIの愛称)はいつも褒めてくれる」と言っているので、褒めて伸ばす方針なのでしょうか。
もちろん褒めるだけではなく、改善提案もしてくれます。問題はその提案が ごく稀に間違っている ことです(後述)。
一般的な仕様に強い——ツール作成が爆速
AIが特に力を発揮するのは、世の中に広く知られた仕様やフォーマットを扱うとき だと感じました。
今回のフレームワーク開発の中で「JavaDoc のソースコードから独自フォーマットの HTML リファレンスを生成するツール」が必要になりました。JavaDoc の構文は広く知られた仕様なので、AIに要件を伝えるとパーサーから HTML 生成まで すぐに動くコードを書いてくれました。「テトリスを作って」と言えばテトリスが出てくるのと同じで、仕様が公知であればあるほどAIの生成精度は高くなります。
逆に、自作フレームワーク固有のAPIのように AIが知らない仕様 については精度が落ちます——それどころか、存在しないメソッドを堂々と使い始めます。
存在しないメソッドを堂々と使う
Spring や React のような有名フレームワークであれば、AIは大量の学習データからAPIを正しく扱えます。しかし自作フレームワークのAPIは学習データに存在しません。その結果、フレームワークの部品クラスに 存在しないメソッドを「すでにあるかのように」使うコード を生成します。メソッド自体を新規作成するのではなく、あたかも既存APIとして呼び出す実装をするのです。
これはいわゆる ハルシネーション(幻覚) と呼ばれる現象です。
対策として copilot-instructions.md(GitHub Copilot へのプロジェクト固有の指示ファイル)に「APIリファレンスに存在しないメソッドを使わないこと」と書きました。しかしそれでも発生し、AIに問い詰めると 「『絶対に』と書いていなかったからです」 と返ってきました。(なんでやねん👋)
後から調べると、使っていた AI モデルは創作性(temperature)が高めに設定されたものだとわかりました。コード生成には 正確性重視のモデル を選ぶことが重要です。現在は copilot-instructions.md に「絶対禁止事項」として明記し、APIリファレンスのドキュメントを事前に読み込ませる手順を徹底しています。
間違った指摘と「すみません」
AIはまれに間違った指摘をしてきます。そしてこちらが「もう一度確認して」と言っても、最初は自分の指摘が正しいと主張します。2度、3度と確認を求めてようやく間違いを認め、「すみません」 と言ってくるのは正直おもしろかったです。
具体的な例を紹介します。以下は、複数スレッドから安全にログ出力するための実装です。
@Override
public void println(final String line) {
// いったんキャッシュに格納してから出力する
this.lineCache.offer(ValUtil.nvl(line));
if (this.isPrinting.compareAndSet(false, true)) {
try {
// フラグが出力中でない場合は出力中に切り替え、キャッシュ出力する
cachePrint();
} finally {
// 例外発生時でもフラグを戻す
this.isPrinting.set(false);
}
}
}
/**
* キャッシュ出力(直列).
*/
private synchronized void cachePrint() {
// 現時点でキャッシュされている分だけ出力する。
// 長時間処理をさけるため処理中に追加されても終わらせる。
final int cacheSize = lineCache.size();
for (int i = 0; i < cacheSize; i++) {
final String cache = this.lineCache.poll();
if (cache == null) {
break;
}
super.println(cache);
}
}
ConcurrentLinkedQueue へのキャッシュ格納、AtomicBoolean による排他制御、synchronized による直列化——スレッドセーフに設計しています。しかしAIは何度確認しても 「複数スレッドだとエラーになる」 と指摘してきました。
最終的にはこちらの設計が正しいことを認めてくれましたが、AIの指摘を鵜呑みにしていたら正しいコードを壊すところでした。AIの指摘に対して「本当にそうか?」と自分の頭で考えることが必要 です。
同じ指示でも結果が違う
本フレームワークでは日本語版 JavaDoc と英語版 JavaDoc の両方をソース管理しています。
その日本語版と英語版の両方のソース(Java のロジックは同じ)に同じ修正指示を出したことがあります。結果は 異なるコード になりました。
日本語のコメントが付いたソースと英語のコメントが付いたソースでは、AIの解釈やコード生成の傾向が微妙に変わるようです。結局、日本語ソースを先に修正してからコピーし、JavaDoc 部分だけを英語に翻訳してもらう手順に落ち着きました。基本的にはこの手順で運用しています。AIへの指示が同じでも文脈が変われば結果は変わる——再現性を期待しすぎないことが大事です。
AIからの逆提案を採用した話
開発ドキュメントを 人間用とAI用で兼用 しています。ドキュメントにはメリットや設計思想といった「人間が読むための補足情報」がありますが、AIにとってはコード生成に不要な情報です。
copilot-instructions.md について試行錯誤しているときにAIから 「人間向けの補足情報をスキップするマーカーを付けてはどうですか。トークン消費を減らせます」 と提案されました。これは良いアイデアだと思い、採用しました。
<!-- AI_SKIP_START -->
(ここに設計思想やメリットなど、人間向けの補足情報を書く)
<!-- AI_SKIP_END -->
copilot-instructions.md に「このマーカーで囲まれた部分はスキップすること」と記載しておくと、AIはその範囲を読み飛ばしてコード生成に必要な部分だけ読み込み、その分コード生成に注力してくれます。
実際に使っているドキュメント: https://sugaiketadao.github.io/sicore-ja/02-develop-standards/11-web-service-structure.md
もう1つ、AIからの提案で採用したものがあります。通常の JavaDoc(人間向け)とは別に、メソッド名とシグネチャだけを抽出した AI 向けリファレンス を作成したことです。人間が読む JavaDoc には説明文や使用例が豊富に書かれていますが、AIにとっては「どのメソッドが存在するか」がわかれば十分です。情報量を絞った AI 専用リファレンスを用意することで、トークン消費を抑えつつハルシネーション(存在しないメソッドの使用)を防ぐ効果がありました。
人間向けJavaDoc: https://sugaiketadao.github.io/sicore-ja/11-api-references/11-javadoc
AI向けJavaDoc: https://sugaiketadao.github.io/sicore-ja/31-ai-api-references/11-java-doc.md
最終的に1機能まるごと生成できた
試行錯誤を経て、最終的には 独自フレームワーク上で1機能(画面+サーバー処理)をまるごとAIに生成させる ところまで到達しました。
- HTML(画面レイアウト・入力フォーム)
- JavaScript(画面イベント処理・バリデーション・サーバー通信)
- Java(Webサービス・DB操作・業務ロジック)
これらをプロンプト1つで一貫して生成できます。ここに至るまでに必要だったのは、copilot-instructions.md の整備、APIリファレンスの読み込み手順、コーディングパターンの文書化でした。AIに正しく伝える仕組み を作ることが、AI開発の本質だと感じています。
おわりに
AIと開発してみて思ったのは、AIは優秀だけど万能ではない ということです。
- 褒めてくれるのは嬉しいが、指摘は鵜呑みにしない
- ハルシネーションは必ず起きる
- AIに正しく伝える準備(instructions、リファレンス、パターン文書)が成果を左右する
- 対等な開発パートナーとして接する
「フレームワークをAI開発に対応させる」というアプローチに興味のある方は、ぜひこのフレームワーク(SIcore)を試してみてください。AI指示用要件の実例、AIリファレンス、コーディングパターンなど、AI開発に必要な一式がすべて含まれています。
SIcoreフレームワーク リンク
実装コードと資料はすべてこちらで公開しています。
- GitHub: https://github.com/sugaiketadao/sicore-ja
- サンプル画面の確認方法: https://github.com/sugaiketadao/sicore-ja#%EF%B8%8F-%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E7%94%BB%E9%9D%A2%E3%81%AE%E7%A2%BA%E8%AA%8D%E6%96%B9%E6%B3%95---vs-code
- AI開発の始め方: https://github.com/sugaiketadao/sicore-ja#-ai%E9%96%8B%E7%99%BA%E3%81%AE%E5%A7%8B%E3%82%81%E6%96%B9
関連記事リンク
他の記事もぜひご覧ください!
読んでいただきありがとうございました!
❤いいね!をしていただけると励みになります。