はじめに
この記事はprimeNumberの夏の自由研究企画、「AI Native Summer Calendar 2025」 の18日目の参加記事です。
AIコーディングエージェントであるClaude Codeは、開発者の生産性を大幅に向上させる可能性を秘めています。しかし、実際に使ってみると「思っていたのと違う」と感じることも少なくありません。本記事では、Claude Codeを使った開発の課題と、それを解決するためのTDD/BDDアプローチについて、実践的な観点から解説します。
Claude Codeで開発するときのチョット難しいポイント
1. 意図しない方向への実装
- 実装計画(設計書)がない状態で作らせてもこちらの意図している方向に実装がされない
- 例えば「ユーザー認証機能を実装して」と伝えても、想定していたアーキテクチャと異なる設計で実装される
- 既存のコードベースの規約やパターンを無視した実装になることがある
2. 生成コードの肥大化問題
- 実行計画を実際にコードを生成してもらっても、生成されたコードが大きすぎて詳細まで見るのが大変
- 一度に数百行のコードが生成され、どこで何をしているのか把握しきれない
- バグが混入していても気づきにくい
3. フィードバックループの長さ
- 大きな変更を一度に行うため、問題に気づくのが遅れる
- 修正が必要な場合、影響範囲が大きくなりがち
解決策:TDD/BDDによる段階的開発アプローチ
これらの課題を解決するため、TDDサイクルとRGBCのサイクルで変更を細かく分けて、助手席に座ってClaude Codeを操縦することで、意図しない方向にコードが生成されるのを防ぐCommandを作成しました。
claude commandの例は以下です。
https://gist.github.com/katamotokosuke/fd232aeb2a2dc6057ff92b2410f5b072
トレードオフ:速度 vs 品質
正直な話
助手席に座る方式なので、今までの開発速度から大きく生産性が上がるということはありません。「AIが全部やってくれる」という期待値とは異なるかもしれません
しかし、実際のところ...
- 丸投げスタイルでも結局コードレビューの時間や方向性を修正していく過程で時間を浪費する
- 「速く作って大きく修正」より「着実に作って小さく修正」の方が、トータルの時間はそんなに変わらない
- むしろ、手戻りが少ない分、精神的なストレスが減る
得られるメリット
- 品質の向上: テストカバレッジが自然と高くなる
- 理解の深化: 小さなステップで進むため、生成されたコードを完全に理解できる
- 学習効果: TDD/BDDの実践を通じて、設計力が向上する
- ドキュメントの自動生成: 実装と同時にドキュメントも整備される
TDDとは
Test-Driven Development(テスト駆動開発)は、以下のサイクルを繰り返す開発手法です:
- Red: 失敗するテストを書く
- Green: テストを通す最小限のコードを書く
- Refactor: コードを改善する
このシンプルなサイクルが、品質の高いコードを生み出す秘訣です。
RGBCとは
Red-Green-Blue-Commit は、TDDのサイクルに「Commit」フェーズを追加したものです:
🔴 Red → 🟢 Green → 🔵 Blue(Refactor) → 📝 Commit
- 🔴 Red: 失敗するテストを書く
- 🟢 Green: テストを通す最小限の実装
- 🔵 Blue: リファクタリング
- 📝 Commit: 意味のある単位でコミット
この「こまめなコミット」が、Claude Codeとの協働において重要な役割を果たします。
BDDとは
Behavior-Driven Development(振る舞い駆動開発)は、ビジネス価値に焦点を当てた開発手法です:
例:
Feature: ユーザー認証
As a ユーザー
I want ログインできる
So that 自分のデータにアクセスできる
Scenario: 正常なログイン
Given ログインページにアクセスしている
When 正しい認証情報を入力する
Then ダッシュボードが表示される
自然言語で書かれたシナリオが、実装の指針となります。
このコマンドでの開発フロー
/tdd
コマンドを使った開発フローを図示します:
ポイント:助手席からの操縦
- ユーザーが方向性を決める: Claude Codeは提案するが、最終決定はユーザー
- 小さなステップで進む: 一度に大きな変更をしない
- 常に確認: 各ステップでユーザーが内容を確認
- コミット前の承認: 必ずユーザーの承認を得てからコミット
実際の使用例
実際に/tdd
コマンドを使った開発セッションの例を見てみましょう。
セッション開始
User: /tdd
Claude: I'll help you implement a feature using BDD and RGBC cycle.
What feature would you like to work on?
User: APIのレート制限機能を実装したい
Claude: 了解しました。まず既存のコードベースを調査します...
※ここで情報を提供したり、方向性を指示することで実行計画を詳細化します
BDDシナリオ作成
Claude: レート制限機能について、以下のシナリオを作成しました:
Feature: APIレート制限
As a システム管理者
I want APIアクセスを制限する
So that サーバーの過負荷を防げる
Scenario: 制限内のアクセス
Given 1分間に10回までの制限がある
When 5回APIを呼び出す
Then すべてのリクエストが成功する
Scenario: 制限超過時のアクセス
Given 1分間に10回までの制限がある
When 11回APIを呼び出す
Then 11回目は429エラーが返る
これでよろしいですか?
User: OK、進めて
実行計画を実際のシナリオに起こします。
RGBCサイクル実行
🔴 Red Phase
Claude: まず失敗するテストを書きます:
# test/rate_limiter_test.rb
require 'minitest/autorun'
class RateLimiterTest < Minitest::Test
def test_allows_requests_within_limit
limiter = RateLimiter.new(limit: 10, window: 60)
10.times do
assert limiter.check('user1')
end
end
end
テストを実行します...
[テスト失敗: RateLimiterクラスが存在しません]
ここからはTDDサイクルに従って進めます。
🟢 Green Phase
Claude: 最小限の実装を行います:
# lib/rate_limiter.rb
class RateLimiter
def initialize(limit:, window:)
@limit = limit
@window = window
@requests = Hash.new { |h, k| h[k] = [] }
end
def check(identifier)
now = Time.now
@requests[identifier].reject! { |t| t < now - @window }
if @requests[identifier].size < @limit
@requests[identifier] << now
true
else
false
end
end
end
テストを実行します...
[テスト成功!]
🔵 Blue Phase
Claude: リファクタリングを行います:
# lib/rate_limiter.rb
require 'thread'
class RateLimiter
def initialize(limit:, window:)
@limit = limit
@window = window
@requests = Hash.new { |h, k| h[k] = [] }
@mutex = Mutex.new
end
def check(identifier)
@mutex.synchronize do
clean_expired_requests(identifier)
if within_limit?(identifier)
record_request(identifier)
true
else
false
end
end
end
private
def clean_expired_requests(identifier)
cutoff_time = Time.now - @window
@requests[identifier].reject! { |timestamp| timestamp < cutoff_time }
end
def within_limit?(identifier)
@requests[identifier].size < @limit
end
def record_request(identifier)
@requests[identifier] << Time.now
end
end
📝 Commit
Claude: 以下の内容でコミットします。よろしいですか?
feat: Add rate limiter service for API throttling
- Implement RateLimiter class with configurable limits
- Support time-window based request counting
- Add thread-safe memory store for request tracking
- Include comprehensive test coverage
RGBC cycle: Red -> Green -> Blue completed
User: OK、コミットして
Claude: コミットしました。次のシナリオに進みますか?
ドキュメント生成
全てのシナリオが完了した後、Claude Codeが自動的にドキュメントを生成・更新します
このドキュメント生成により、実装と同時に以下が保証されます:
- API仕様の文書化: 他の開発者が使いやすい
- 変更履歴の記録: 何が変わったか明確
まとめ
Claude Codeとの付き合い方
/tdd
コマンドを使った開発は、AIツールをより効果的に活用するための一つのアプローチです。
Before: 丸投げスタイル
- 大きな要求を投げる
- 大量のコードが生成される
- 理解が追いつかない
- 後から大きな修正
After: 協働スタイル
- 小さなステップで進む
- 理解しながら実装
- 品質を保証しながら進む
- 修正が最小限
得られる価値
- 生成されたコードの理解度UP: 小さく開発を進めることで生成されたコードを理解しやすい
- 高い品質: TDDで開発するので、テストカバレッジが高く保てる
- 学習効果: TDD/BDDの実践スキル向上
- ドキュメントの充実: 実装と同時に仕様書・使用例・変更履歴が自動生成される
最後に
Claude Codeは強力なツールですが、使い方次第で結果は大きく変わります。
/tdd
コマンドは、生成されるコードの品質と理解度を高めるための実践的な方法の一つです。開発速度は劇的には変わりませんが、手戻りが減り、コードの把握が容易になるという現実的なメリットがあります。
AIツールとの付き合い方に正解はありませんが、このアプローチが皆さんの開発スタイルの参考になれば幸いです。
この記事で紹介した/tdd
コマンドは、Claude Codeのカスタムコマンド機能を使用しています。ぜひ皆さんも試してみてね。
https://gist.github.com/katamotokosuke/fd232aeb2a2dc6057ff92b2410f5b072