mcpField
A
ai-coding-discipline

ai-coding-discipline

github.com/luoling8192開発17249 回インストール31 週間前に更新
リポジトリ

ai-coding-discipline について

AI エージェント向けのコーディング規則集で、欠損データの明示的な処理、具体的なテスト、規律あるバグ修正手順を重視します。エラー処理、テスト専用のハードコード回避、修正確認までのデバッグログ保持も扱います。

主な機能

  1. 01暗黙のフォールバックを回避
  2. 02包括的なエラー捕捉を制限
  3. 03具体的なテスト結果を検証
  4. 04テスト専用のハードコードを回避
  5. 05バグ修正でレッド・グリーンテスト
  6. 06修正確認までデバッグログを保持

活用シーン

  1. 01AI 生成コードの変更をレビュー
  2. 02業務動作を検証するテストを改善
  3. 03テスト先行のバグ修正を実践
  4. 04エラー処理とフォールバックを点検

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/luoling8192/ai-coding-principles --skill ai-coding-discipline

インストール後、Claude Code で/ai-coding-disciplineを入力して読み込まれたか確認します。

詳細

AI コーディングの規律

これらのルールは、AI の標準的なコーディング傾向より優先されます。作成または変更するすべてのコードで、必ず従ってください。


ルール 1:暗黙のフォールバックを使わない

欠落しているはずのないデータを隠すために、フォールバック値を使ってはいけません。

// FORBIDDEN — hides upstream bugs
const price = product?.price ?? 0;
const userName = user?.name || "Unknown";

// CORRECT — fail fast when data contract is violated
if (product.price == null) {
  throw new Error(`Product ${product.id} is missing price`);
}
const price = product.price;

フォールバックが許容される場合:

  • 明確な設計意図がある、ユーザー向けの表示(例:アバターのプレースホルダー)
  • デフォルト値が文書化されている、任意の設定
  • 欠落が有効な状態である、外部入力の解析

??、||、または ?. を書く前のチェックリスト:

  1. この時点で、この値が正当に null/undefined になることはありますか?
  2. null の場合、フォールバックによって後続処理で正しい結果が得られますか?
  3. エラーをスローしたほうが、バグを早く見つけられますか?

#3 の答えが「はい」なら、フォールバックではなくエラーをスローしてください。


ルール 2:ビジネスロジックで包括的な try/catch を使わない

ビジネスロジックの関数で、すべてを try/catch で囲んではいけません。エラーはそのまま自然に伝播させてください。

// FORBIDDEN — swallows all errors into a useless null
async function createOrder(data: OrderInput) {
  try {
    const user = await getUser(data.userId);
    const coupon = await validateCoupon(data.couponCode);
    const order = await saveOrder({ ...data, discount: coupon.value });
    return order;
  } catch (error) {
    console.log('Error creating order:', error);
    return null; // caller gets null, has no idea what failed
  }
}

// CORRECT — let errors bubble up, catch at the boundary
async function createOrder(data: OrderInput) {
  const user = await getUser(data.userId);
  const coupon = await validateCoupon(data.couponCode);
  const order = await saveOrder({ ...data, discount: coupon.value });
  return order;
}

// Catch ONLY at the API/controller boundary
app.post('/orders', async (req, res) => {
  try {
    const order = await createOrder(req.body);
    res.json(order);
  } catch (error) {
    logger.error('Order creation failed', { error, body: req.body });
    res.status(500).json({ error: 'Order creation failed' });
  }
});

try/catch が適切な場合:

  • API ルートハンドラー/コントローラーの境界
  • 最上位のイベントハンドラー(メッセージキュー、cron ジョブ)
  • 部分的な失敗が想定され、復旧方法が定義されている処理(例:アイテムごとにエラーを処理するバッチ処理)
  • 異なる方法で処理する意図がある、特定の名前付きエラー型

Error を捕捉して、単に null、undefined、false、または空のオブジェクトを返してはいけません。


ルール 3:コードが壊れたときにテストが失敗するようにする

すべてのテストで、具体的なビジネス上の結果を検証してください。中核となるロジックを削除しても成功するテストに価値はありません。

// FORBIDDEN — passes even if processOrder returns garbage
test('should process order', async () => {
  const result = await processOrder(mockOrder);
  expect(result).toBeDefined();
});

// CORRECT — verifies exact business behavior
test('should calculate total with 10% discount', async () => {
  const result = await processOrder({
    ...mockOrder,
    discount: 0.1,
  });
  expect(result.totalAmount).toBe(900);       // 1000 * 0.9
  expect(result.discountAmount).toBe(100);
  expect(result.status).toBe('confirmed');
});

テスト品質チェックリスト:

  1. 関数本体を削除した場合、このテストは失敗しますか?失敗しないなら、そのテストは役に立ちません。
  2. 動作をテストしていますか、それとも「何かが存在する」ことだけをテストしていますか?
  3. アサーションでは、単なる真偽値ではなく、具体的な値をチェックしていますか?

禁止する弱いアサーション(存在確認そのものが要件である場合を除く):

  • 唯一のアサーションとして使う toBeDefined()、toBeTruthy()、toBeFalsy()
  • toHaveLength(expect.any(Number))
  • 追加の値チェックをせずに使う expect(result).not.toBeNull()

ルール 4:ハードコードしたルックアップテーブルによる実装をしない

テストケースに合致する戻り値をハードコードして、ビジネスロジックを実装してはいけません。

// FORBIDDEN — fake implementation that "fits" the tests
function calculateDiscount(amount: number, level: string): number {
  if (amount === 1000 && level === 'gold') return 100;
  if (amount === 500 && level === 'silver') return 25;
  return 0;
}

// CORRECT — real logic
function calculateDiscount(amount: number, level: string): number {
  const rates: Record<string, number> = { gold: 0.1, silver: 0.05, bronze: 0.02 };
  const rate = rates[level] ?? 0;
  return amount * rate;
}

これを防ぐ方法:

  • 複数の金額、エッジケース、境界値など、多様なテストデータを使う
  • 適切な場合は、プロパティベーステスト/ファジーテストを追加する
  • ルックアップテーブルを使った偽の実装を見つけるため、元の仕様に含まれていない値でテストする

ルール 5:Red-Green テスト(TDD の順序)

バグを修正するときは、必ず最初に失敗するテストを書いてから、コードを修正してください。

Correct order:
1. Discover bug
2. Write a test that reproduces the bug
3. Run the test — confirm it FAILS (red)
4. Fix the code
5. Run the test — confirm it PASSES (green)

これが重要な理由: コードを先に修正してからテストを書くと、そのテストで本当にバグを検出できたかどうかを確かめられません。誤った理由でテストが成功する可能性があります。

手順 3 を決して省略しないでください。 テストが red から green に変わるのを確認することが、そのテストの妥当性を示す証拠です。


ルール 6:修正時にデバッグログを削除しない

デバッグ中は、人間が修正の動作を確認した後にのみ、デバッグログを削除してください。

FORBIDDEN workflow:
1. Human asks to add debug logs
2. AI adds logs
3. Human runs code, shares log output
4. AI "finds the problem", applies fix AND removes debug logs in the same edit
5. Fix doesn't work — logs are gone, must re-add them

CORRECT workflow:
1. Human asks to add debug logs
2. AI adds logs
3. Human runs code, shares log output
4. AI applies fix ONLY — debug logs stay untouched
5. Human verifies the fix
6. Human decides when to remove debug logs (or asks AI to remove them)

ルール:修正と同じコミットでデバッグ/診断ログに手を加えてはいけません。これらは別々に扱うべきものです。


クイックリファレンス:コードを提出する前のセルフチェック

コード変更を確定する前に、次のチェックリストを確認してください。

チェック項目質問
フォールバック欠落してはいけない値を隠すために、?? または || を使いましたか?
エラー処理エラーをそのまま伝播させるべきビジネスロジックに try/catch を追加しましたか?
テストの強度実装を削除しても、テストは成功しますか?
テストの誠実さ実際のロジックを実装する代わりに、テストケースに合う値をハードコードしましたか?
TDD の順序バグ修正の場合、修正を適用する前にテストが失敗するのを確認しましたか?
デバッグログ修正と同じ変更で診断ログを削除していますか?

いずれかの答えが「はい」なら、先に修正してください。

コメント