クリーンアーキテクチャ#

概要#

クリーンアーキテクチャ(Clean Architecture)は、Robert C. Martin(Uncle Bob)によって提唱されたソフトウェアアーキテクチャパターン。

ビジネスロジックを中心に配置し、外部依存から独立させることで、テスタビリティ、保守性、柔軟性を高める。

依存関係のルール#

クリーンアーキテクチャの最も重要な原則は依存関係の方向。
依存関係は内側(中心)に向かう一方向のみ とする

各層の役割#

1. エンティティ層(Entities)#

  • ビジネスの最も基本的なルール

  • 他のどの層にも依存しない

  • エンタープライズ全体で共有されるビジネスロジック

class User:
    def __init__(self, id, name, email):
        self.id = id
        self.name = name
        self.email = email
    
    def validate_email(self):
        return "@" in self.email

2. ユースケース層(Use Cases)#

  • アプリケーション固有のビジネスルール

  • システムの全ユースケースを実装

  • エンティティのみに依存

class CreateUserUseCase:
    def __init__(self, user_repository):
        self.user_repository = user_repository
    
    def execute(self, name, email):
        user = User(None, name, email)
        if not user.validate_email():
            raise ValueError("Invalid email")
        return self.user_repository.save(user)

3. インターフェースアダプター層(Interface Adapters)#

  • データフォーマットの変換

  • Controllers、Presenters、Gateways

  • 外部と内部の橋渡し

class UserController:
    def __init__(self, create_user_use_case):
        self.create_user_use_case = create_user_use_case
    
    def create(self, request):
        try:
            user = self.create_user_use_case.execute(
                request["name"], 
                request["email"]
            )
            return {"status": "success", "user_id": user.id}
        except ValueError as e:
            return {"status": "error", "message": str(e)}

4. フレームワーク&ドライバー層(Frameworks & Drivers)#

  • Webフレームワーク

  • データベース

  • UI

  • 外部ライブラリ

依存性逆転の原則(DIP)#

外側の層が内側の層に依存するには、インターフェース(抽象)を介して行う。

# ユースケース層(内側)- インターフェースを定義
from abc import ABC, abstractmethod

class UserRepository(ABC):
    @abstractmethod
    def save(self, user):
        pass
    
    @abstractmethod
    def find_by_id(self, user_id):
        pass

# インフラ層(外側)- インターフェースを実装
class PostgresUserRepository(UserRepository):
    def save(self, user):
        # PostgreSQL固有の実装
        pass
    
    def find_by_id(self, user_id):
        # PostgreSQL固有の実装
        pass

メリット#

  1. 独立性

    • フレームワークに依存しない

    • データベースに依存しない

    • UIに依存しない

    • 外部エージェンシーに依存しない

  2. テスタビリティ

    • ビジネスロジックを外部依存なしでテスト可能

    • モックやスタブを使いやすい

  3. 保守性

    • 変更の影響範囲が限定される

    • ビジネスロジックが明確に分離されている

  4. 柔軟性

    • データベースの変更が容易

    • UIフレームワークの変更が容易

    • ビジネスロジックに影響を与えずに外部依存を変更可能

デメリット#

  • 学習コスト: 理解と実装に時間がかかる

  • 初期コスト: 小規模プロジェクトには過剰

  • 抽象化のオーバーヘッド: インターフェースやアダプターの追加コード

  • 複雑性: 単純なCRUD操作でも多くの層を経由する

適用場面#

クリーンアーキテクチャが適している場合:

  • 長期的なメンテナンスが必要なシステム

  • 複雑なビジネスロジックを持つシステム

  • 技術スタックの変更が予想されるシステム

  • 高いテストカバレッジが求められるシステム

  • 複数のインターフェース(Web、CLI、APIなど)を持つシステム

参考文献#