← 記録・ドキュメント キャリア戦略 →

06 開発手法カタログ — プロジェクトタイプ別レシピ

どの開発手法をどのプロジェクトで使うかを整理する「手法セレクタ」


手法選択ガイド

新しいプロジェクトが来た
    ↓
どんな性質のプロジェクト?
    │
    ├── ビジネスロジック重要・長期運用
    │   └── → DDD + クリーンアーキテクチャ
    │
    ├── 外部APIやDBを触る機能
    │   └── → TDD(テストファースト)
    │
    ├── 要件が曖昧・ステークホルダーとの合意が必要
    │   └── → BDD(振舞駆動)
    │
    ├── APIを設計・公開する
    │   └── → 仕様駆動開発(OpenAPI先行)
    │
    └── スクリプト・ワンショットツール
        └── → シンプル実装(手法不要)

TDD — テスト駆動開発

いつ使う: 外部API・DB・副作用を伴う機能

Red-Green-Refactorサイクル

1. Red:    失敗するテストを書く
2. Green:  テストを通す最小実装をする
3. Refactor: コードをきれいにする(テストはまだ通る)
→ 繰り返す

実例

# Step 1: Red(失敗するテスト)
def test_validate_email():
    assert validate_email("user@example.com") == True
    assert validate_email("invalid") == False
# → ImportError: cannot import name 'validate_email'

# Step 2: Green(通す最小実装)
def validate_email(email: str) -> bool:
    return "@" in email  # 最小実装

# Step 3: Refactor(改善)
import re
def validate_email(email: str) -> bool:
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))

BDD — 振舞駆動開発

いつ使う: ステークホルダーとの要件合意・受け入れテスト

Given-When-Then形式

Feature: ユーザーログイン

  Scenario: 正常なログイン
    Given ユーザー "alice@example.com" が登録済みである
    When パスワード "correct-password" でログインする
    Then ダッシュボードにリダイレクトされる

  Scenario: 誤ったパスワード
    Given ユーザー "alice@example.com" が登録済みである
    When パスワード "wrong-password" でログインする
    Then "認証エラー" のメッセージが表示される

メリット


DDD — ドメイン駆動設計

いつ使う: ビジネスロジックが複雑で長期運用するシステム

主要概念

概念 説明
エンティティ IDを持つオブジェクト User(id=123)
値オブジェクト 値が同じなら同一 Email("a@b.com")
集約 整合性の境界 Order + OrderItems
リポジトリ 永続化の抽象 UserRepository
ドメインサービス オブジェクトをまたがるロジック TransferService

レイヤー構造

Presentation (API/UI)
    ↓
Application (ユースケース)
    ↓
Domain (ビジネスロジック) ← ここが核心
    ↓
Infrastructure (DB/外部API)

仕様駆動開発 — OpenAPI先行設計

いつ使う: APIを設計・公開するプロジェクト

手順

1. OpenAPI仕様を書く(コードを書く前に)
↓
2. モックサーバーでフロントエンドが開発開始
↓
3. 仕様からサーバーコードを生成
↓
4. 仕様に合わせてテストを自動生成
↓
5. 仕様・テスト・実装が常に同期
# openapi.yaml(先に書く)
paths:
  /users/{id}:
    get:
      summary: ユーザー取得
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'

クリーンアーキテクチャ

いつ使う: 長期運用・チーム開発・依存関係を整理したい場合

依存の方向

外側 → 内側に依存(内側は外側を知らない)

Frameworks & Drivers (最外層)
    → Interface Adapters
        → Use Cases
            → Entities (最内層・純粋なビジネスロジック)

実装例(Python)

# Domain Layer(外部依存ゼロ)
class User:
    def __init__(self, id: int, email: str):
        self.id = id
        self.email = email

# Use Case Layer(Repositoryは抽象に依存)
class GetUserUseCase:
    def __init__(self, user_repo: UserRepository):
        self._repo = user_repo

    def execute(self, user_id: int) -> User:
        return self._repo.find_by_id(user_id)

# Infrastructure Layer(DBの実装はここだけ)
class PostgresUserRepository(UserRepository):
    def find_by_id(self, user_id: int) -> User:
        # PostgreSQL固有のコード
        ...

SOLID原則

原則 意味 実践
S: 単一責任 クラスは1つの責任を持つ UserValidatorUserSaver を分ける
O: 開放/閉鎖 拡張に開いて修正に閉じる 継承より合成を使う
L: リスコフ置換 サブクラスは基底クラスと置換可能 インターフェースを守る
I: インターフェース分離 大きなIFより小さなIFを複数 必要なメソッドだけ定義
D: 依存逆転 具体でなく抽象に依存する DIコンテナ・Repository pattern

SSOTでの手法管理

各手法の詳細をSSOTに格納:

00_SYSTEM/開発手法カタログ/
├── 00_セレクタ.md     ← このファイルが出発点
├── 01_TDD.md
├── 02_BDD.md
├── 03_DDD.md
├── 04_仕様駆動開発.md
└── 05_クリーンアーキテクチャ.md

新しいプロジェクト開始時は 00_セレクタ.md から始める。