この件について、私自身の結論は非常に明確です。AI は、初期設計や依存関係の決定をすべて肩代わりするのではなく、急速に推進力のあるペアプログラマーとして適しています。GitHub のドキュメントでは、最初はより簡単なタスクから始めるよう推奨しており、エージェントにバグ修正、ドキュメント作成、テスト、技術的負債といった境界がより明確な作業を先にこなしてもらうべきだと述べています。一方、Anthropic の Plan Mode のドキュメントは、むしろ複雑な変更に対する保険のようなものであり、「まずコードを読み、計画を立ててから、修正するかどうかを決める」という流れです。両者の主張は完全に一致しているわけではありませんが、指し示す方向性は似ています。最初から最も難しく、最も混沌としていて、依存関係が最も多い塊をすべてAIに丸投げするのは避けるべきです。
そのため、この記事では大量の仕様を語るのではなく、すぐに手を動かせる小さなケーススタディを提供します。任意の空のC++リポジトリがあれば、これに従って作業できます。
AIじゃないからダメなのではなく、最初の一手が貪欲すぎるからだ
人工知能のプロジェクト、特にC++の場合、多くの時は非常に原始的な方法になりがちです。
- まずは
main.cppから最小実行可能なバージョンを始める - まずコンパイルのリンクを通す
- その後、どのライブラリを導入するか決める
- 一歩進むごとにビルドできることを保証する
- ビジネスの輪郭が見えてから、リファクタリングを開始する
この方法は遅く見えるかもしれませんが、実際は非常に安定しています。なぜなら、どのステップで何を得たのか、そして問題がどのステップから生じているのかをすべて知っているからです。
AI はこのリズムを崩しやすいです。一気に「完璧に手伝ってくれる」のが好きなんです:
- 設定ファイルもついでに用意したよ
- ログモジュールもついでに取り出したよ
- エラーコード、ユーティリティクラス、ディレクトリ構造もまとめて整理したよ
- サードパーティライブラリの組み込み方法も、代わりに選んでおいたよ
結果として、デモは完成しているように見えても、あなたのメンタルモデルは空っぽである。その後、ライブラリの能力境界とあなたが考えていることに少しでも食い違いがあると、手直しが必要なのは一点ではなく、連続したものになってしまう。
まずは小さなプロジェクトで練習する
個人的には、練習に最適だと思うのは、非常に小さなログスキャンツールを作ることです。名前は適当でいいですが、例えば logscan のようなものです。
それはただ一つのことをします。あるディレクトリ内のログファイルをスキャンし、error と warn の数を数え、その結果を出力するだけです。この問題はそれほど大きくありませんが、C++の小規模プロジェクトで最も一般的ないくつかの部分をすべて通るのにちょうど良いものです:
mainと引数エントリポイント- 出力フォーマット化
- ログ
- 設定ファイル
- ビジネスモジュールの分割
重要なのは問題がどれだけ高度かではなく、分解の方法です。
これを4つのステップに分割し、各ステップではAIが現在の小さな一歩のみを行うようにします。
ステップ1:まず出力を準備する
最初のステップは、ログや設定には触れず、抽象化を考えないことです。
2つのことをする:
- 最低限の
main.cppを作成する fmtをインポートし、スキャンしたディレクトリと統計結果を出力する
fmt の公式ドキュメントには、非常に明確な CMake の使い方が記載されています。そこには fmt::fmt と fmt::fmt-header-only という2つのターゲットがあり、ドキュメントではコンパイル版をより推奨していると明記されており、その理由は単純で、ビルド時間がより親切だからです。CMake の FetchContent のドキュメントも新しいプロジェクトの開始に非常に適しています。なぜなら、これはビルド段階になってから一時的にダウンロードするのではなく、configure 段階で依存関係を読み込むからです。
このステップでは、依存戦略を固定し、AIに自由に発揮させません。
FetchContentを統一する- または
find_packageを統一する - いざという時に vcpkg、いざという時に
add_subdirectory、そしてまた手動でヘッダーファイルをコピーするのはやめてほしい
もし練習用のプロジェクトであれば、私はAIにこのように制約をかけます:
アーキテクチャを一度に最適化しないでください。
現在の目標はこのステップのみであり、プロジェクトは常にコンパイル可能でなければなりません。
このステップでは以下の3点のみを行います:
1. ルートの CMakeLists.txt に fmt を導入する
2. main.cpp で渡されたディレクトリとスキャン結果を fmt で出力する
3. 既存のターゲット名とディレクトリ構造を維持し、ログ、設定、テストフレームワークは追加しない
まず修正リストを提示し、その後コードを提示してください。
完了したら、ビルドコマンドと期待される出力を提示してください。
ここに重要な詳細があります。AIは、制約がない場合、「ついでにこれもやった」ということを加点要素として扱いがちです。今回のラウンドでは範囲を超えてはいけないと明確に伝える必要があります。
ステップ2、ログのアップロード
まずステップとして、コードが書けて、動いて、出力も綺麗になったら、spdlogを追加する。
spdlog の公式 README は、実際何ができるかを非常に分かりやすく記述しています。コンソールログだけでなく、通常のファイル、ローテーションファイル、日付ごとの分割、さらにはバックトレースリングバッファまで対応できます。問題はここです。機能が多すぎると、AI は興奮しすぎてしまい、まるで初版でカラーコンソール、ローテーションログ、日付アーカイブ、グローバルロガーファクトリを全部盛り込みたがるのです。
不要です。
このステップでは、コンソールログを出すか、せいぜい最もシンプルなファイルログを追加するだけです。なぜなら、ここで本当に学ぶべきことは、「どうやってロギングシステムを完全に設計するか」ではなく、以下の3点だからです。
- ロガーの初期化はどこで行うべきか
- ビジネスロジック内でどのようにロガーを取得するか
- エラー発生時と通常出力時のログの役割分担はどうすべきか
もし最初から rotating_file_sink や daily_file_sink を使うと、「機能がとても充実した」ロギングモジュールを手に入れたように感じますが、実際にはローテーションや日付ごとの分割が必要なのか、それともデバッグ段階でターミナルに出力するだけで十分なのか、自分自身がまだ分かっていないかもしれません。
要するに、ログファクトリをいかに美しく描くかよりも、まずspdlog::info()の使い方を理解することがより重要です。
ステップ3、設定ファイルに触れる
設定ファイルの部分は、AIによって大規模なプロジェクトになりやすいです。
私は、それが「最強」だからというよりは、新しいプロジェクトの初期段階に適しているから、toml++ のようなシンプルなライブラリで練習したいと思っています。それ自体が C++17 のヘッダーオンリーな TOML パーサーであり、README に記載されている例も非常に短く、toml::parse_file("configuration.toml") で直接読み込めます。さらに重要なのは、単一ヘッダーファイル形式が本当に手間いらずなことです。公式の説明文もとても面白いのですが、シングルヘッダーのソリューションは「toml.hpp をソースツリーに放り込むだけ」で、「第二の手順はありません」。
このステップでは「設定センター」は行わず、以下の3つのフィールドを読み込んでください:
- スキャンディレクトリ
- キーワードリスト
- 出力はファイルに書き込むか
そしてそれらを非常に薄い AppConfig 構造体に詰め込みます。
それで十分です。
多くの手戻りは、実はここから生じているんです。設定を起動時に一度読み込むのか、実行時にホットアップデートするのか。ローカルのCLI専用なのか、それとも将来的にサービスプロセスで再利用するのか、ご自身でまだ明確に考えていない。AIはすでにあなたのために5、6層も処理してくれました。後から方向性を変更すると、これまで積み上げてきた「完璧な設計」がすべて重荷になってしまいますよ。
ステップ4:ビジネスモジュールの分解
例えば、fmt、spdlog、toml++ などはすべて自分で公式ドキュメントを一度確認し、実際に動作テストを行った上で、AIにモジュール分割を手伝ってもらう、といった具合です。
この時分解すると、心に余裕ができます。
通常、私は以下のようなファイルを収集します:
main.cppはアセンブリのみを担当するapp_config.{h,cpp}は設定の読み取りのみを担当するlogger.{h,cpp}はログの初期化のみを担当するlog_scanner.{h,cpp}に業務ロジックを配置する
注意点として、この段階になってから分割するものであり、最初から分割するわけではありません。最初のステップで目次をきれいに並べることは、多くの場合、視覚的に心地よいだけであり、認知的な明確さが増すわけではありません。
本当に役立つのは、複雑な規範ではない
インターネット上には、AIのコーディング規約が非常に複雑なものが多くて、十数項目、数十項目とあって、見るだけで疲れますね。私が今残したものは、実はたった3つだけなので、これで十分だと思います。
第1条、まず「ライブラリカード」を作成します。
サードパーティライブラリを準備するたびに、私はまずAIに以下の4つの質問だけを回答するようにしてもらいます。
- このライブラリは何の問題を解決しますか
- 公式版はどこまでサポートしていますか
- 今回はどの機能の 1 つか 2 つに絞って使いたいと思っています
- ビルド、デプロイ、実行にどのような制約をもたらしますか
このカードが分からない場合は、とりあえず受けないでください。
第2条、一度にAIを一つのチェックポイントだけに通す。
例えば、このラウンドではこれだけを完了させることを許可する:
- コーディングできる
- 実行できる
- 期待される出力を確認できる
同じラウンドで「ついでにディレクトリをリファクタリングする」「ついでに設定クラスを追加する」「ついでに例外処理の仕組みも統一する」といったことをするのはやめてください。C++プロジェクトでは、「ついで」というものが、問題の原因箇所を汚染しやすくなります。
第3条、各ラウンドでロールバックポイントを残すこと。
コミットしなくても、以下の質問に答えられる必要があります。
- このステップで具体的に何が変わったのか
- 間違っていた場合、どこを削除する必要があるか
- 一つ前のステップに戻した場合、プロジェクトはまだ編集可能か
気づくと、この考え方は実は手動での開発と非常によく似ています。違いは、以前は自分でコードを書いていたのに対し、今はAIが暴走しないように見張っているという点だけです。
より実戦的なAIの活用方法
この一連のものを本当に習得したいなら、3周連続でやることをお勧めします。
第1ラウンドは、AIにfmtの補完だけを任せて、残りは自分でCMakeの設定と出力コードを読み直してください。
第2ラウンドは、AIにspdlogのみを扱わせてください。コンソールログにするかファイルログにするかは自分で決めてください。両方同時に使うのは禁止です。
第3ラウンドは、AIにtoml++の受け渡しのみをさせ、設定項目は自分で決め、AIに将来のニーズを推測させることは禁止とする。
この3周を終えると、AIプログラミングに対する感覚が大きく変わるでしょう。前は「どうしてこんなにたくさん生成してくれるんだ」という感じだったのが、徐々に「次のステップをどれくらい小さくすれば最も効率的か」という視点になるようになります。
これが今のAIプログラミングで最も価値のある能力だと思います。
デモを出すわけではない。
むしろ、一つのプロジェクトを確実に前進させる。
正直なところ、このやり方は目新しくなく、むしろ古臭いかもしれません。しかし、古い方法は再作業に強い傾向があります。特にC++のような言語では、AIに少し任せる部分を減らして、自分で確認する部分を増やすと、後が本当に楽になります。そうしないと、3分で飛び立っても、3時間かけてやり直すのは自分自身ですからね。
参考資料
- Anthropic, Claude Code Common Workflows
- Anthropic, Claude Code Overview
- GitHub Docs, Best practices for using GitHub Copilot to work on tasks
- CMake Docs, FetchContent
- {fmt} Get Started
- gabime/spdlog README
- gabime/spdlog Wiki: Sinks
- marzer/tomlplusplus README
作成上の注記
元のプロンプト
プロンプト:人間がプロジェクトを構築する際、C++のようにフレームワークを使わない言語の場合、まず
mainからロジックを展開していく「骨格」を作り、徐々に設定ファイル、ログモジュール、反復的なビジネスモジュールなどを追加していくのが良いと思います。私の習慣としては、毎回コンパイルが通ることを確認し、段階的にリファクタリングを進めることです。最初から最適解である必要はありません。AIによるプログラミングは、今や多くのケースで工程を飛ばしたり、初期の思考が不足したりしがちです。特に新しいサードパーティライブラリを導入する場合、AIはすぐにデモを出せますが、私が新しく導入したサードパーティライブラリの詳細な仕様やサポートする機能が不明確なため、関連ロジックの作り直し(手戻り)率は人間による開発よりも明らかに高くなります。学べるような良い実例はありませんか?インターネット上には複雑なAIプログラミング規約はたくさんあると知っていますが、私はもっとシンプルで、すぐに適用できるものが欲しいです。
ライティングのアイデア概要
- トピックを
toolingレーンに絞り、AI がワークフローを変えた後、どこが楽になり、逆にどこが不自然になったかを重点的に書く。 - 一般的な規範リストではなく、C++ の小規模プロジェクトの段階的な練習事例に変更する。
- ユーザーが「
mainから始め、各ステップでコンパイルでき、徐々にリファクタリングできる」という核となる判断を維持し、これを記事全体のメインラインとする。 - Anthropic、GitHub、CMake、fmt、spdlog、toml++ の一次資料を補完し、ツールの機能や依存方法について憶測するのを避ける。
- 記事の構成は
fmt -> spdlog -> toml++ -> モジュール分割の順に進め、意図的に AI に一度で全てを解決させないようにする。