{"id":"architecture-patterns","name":"architecture-patterns","summary":"クリーンアーキテクチャ、ヘキサゴナルアーキテクチャ、ドメイン駆動デザインなど、実績のあるバックエンドアーキテクチャパターンを実装しましょう。","body":"# Architecture Patterns\n\nMaster proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design to build maintainable, testable, and scalable systems.\n\n**Given:** a service boundary or module to architect.\n**Produces:** layered structure with clear dependency rules, interface definitions, and test boundaries.\n\n## When to Use This Skill\n\n- Designing new backend services or microservices from scratch\n- Refactoring monolithic applications where business logic is entangled with ORM models or HTTP concerns\n- Establishing bounded contexts before splitting a system into services\n- Debugging dependency cycles where infrastructure code bleeds into the domain layer\n- Creating testable codebases where use-case tests do not require a running database\n- Implementing domain-driven design tactical patterns (aggregates, value objects, domain events)\n\n## Core Concepts\n\n### 1. Clean Architecture (Uncle Bob)\n\n**Layers (dependency flows inward):**\n\n- **Entities**: Core business models, no framework imports\n- **Use Cases**: Application business rules, orchestrate entities\n- **Interface Adapters**: Controllers, presenters, gateways — translate between use cases and external formats\n- **Frameworks & Drivers**: UI, database, external services — all at the outermost ring\n\n**Key Principles:**\n\n- Dependencies point inward only; inner layers know nothing about outer layers\n- Business logic is independent of frameworks, databases, and delivery mechanisms\n- Every layer boundary is crossed via an abstract interface\n- Testable without UI, database, or external services\n\n### 2. Hexagonal Architecture (Ports and Adapters)\n\n**Components:**\n\n- **Domain Core**: Business logic lives here, framework-free\n- **Ports**: Abstract interfaces that define how the core interacts with the outside world (driving and driven)\n- **Adapters**: Concrete implementations of ports (PostgreSQL adapter, Stripe adapter, REST adapter)\n\n**Benefits:**\n\n- Swap implementations without touching the core (e.g., replace PostgreSQL with DynamoDB)\n- Use in-memory adapters in tests — no Docker required\n- Technology decisions deferred to the edges\n\n### 3. Domain-Driven Design (DDD)\n\n**Strategic Patterns:**\n\n- **Bounded Contexts**: Isolate a coherent model for one subdomain; avoid sharing a single model across the whole system\n- **Context Mapping**: Define how contexts relate (Anti-Corruption Layer, Shared Kernel, Open Host Service)\n- **Ubiquitous Language**: Every term in code matches the term used by domain experts\n\n**Tactical Patterns:**\n\n- **Entities**: Objects with stable identity that change over time\n- **Value Objects**: Immutable objects identified by their attributes (Email, Money, Address)\n- **Aggregates**: Consistency boundaries; only the root is accessible from outside\n- **Repositories**: Persist and reconstitute aggregates; abstract over the storage mechanism\n- **Domain Events**: Capture things that happened inside the domain; used for cross-aggregate coordination\n\n## Detailed patterns and worked examples\n\nDetailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.\n\n## Testing — In-Memory Adapters\n\nThe hallmark of correctly applied Clean Architecture is that every use case can be exercised in a plain unit test with no real database, no Docker, and no network:\n\n```python\n# tests/unit/test_create_user.py\nimport asyncio\nfrom typing import Dict, Optional\nfrom domain.entities.user import User\nfrom domain.interfaces.user_repository import IUserRepository\nfrom use_cases.create_user import CreateUserUseCase, CreateUserRequest\n\n\nclass InMemoryUserRepository(IUserRepository):\n    def __init__(self):\n        self._store: Dict[str, User] = {}\n\n    async def find_by_id(self, user_id: str) -> Optional[User]:\n        return self._store.get(user_id)\n\n    async def find_by_email(self, email: str) -> Optional[User]:\n        return next((u for u in self._store.values() if u.email == email), None)\n\n    async def save(self, user: User) -> User:\n        self._store[user.id] = user\n        return user\n\n    async def delete(self, user_id: str) -> bool:\n        return self._store.pop(user_id, None) is not None\n\n\nasync def test_create_user_succeeds():\n    repo = InMemoryUserRepository()\n    use_case = CreateUserUseCase(user_repository=repo)\n\n    response = await use_case.execute(CreateUserRequest(email=\"alice@example.com\", name=\"Alice\"))\n\n    assert response.success\n    assert response.user.email == \"alice@example.com\"\n    assert response.user.id is not None\n\n\nasync def test_duplicate_email_rejected():\n    repo = InMemoryUserRepository()\n    use_case = CreateUserUseCase(user_repository=repo)\n\n    await use_case.execute(CreateUserRequest(email=\"alice@example.com\", name=\"Alice\"))\n    response = await use_case.execute(CreateUserRequest(email=\"alice@example.com\", name=\"Alice2\"))\n\n    assert not response.success\n    assert \"already exists\" in response.error\n```\n\n## Troubleshooting\n\n### Use case tests require a running database\n\nBusiness logic has leaked into the infrastructure layer. Move all database calls behind an `IRepository` interface and inject an in-memory implementation in tests (see Testing section above). The use case constructor must accept the abstract port, not the concrete class.\n\n### Circular imports between layers\n\nA common symptom is `ImportError: cannot import name X` between `use_cases` and `adapters`. This happens when a use case imports a concrete adapter class instead of the abstract port. Enforce the rule: `use_cases/` imports only from `domain/` (entities and interfaces). It must never import from `adapters/` or `infrastructure/`.\n\n### Framework decorators appearing in domain entities\n\nIf SQLAlchemy `Column()` or Pydantic `Field()` annotations appear on domain entities, the entity is no longer pure. Create a separate ORM model in `adapters/repositories/` and map to/from the domain entity in the repository's `_to_entity()` method.\n\n### All logic ending up in controllers\n\nWhen the controller grows beyond HTTP parsing and response formatting, extract the logic into a use case class. A controller method should do three things only: parse the request, call a use case, map the response.\n\n### Value objects raising errors too late\n\nValidate invariants in `__post_init__` (Python) or the constructor so an invalid `Email` or `Money` cannot be constructed at all. This surfaces bad data at the boundary, not deep inside business logic.\n\n### Context bleed across bounded contexts\n\nIf the `Order` context is importing `User` entities from the `Identity` context, introduce an Anti-Corruption Layer. The `Order` context should hold its own lightweight `CustomerId` value object and only call the `Identity` context through an explicit interface.\n\n## Advanced Patterns\n\nFor detailed DDD bounded context mapping, full multi-service project trees, Anti-Corruption Layer implementations, and Onion Architecture comparisons, see:\n\n- [`references/advanced-patterns.md`](references/advanced-patterns.md)\n\n## Related Skills\n\n- `microservices-patterns` — Apply these architecture patterns when decomposing a monolith into services\n- `cqrs-implementation` — Use Clean Architecture as the structural foundation for CQRS command/query separation\n- `saga-orchestration` — Sagas require well-defined aggregate boundaries, which DDD tactical patterns provide\n- `event-store-design` — Domain events produced by aggregates feed directly into an event store","author":"@wshobson","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/wshobson/agents/tree/main/plugins/backend-development/skills/architecture-patterns","license":"MIT","category":"testing","lang":"en","tokens":1558,"stars":0,"calls30d":2,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"references/advanced-patterns.md","size":15329,"sha256":"e1cb31c83b532e579991de277836a1ea5e3d88b2ca30fc8ac16f6047ceca439e"},{"path":"references/details.md","size":10993,"sha256":"a53411600b253b343247db9d86140f3136ee7bd26a67aa8411962bcc1f5ff981"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":[]}}