第29章:AI拡張と上手に進める(丸投げしないコツ)🤖🎀

この章のゴール🎯✨
AI(Copilot / Codex など)を**“テスタブル設計(I/O境界の分離)”の味方**にしつつ、 境界の判断は自分で握ったままスピードを上げられるようになることだよ〜😊🫶
29-1. まず大事な考え方:AIは「手」🖐️
、設計は「脳」🧠💗AIが得意🥰
- テストケースの洗い出し(抜け漏れ探し)🧪🔍
- スタブ/スパイ/モックの下書き🧸
- 既存コードの読解・要約・命名案だし📚✍️
- 小さめのリファクタ案の提案(段取りを作る)🛠️🗺️
- 「I/Oが混ざってない?」みたいなレビュー👀✨
AIに丸投げしない🙅♀️
- どこが境界か(中心と外側の線引き)✂️
- 仕様の解釈(「割引って端数どうするの?」とか)📏
- 例外/エラーの扱い方針(ドメイン vs インフラ)🚨
- セキュリティ/個人情報/秘密情報の扱い🔐
- 「それっぽいけど違う」API・古い情報の採用🥲
コツは “AIに作らせる前に、先にルールを渡す” だよ〜💡😊
29-2. 2026年っぽいAI機能の使い分け(知ってるだけで勝ち)
🏆✨## ① Copilot Edits:複数ファイル編集の2モード🧩
🧹* Edit mode:触らせるファイルを自分で選んで、提案を見ながら進める(コントロール重視)🫶
- Agent mode:タスクを渡すと、Copilot が自律的に編集&必要ならコマンド提案までして進める(スピード重視)🚀 (GitHub Docs)
👉 テスタブル設計ではおすすめ運用はこれ👇
- 境界を作る/変える作業 → まずは Edit mode(暴れにくい)😊
- ルールが固まった後の機械作業(テスト追加、命名揃え、薄いアダプタ量産) → Agent mode 🚀 (GitHub Docs)
② VS Code の Agent Skills(実験機能)
:AIに“家庭教師プリセット”を渡せる📁🧠VS Code 1.108(2025年12月アップデート)あたりで、**Agent Skills(実験)**が入っていて、
「フォルダに置いた指示・スクリプト・資料」を Copilot が必要に応じて読み込める、みたいな方向が進んでるよ〜📦✨(設定キー chat.useAgentSkills)
(Visual Studio Code)
これ、テスタブル設計と相性バツグンで👇
- 「中心は純粋関数だけ!」🍰
- 「中心では Date/fetch/env/DB/FS を触らない!」🚫
- 「I/Oは adapter に押し出して interface 越し!」🔌 …みたいな プロジェクトの掟 を“スキル”として置けるのが強い💪💖 (Visual Studio Code)
③ Copilot CLI(public preview)
:ターミナルからAIに頼める🧑💻✨Copilot CLI は ターミナルで自然言語→提案ができるやつで、プレビュー扱いだよ〜🧪 (GitHub Docs)
おすすめは👇
- 「このログ出た、原因候補3つ出して」🕵️♀️
- 「このコマンドの意味ざっくり説明して」📖
- 「テスト失敗の読み解き」🧪
逆に、いきなり「全部直して」は危険⚠️(I/O境界ごと壊す事故あるある🥲)
④ OpenAI Codex IDE extension:IDE横で“エージェント”できる🧠🤖Codex の VS Code 拡張は、IDEの横で 読んで・直して・実行までを支援する方向で、クラウドに作業を委任する流れもあるよ〜☁️
注意点として、Windows対応は experimentalで、より良い体験には WSLワークスペース推奨って書かれてるよ🪟⚠️ (OpenAI Developers)
29-3. テスタブル設計を守る「AI利用3ルール」🧪🛡
️✨## ルールA:先に“境界ルール”を宣言する📣AIは放っておくと、平気で中心に Date.now() とか fetch() とか混ぜるよ〜😇💥
だから最初のプロンプトでこれを言う👇
- 中心(ロジック)は 純粋関数
- I/O は adapter
- 境界は interface
- テストは中心はユニット、外側は最小限の結合🧪
ルールB:いきなりコードを書かせず「設計→テスト→実装」🗺
️🧪🛠️順番が逆だと、AIが「動けばOK」をやりがち🥲 まずは
- 境界図(どれがI/O?)
- interface案
- テストケース
- 実装 の順が安定💕
ルールC:AIの変更は“差分レビュー前提”👀* 余計な依存追加してない?📦
- 中心にI/O混ざってない?🚫
- テストが実ネットワーク叩いてない?🌐💥
- ランダム・時刻が固定化されてる?⏰🎲
ここは人間の仕事💪😊
29-4. すぐ使える✨
「良いプロンプト」テンプレ集📝🤖## ① テストケース洗い出し(最強に便利)
🧪🔍
あなたはテスト設計の相棒です🧪
次の純粋関数仕様に対して、AAA形式でテストケースを列挙してね。
条件:
- I/Oは一切ない前提
- 正常系/境界値/異常系をバランスよく
- 「何を確認するか」を日本語で1行説明付き
仕様:
- 入力:items(価格), coupon(割引), taxRate
- 出力:小計/税/合計
- 端数処理:税は四捨五入
- couponは小計を下回らない(下回るなら0)
👉 返答が「テスト名だけ」なら追加で 「期待値の数字も例で出して」って言うと超よい😊💕
② interface とテストダブル(スタブ/スパイ)
を作らせる🧸✨
次のinterfaceに対して、テスト用の
- Stub(固定値を返す)
- Spy(呼び出し記録を取る)
をTypeScriptで作ってください。
制約:
- 外部ライブラリ追加なし
- できるだけ小さく
- 使い方の例も1つ
interface:
export interface Clock { now(): Date }
export interface Logger { info(msg: string, meta?: Record<string, unknown>): void }
③ I/O境界分離リファクタ(段取り→小さいPR)
✂️🧹
次のコードを「中心(純粋ロジック)」と「外側(I/O)」に分離したいです。
いきなり全修正せず、まずは段取りを提案してね。
出力フォーマット:
1) 境界の候補(I/O一覧)
2) 新しく作るinterface案(最小)
3) まず切り出す純粋関数のシグネチャ案
4) 1PR目でやる変更(小さく)
5) 2PR目でやる変更
コード:
(ここに対象ファイルを貼る)
ここでちゃんと段取りが出てきたら、次に 「じゃあ1PR目の差分だけコードで」って進めると安全🫶✨
④ 境界違反レビュー(AIに“監視役”をやらせる)
👀🚨
あなたは「I/O境界の分離」レビュワーです🕵️♀️
次の差分を見て、中心にI/Oが混ざっていないかチェックして。
観点:
- Date / Random / fetch / fs / env / DB / console など
- interface越しになってるか
- テストが不安定(時刻や乱数が固定されてない)になってないか
差分:
(diffを貼る)
29-5. ダメ回答の見抜き方(赤信号🚥あるある)
😵💫AIの提案がこうだったら黄色信号⚠️
- 「中心の関数の中で
fetch()して計算して保存してログ出す」🌀 - 「テストで実API叩いてます」🌐💥
- 「
Date.now()をそのまま使って期待値が日によって変わる」⏰😇 - 「便利だから新ライブラリ入れました!(大量)」📦📦📦
- 「interfaceが巨大(Repositoryに100メソッド)」📜😱
- 「例外がなんでも
throw new Error()」🚨🧯
こういうときは、AIに言い直す👇
- 「中心は純粋関数、I/O禁止」
- 「境界は最小interface」
- 「テストは安定(時刻/乱数固定)」 って“掟”を再掲すると戻りやすいよ😊✨
29-6. ハンズオン:AIと一緒に“境界を守る”練習しよ🎮🧪💗## お題:クーポン適用つき合計計算🛒🎟️
最初はわざと「ぐちゃぐちゃ版」からスタート😈
ぐちゃぐちゃ版(例)
export async function checkout(userId: string, items: { price: number }[]) {
const couponApi = process.env.COUPON_API!;
const res = await fetch(`${couponApi}/coupon?user=${userId}`);
const coupon = await res.json() as { amountOff: number };
const subtotal = items.reduce((a, x) => a + x.price, 0);
const discounted = Math.max(0, subtotal - coupon.amountOff);
const taxRate = Number(process.env.TAX_RATE ?? "0.1");
const tax = Math.round(discounted * taxRate);
console.log("checkout at", new Date().toISOString());
return { subtotal, tax, total: discounted + tax };
}
👀 どこがI/O?
process.env(設定)⚙️fetch(HTTP)🌐console.log(ログ)📝new Date()(時刻)⏰
ステップ1:AIに“境界図”を作らせる🗺
️✨プロンプト例👇
この関数のI/Oを列挙して、中心(純粋ロジック)に残すべきものと
外側(adapter)へ出すべきものを分けて。
最後に、中心関数のシグネチャ案を1つ出してね。
✅ ここで欲しい答えは
- 中心:合計計算、割引、税計算(純粋)🍰
- 外側:クーポン取得、設定読み、ログ、時刻⛩️(外の世界)
ステップ2:最小interfaceを作る(ここが勝負✂️
)こんな感じに“薄く”するのが理想だよ〜😊
export interface CouponClient {
getAmountOff(userId: string): Promise<number>;
}
export interface Config {
taxRate: number;
}
export interface Clock {
now(): Date;
}
export interface Logger {
info(msg: string, meta?: Record<string, unknown>): void;
}
ステップ3:中心(純粋関数)
を作って、先にテスト🧪🎉中心はI/Oゼロでいこ💖
export type CheckoutResult = { subtotal: number; tax: number; total: number };
export function calcCheckout(
items: { price: number }[],
amountOff: number,
taxRate: number
): CheckoutResult {
const subtotal = items.reduce((a, x) => a + x.price, 0);
const discounted = Math.max(0, subtotal - Math.max(0, amountOff));
const tax = Math.round(discounted * taxRate);
return { subtotal, tax, total: discounted + tax };
}
ここでAIに「テストケース列挙」を投げると速いよ🧪💨(テンプレ①)
ステップ4:外側で組み立て(I/Oはここだけ)
🔌🏗️
export function makeCheckout(deps: {
couponClient: CouponClient;
config: Config;
clock: Clock;
logger: Logger;
}) {
return async function checkout(userId: string, items: { price: number }[]) {
const amountOff = await deps.couponClient.getAmountOff(userId);
const result = calcCheckout(items, amountOff, deps.config.taxRate);
deps.logger.info("checkout", {
at: deps.clock.now().toISOString(),
userId,
subtotal: result.subtotal,
total: result.total,
});
return result;
};
}
こうなると、中心はテストが超ラク🥹✨ 外側は最小限の結合テストでOK👍
29-7. さらに一歩:AIに“掟”を覚えさせる📁🧠(Agent Skills 的発想)
VS Code の Agent Skills は「AIに読ませる指示フォルダ」みたいな方向で、Copilot にドメイン知識や手順を渡せる設計が進んでるよ〜(実験)📦✨ (Visual Studio Code)
例えば「skills/iosplit/README」にこんな掟を書いておくイメージ👇
- 中心は純粋関数
- I/Oはadapter
- interfaceは最小
- テストは AAA
- Clock/Random/Logger/Config は注入
こういう“プロジェクト憲法”があると、Agent mode を使っても事故りにくくなる😊🫶 (Copilot Edits の agent mode 自体も「自律で編集してタスク完了まで反復する」方向だよ)(GitHub Docs)
29-8. まとめ(今日の持ち帰り🍀
✨)* AIは テストケース列挙🧪 と 下書き📝 と レビュー👀 に最強
- でも 境界の判断✂️ は自分で握る!
- 進め方は 設計→テスト→実装 が安定🗺️🧪🛠️
- Agent系(Copilot Edits / Agent Skills / Codex)を使うほど、先に“掟”を渡すのが大事📜💗
- WindowsでCodex拡張は experimental なので、使うなら注意してね(WSL推奨)🪟⚠️ (OpenAI Developers)