Skip to content

AI Copilot開発手法とRules

AI Copilot(GitHub Copilot、Cursor、Claude等)を活用した開発において、rulesやプロンプトエンジニアリングを用いて開発効率と品質を向上させる手法を解説します。

AI Copilotは、コード生成、リファクタリング、デバッグ支援を行うAIアシスタントです。

主要なAI Copilotツール:

  • GitHub Copilot
  • Cursor
  • Claude (Anthropic)
  • ChatGPT Code Interpreter
  • Tabnine

AI Copilotを効果的に活用するには、明確なルールとガイドラインが必要です。

なぜRulesが重要か:

  • AIの出力品質を一定に保つ
  • チーム全体で統一された開発スタイルを維持
  • セキュリティリスクを軽減
  • 保守性の高いコードを生成
## コーディング規約Rules
### 命名規則
- 変数名: camelCase(例: userName, isActive)
- 関数名: camelCase(例: getUserData, validateInput)
- クラス名: PascalCase(例: UserService, DataProcessor)
- 定数: UPPER_SNAKE_CASE(例: MAX_RETRY_COUNT)
### 関数設計
- 1つの関数は1つの責務のみ
- 関数名は動詞で始める
- 引数は5個以下に制限
- 戻り値の型を明示
### エラーハンドリング
- try-catch文を適切に使用
- エラーメッセージは具体的に記述
- ログ出力を含める
## セキュリティRules
### 入力検証
- すべての外部入力を検証
- SQLインジェクション対策を実装
- XSS対策を実装
### 認証・認可
- JWT トークンの適切な検証
- パスワードのハッシュ化
- セッション管理の実装
### 機密情報
- ハードコードされた秘密鍵を禁止
- 環境変数を使用
- ログに機密情報を出力しない
## パフォーマンスRules
### データベース
- N+1クエリを避ける
- インデックスを適切に使用
- クエリの実行計画を確認
### キャッシュ
- 適切なキャッシュ戦略を実装
- キャッシュの有効期限を設定
- キャッシュキーの命名規則を統一
### 非同期処理
- 重い処理は非同期で実行
- Promise/async-awaitを適切に使用
- エラーハンドリングを含める
## コード生成Prompt テンプレート
あなたは経験豊富なソフトウェアエンジニアです。
以下の要件に従ってコードを生成してください。
### 要件
- [具体的な機能要件]
- [技術的制約]
- [パフォーマンス要件]
### 制約条件
- TypeScriptを使用
- エラーハンドリングを含める
- 単体テストも生成
- JSDocコメントを追加
### コーディング規約
- 関数名はcamelCase
- 1つの関数は1つの責務
- 戻り値の型を明示
### セキュリティ要件
- 入力検証を実装
- SQLインジェクション対策
- 適切なエラーメッセージ
コードを生成してください。
## リファクタリングPrompt テンプレート
以下のコードをリファクタリングしてください。
### 改善目標
- 可読性の向上
- パフォーマンスの最適化
- 保守性の向上
### 適用する原則
- SOLID原則
- DRY原則
- 単一責任の原則
### 制約条件
- 既存の機能を変更しない
- 後方互換性を保つ
- テストケースも更新
[対象コード]
改善されたコードと変更理由を説明してください。
## デバッグPrompt テンプレート
以下のコードにバグがあります。
問題を特定し、修正してください。
### 症状
- [具体的なエラーメッセージ]
- [期待する動作]
- [実際の動作]
### 環境情報
- [使用言語・フレームワーク]
- [実行環境]
### 調査観点
- ロジックエラー
- 型エラー
- 非同期処理の問題
- エラーハンドリングの不備
[問題のあるコード]
バグの原因と修正方法を説明してください。
## Rules文書管理
### 文書構成

project-root/ ├── .ai-rules/ │ ├── coding-standards.md │ ├── security-rules.md │ ├── performance-rules.md │ └── prompt-templates.md ├── .copilot/ │ ├── instructions.md │ └── examples/ └── docs/ └── ai-development-guide.md

### 更新プロセス
1. Rules変更提案
2. チームレビュー
3. 承認・マージ
4. チーム周知
.github/workflows/ai-rules-check.yml
name: AI Rules Check
on:
pull_request:
branches: [ main ]
jobs:
rules-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Check Coding Standards
run: |
# コーディング規約チェック
npm run lint
npm run type-check
- name: Security Scan
run: |
# セキュリティスキャン
npm audit
npm run security-check
- name: Performance Check
run: |
# パフォーマンステスト
npm run performance-test
.vscode/settings.json
{
"github.copilot.enable": {
"*": true,
"yaml": false,
"plaintext": false
},
"github.copilot.advanced": {
"secret_key": "off",
"length": 500
}
}
.copilot/instructions.md
# Copilot Instructions
## プロジェクト概要
このプロジェクトは[プロジェクト説明]です。
## 技術スタック
- TypeScript
- React
- Node.js
- PostgreSQL
## コーディング規約
- ESLint設定に従う
- Prettierでフォーマット
- JSDocコメント必須
## 禁止事項
- console.logの本番コード含有
- ハードコードされた設定値
- 未処理のPromise
// Prompt例
/*
以下の要件でREST APIを作成してください:
要件:
- ユーザー管理API
- CRUD操作をサポート
- JWT認証を実装
- バリデーション機能
- エラーハンドリング
技術スタック:
- Express.js
- TypeScript
- Prisma ORM
- Zod(バリデーション)
セキュリティ要件:
- パスワードハッシュ化
- レート制限
- 入力サニタイゼーション
*/
// AI生成コード例
import express from 'express';
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { z } from 'zod';
import rateLimit from 'express-rate-limit';
const app = express();
// レート制限
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分
max: 100 // 最大100リクエスト
});
app.use(limiter);
app.use(express.json());
// バリデーションスキーマ
const userSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
name: z.string().min(1)
});
// ユーザー作成API
app.post('/api/users', async (req, res) => {
try {
// バリデーション
const validatedData = userSchema.parse(req.body);
// パスワードハッシュ化
const hashedPassword = await bcrypt.hash(validatedData.password, 10);
// ユーザー作成(Prisma使用)
const user = await prisma.user.create({
data: {
email: validatedData.email,
password: hashedPassword,
name: validatedData.name
}
});
// レスポンス(パスワードは除外)
const { password, ...userResponse } = user;
res.status(201).json(userResponse);
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(400).json({
error: 'Validation failed',
details: error.errors
});
}
console.error('User creation error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});

2. フロントエンド開発での活用

Section titled “2. フロントエンド開発での活用”
// Prompt例
/*
以下の要件でReactコンポーネントを作成してください:
要件:
- ユーザー一覧表示コンポーネント
- 検索・フィルタ機能
- ページネーション
- ローディング状態管理
- エラーハンドリング
技術要件:
- TypeScript
- React Hooks
- TanStack Query
- Tailwind CSS
パフォーマンス要件:
- 仮想スクロール対応
- メモ化の適用
- 不要な再レンダリング防止
*/
// AI生成コード例
import React, { useState, useMemo, useCallback } from 'react';
import { useQuery } from '@tanstack/react-query';
import { FixedSizeList as List } from 'react-window';
interface User {
id: string;
name: string;
email: string;
role: string;
}
interface UserListProps {
searchTerm?: string;
roleFilter?: string;
}
const UserList: React.FC<UserListProps> = ({
searchTerm = '',
roleFilter = ''
}) => {
const [page, setPage] = useState(1);
const pageSize = 50;
// ユーザーデータ取得
const { data, isLoading, error } = useQuery({
queryKey: ['users', page, searchTerm, roleFilter],
queryFn: () => fetchUsers({ page, pageSize, searchTerm, roleFilter }),
keepPreviousData: true
});
// フィルタリングされたユーザー
const filteredUsers = useMemo(() => {
if (!data?.users) return [];
return data.users.filter(user => {
const matchesSearch = user.name.toLowerCase()
.includes(searchTerm.toLowerCase());
const matchesRole = !roleFilter || user.role === roleFilter;
return matchesSearch && matchesRole;
});
}, [data?.users, searchTerm, roleFilter]);
// ユーザー行コンポーネント(メモ化)
const UserRow = React.memo(({ index, style }: {
index: number;
style: React.CSSProperties
}) => {
const user = filteredUsers[index];
return (
<div style={style} className="flex items-center p-4 border-b">
<div className="flex-1">
<h3 className="font-medium">{user.name}</h3>
<p className="text-gray-600">{user.email}</p>
</div>
<span className="px-2 py-1 bg-blue-100 text-blue-800 rounded">
{user.role}
</span>
</div>
);
});
// ページ変更ハンドラ
const handlePageChange = useCallback((newPage: number) => {
setPage(newPage);
}, []);
if (isLoading) {
return (
<div className="flex justify-center items-center h-64">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
</div>
);
}
if (error) {
return (
<div className="text-red-600 text-center p-4">
エラーが発生しました: {error.message}
</div>
);
}
return (
<div className="h-96">
<List
height={384}
itemCount={filteredUsers.length}
itemSize={80}
itemData={filteredUsers}
>
{UserRow}
</List>
{/* ページネーション */}
<div className="flex justify-center mt-4">
<button
onClick={() => handlePageChange(page - 1)}
disabled={page === 1}
className="px-4 py-2 mr-2 bg-blue-600 text-white rounded disabled:opacity-50"
>
前へ
</button>
<span className="px-4 py-2">
{page} / {Math.ceil((data?.total || 0) / pageSize)}
</span>
<button
onClick={() => handlePageChange(page + 1)}
disabled={page >= Math.ceil((data?.total || 0) / pageSize)}
className="px-4 py-2 ml-2 bg-blue-600 text-white rounded disabled:opacity-50"
>
次へ
</button>
</div>
</div>
);
};
export default UserList;
// Prompt例
/*
以下のコードに対する包括的なテストを作成してください:
要件:
- 単体テスト
- 統合テスト
- エラーケースのテスト
- モックの適切な使用
テストフレームワーク:
- Jest
- React Testing Library
- MSW(API モック)
カバレッジ目標:
- 90%以上のコードカバレッジ
- すべてのエラーパスをテスト
- エッジケースを含む
*/
// AI生成テストコード例
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import UserList from './UserList';
// MSWサーバー設定
const server = setupServer(
rest.get('/api/users', (req, res, ctx) => {
const page = req.url.searchParams.get('page') || '1';
const searchTerm = req.url.searchParams.get('search') || '';
const mockUsers = [
{ id: '1', name: 'John Doe', email: 'john@example.com', role: 'admin' },
{ id: '2', name: 'Jane Smith', email: 'jane@example.com', role: 'user' }
];
const filteredUsers = mockUsers.filter(user =>
user.name.toLowerCase().includes(searchTerm.toLowerCase())
);
return res(
ctx.json({
users: filteredUsers,
total: filteredUsers.length,
page: parseInt(page)
})
);
})
);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
const renderWithQueryClient = (component: React.ReactElement) => {
const queryClient = new QueryClient({
defaultOptions: {
queries: { retry: false },
},
});
return render(
<QueryClientProvider client={queryClient}>
{component}
</QueryClientProvider>
);
};
describe('UserList', () => {
test('ユーザー一覧が正常に表示される', async () => {
renderWithQueryClient(<UserList />);
// ローディング状態の確認
expect(screen.getByRole('status')).toBeInTheDocument();
// ユーザーデータの表示確認
await waitFor(() => {
expect(screen.getByText('John Doe')).toBeInTheDocument();
expect(screen.getByText('Jane Smith')).toBeInTheDocument();
});
});
test('検索機能が正常に動作する', async () => {
renderWithQueryClient(<UserList searchTerm="John" />);
await waitFor(() => {
expect(screen.getByText('John Doe')).toBeInTheDocument();
expect(screen.queryByText('Jane Smith')).not.toBeInTheDocument();
});
});
test('APIエラー時にエラーメッセージが表示される', async () => {
server.use(
rest.get('/api/users', (req, res, ctx) => {
return res(ctx.status(500), ctx.json({ error: 'Server Error' }));
})
);
renderWithQueryClient(<UserList />);
await waitFor(() => {
expect(screen.getByText(/エラーが発生しました/)).toBeInTheDocument();
});
});
test('ページネーションが正常に動作する', async () => {
renderWithQueryClient(<UserList />);
await waitFor(() => {
expect(screen.getByText('次へ')).toBeInTheDocument();
});
fireEvent.click(screen.getByText('次へ'));
// ページ変更の確認
await waitFor(() => {
expect(screen.getByText('2 /')).toBeInTheDocument();
});
});
test('空のデータセットが正常に処理される', async () => {
server.use(
rest.get('/api/users', (req, res, ctx) => {
return res(ctx.json({ users: [], total: 0, page: 1 }));
})
);
renderWithQueryClient(<UserList />);
await waitFor(() => {
expect(screen.queryByText('John Doe')).not.toBeInTheDocument();
});
});
});
## 段階的導入プロセス
### フェーズ1: 基本Rules(1-2週間)
- コーディング規約
- 基本的なセキュリティルール
- エラーハンドリング規約
### フェーズ2: 高度なRules(2-4週間)
- パフォーマンス最適化
- テスト戦略
- アーキテクチャパターン
### フェーズ3: チーム最適化(継続的)
- チーム固有のルール
- プロジェクト特化ルール
- 継続的改善
// Rules適用効果の測定
interface QualityMetrics {
codeQuality: {
lintErrors: number;
typeErrors: number;
testCoverage: number;
};
productivity: {
linesOfCodePerDay: number;
featuresDelivered: number;
bugCount: number;
};
aiUsage: {
copilotAcceptanceRate: number;
promptEffectiveness: number;
timeToCompletion: number;
};
}
// 測定ダッシュボード
const QualityDashboard = () => {
const metrics = useQualityMetrics();
return (
<div className="grid grid-cols-3 gap-4">
<MetricCard
title="コード品質"
value={metrics.codeQuality.testCoverage}
unit="%"
trend="up"
/>
<MetricCard
title="生産性"
value={metrics.productivity.featuresDelivered}
unit="features/week"
trend="up"
/>
<MetricCard
title="AI活用率"
value={metrics.aiUsage.copilotAcceptanceRate}
unit="%"
trend="stable"
/>
</div>
);
};
## 継続的改善プロセス
### 週次レビュー
- Rules適用状況の確認
- 問題点の洗い出し
- 改善提案の収集
### 月次評価
- 品質メトリクスの分析
- 生産性向上の測定
- Rules更新の検討
### 四半期見直し
- 全体戦略の見直し
- 新技術への対応
- チーム成長に合わせた調整

AI Copilotを活用した開発では、適切なRulesとプロンプトエンジニアリングが成功の鍵となります。

  1. 明確なRules設定 - コーディング規約、セキュリティ、パフォーマンス
  2. 効果的なPrompt設計 - 具体的で構造化されたプロンプト
  3. チーム運用 - 文書管理、自動化、品質測定
  4. 継続的改善 - 段階的導入、効果測定、定期見直し

適切にRulesを設計・運用することで、AI Copilotの能力を最大限に活用し、高品質なソフトウェア開発を実現できます。