Chapter 26: Copilot で機能を実装する
要件からコードへの変換、テスト駆動開発
GitHub Copilot はエディタに統合された AI ペアプログラマーです。コードを書く手を止めずに、補完・生成・説明を受けられます。この章では Copilot を実務で最大限活用するテクニックを学びます。
26.1 要件をコードに変換する
コメントドリブン開発
Copilot はコメントをコードに変換するのが得意です。実装したい内容をコメントとして書くと、その下にコードを生成してくれます。
例: ユーザー登録機能の実装
// ユーザー登録関数
// - email と password を受け取る
// - email の重複チェックを行う
// - password を bcrypt でハッシュ化する
// - DB にユーザーを保存して user オブジェクトを返す
// - email が不正な形式の場合は ValidationError を投げる
async function registerUser(email: string, password: string): Promise<User> {
// ここで Tab を押すと Copilot が実装を生成する
}このようにコメントで仕様を詳細に書くほど、生成されるコードの精度が上がります。
Copilot Chat での要件相談
エディタ内の Copilot Chat を使うと、より複雑な要件を対話形式で実装できます。
プロンプト例:
このプロジェクトの認証システムに、以下の機能を追加したい:
1. JWT トークンのリフレッシュ機能
2. トークンの有効期限は15分
3. リフレッシュトークンは7日間有効
4. リフレッシュトークンは Redis に保存する
既存の auth.ts を参考に、新しい関数を実装してほしい。
出典: VS Code 公式ドキュメント
TODO: あとで実際のスクリーンショットに置き換え - Copilot Chat でコードを生成している様子(VS Code のサイドパネル)
26.2 テスト駆動開発 with Copilot
TDD (Test-Driven Development) と Copilot を組み合わせることで、品質の高いコードを素早く書けます。
TDD × Copilot のワークフロー
実践例: 価格計算ロジックの TDD
Step 1: テストを先に書く
// tests/pricing.test.ts
describe('calculateDiscount', () => {
// 通常価格は割引なし
it('should return original price for no discount', () => {
expect(calculateDiscount(1000, 0)).toBe(1000);
});
// 10%割引の場合
it('should apply 10% discount correctly', () => {
expect(calculateDiscount(1000, 10)).toBe(900);
});
// 割引率が100%を超える場合はエラー
it('should throw error when discount rate exceeds 100', () => {
expect(() => calculateDiscount(1000, 101)).toThrow('Invalid discount rate');
});
// 価格が負の場合はエラー
it('should throw error for negative price', () => {
expect(() => calculateDiscount(-100, 10)).toThrow('Price must be positive');
});
});Step 2: Copilot に実装を生成させる
テストファイルの内容を Copilot が読み取り、対応する実装を提案します。Copilot Chat で以下のように依頼することもできます。
上のテストコードを全てパスする calculateDiscount 関数を実装してほしい。
TypeScript の型定義も含めること。26.3 段階的な実装指示のテクニック
複雑な機能を一度に実装しようとすると、Copilot の出力品質が下がります。段階的に指示する方が効果的です。
分割指示パターン
悪い例(一度にすべてを頼む):
ユーザー管理システム全体を実装してほしい。CRUD 操作、認証、権限管理、メール通知、ログ記録すべて含む。良い例(段階的に依頼する):
# Step 1
まずユーザー関連の型定義だけを作ってほしい。
User, CreateUserInput, UpdateUserInput の型を定義する。
# Step 2 (Step 1 が完成してから)
次に、ユーザーを DB から取得する getUserById 関数を実装してほしい。
エラーハンドリングは後でやるので、今はハッピーパスだけでよい。
# Step 3
getUserById にエラーハンドリングを追加してほしい。
ユーザーが見つからない場合は UserNotFoundError を投げること。コンテキストを明示する
Copilot に現在のコンテキストを正確に伝えることが重要です。
// このファイルは Express.js + TypeScript で書かれている
// データベースは PostgreSQL、ORM は Prisma を使用
// エラーハンドリングは AppError クラスを継承する
// 認証済みユーザーは req.user に格納されている
// ユーザーのプロフィール更新エンドポイント
// PATCH /api/users/:id
// 自分のプロフィールのみ更新可能(他ユーザーは 403)
router.patch('/users/:id', authenticate, async (req, res, next) => {26.4 複数ファイルにまたがる実装
Copilot Chat の「@workspace」機能を使うと、プロジェクト全体を参照した実装ができます。
プロンプト例:
@workspace
現在のプロジェクト構成を参考に、商品カテゴリー管理の機能を追加してほしい。
既存の User モデルや Product モデルと同じパターンで実装すること。
必要なファイル:
1. src/models/category.ts (モデル定義)
2. src/repositories/categoryRepository.ts (DB アクセス)
3. src/services/categoryService.ts (ビジネスロジック)
4. src/controllers/categoryController.ts (HTTP ハンドラ)
5. src/routes/category.ts (ルート定義)
出典: VS Code 公式ドキュメント
TODO: あとで実際のスクリーンショットに置き換え - @workspace を使って複数ファイルにまたがる実装を生成している様子
ファイル間の整合性を保つ
複数ファイルを生成した後は、整合性を確認するよう依頼します。
今生成したカテゴリー管理機能のファイル群を確認して、以下をチェックしてほしい:
1. 型の不整合がないか
2. import パスが正しいか
3. 既存のエラーハンドリングパターンと一致しているか26.5 ハンズオン: Web アプリの機能追加
課題: タスク管理アプリに「優先度」機能を追加する
以下の手順で実装してみましょう。
準備:
git clone https://github.com/example/task-app-starter
cd task-app-starter
npm install
npm test # 既存のテストが全て通ることを確認Step 1: 型定義を Copilot に生成させる
// src/types/task.ts
// 既存の Task 型に priority フィールドを追加してほしい
// priority は 'low' | 'medium' | 'high' | 'urgent' の4段階
// デフォルト値は 'medium'
// PriorityLevel 型も別途定義することStep 2: テストを先に書かせる
Copilot Chat で依頼:
優先度でタスクをソートする sortTasksByPriority 関数のテストを書いてほしい。
urgent > high > medium > low の順でソートする。
同じ優先度の場合は作成日時の新しい順にする。Step 3: 実装を生成させる
テストが揃ったら実装を依頼します。
Step 4: 動作確認
npm test # 全テストが通ることを確認
npm run dev # 実際に動かして確認チェックリスト
- 型定義が正しく生成されたか
- テストがすべて通るか
- 既存のテストが壊れていないか
- コードのスタイルが既存コードと一致しているか
- エッジケース(空配列、同じ優先度のタスク)が処理されているか
まとめ
Copilot を効果的に使うポイントをまとめます。
| テクニック | 効果 |
|---|---|
| コメントで仕様を詳細に書く | 生成精度が向上する |
| TDD と組み合わせる | 品質が担保されやすい |
| 段階的に指示する | 複雑な機能でも精度を保てる |
| @workspace を使う | プロジェクト全体と整合したコードを生成できる |
| コンテキストを明示する | フレームワーク・パターンに合ったコードが出る |
次の章では、Claude Code を使ったより大規模な実装フローを学びます。