Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Software architecture patterns skill from a 146-skill AI agent marketplace for Claude Code (Opus 4.6/Sonnet 4.6).
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
SKILL.md
1---2name: architecture-patterns3description: Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use this skill when designing clean architecture for a new microservice, when refactoring a monolith to use bounded contexts, when implementing hexagonal or onion architecture patterns, or when debugging dependency cycles between application layers.4---56# Architecture Patterns78Master proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design to build maintainable, testable, and scalable systems.910**Given:** a service boundary or module to architect.11**Produces:** layered structure with clear dependency rules, interface definitions, and test boundaries.1213## When to Use This Skill1415- Designing new backend services or microservices from scratch16- Refactoring monolithic applications where business logic is entangled with ORM models or HTTP concerns17- Establishing bounded contexts before splitting a system into services18- Debugging dependency cycles where infrastructure code bleeds into the domain layer19- Creating testable codebases where use-case tests do not require a running database20- Implementing domain-driven design tactical patterns (aggregates, value objects, domain events)2122## Core Concepts2324### 1. Clean Architecture (Uncle Bob)2526**Layers (dependency flows inward):**2728- **Entities**: Core business models, no framework imports29- **Use Cases**: Application business rules, orchestrate entities30- **Interface Adapters**: Controllers, presenters, gateways — translate between use cases and external formats31- **Frameworks & Drivers**: UI, database, external services — all at the outermost ring3233**Key Principles:**3435- Dependencies point inward only; inner layers know nothing about outer layers36- Business logic is independent of frameworks, databases, and delivery mechanisms37- Every layer boundary is crossed via an abstract interface38- Testable without UI, database, or external services3940### 2. Hexagonal Architecture (Ports and Adapters)4142**Components:**4344- **Domain Core**: Business logic lives here, framework-free45- **Ports**: Abstract interfaces that define how the core interacts with the outside world (driving and driven)46- **Adapters**: Concrete implementations of ports (PostgreSQL adapter, Stripe adapter, REST adapter)4748**Benefits:**4950- Swap implementations without touching the core (e.g., replace PostgreSQL with DynamoDB)51- Use in-memory adapters in tests — no Docker required52- Technology decisions deferred to the edges5354### 3. Domain-Driven Design (DDD)5556**Strategic Patterns:**5758- **Bounded Contexts**: Isolate a coherent model for one subdomain; avoid sharing a single model across the whole system59- **Context Mapping**: Define how contexts relate (Anti-Corruption Layer, Shared Kernel, Open Host Service)60- **Ubiquitous Language**: Every term in code matches the term used by domain experts6162**Tactical Patterns:**6364- **Entities**: Objects with stable identity that change over time65- **Value Objects**: Immutable objects identified by their attributes (Email, Money, Address)66- **Aggregates**: Consistency boundaries; only the root is accessible from outside67- **Repositories**: Persist and reconstitute aggregates; abstract over the storage mechanism68- **Domain Events**: Capture things that happened inside the domain; used for cross-aggregate coordination6970## Detailed patterns and worked examples7172Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.7374## Testing — In-Memory Adapters7576The 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:7778```python79# tests/unit/test_create_user.py80import asyncio81from typing import Dict, Optional82from domain.entities.user import User83from domain.interfaces.user_repository import IUserRepository84from use_cases.create_user import CreateUserUseCase, CreateUserRequest858687class InMemoryUserRepository(IUserRepository):88def __init__(self):89self._store: Dict[str, User] = {}9091async def find_by_id(self, user_id: str) -> Optional[User]:92return self._store.get(user_id)9394async def find_by_email(self, email: str) -> Optional[User]:95return next((u for u in self._store.values() if u.email == email), None)9697async def save(self, user: User) -> User:98self._store[user.id] = user99return user100101async def delete(self, user_id: str) -> bool:102return self._store.pop(user_id, None) is not None103104105async def test_create_user_succeeds():106repo = InMemoryUserRepository()107use_case = CreateUserUseCase(user_repository=repo)108109response = await use_case.execute(CreateUserRequest(email="[email protected]", name="Alice"))110111assert response.success112assert response.user.email == "[email protected]"113assert response.user.id is not None114115116async def test_duplicate_email_rejected():117repo = InMemoryUserRepository()118use_case = CreateUserUseCase(user_repository=repo)119120await use_case.execute(CreateUserRequest(email="[email protected]", name="Alice"))121response = await use_case.execute(CreateUserRequest(email="[email protected]", name="Alice2"))122123assert not response.success124assert "already exists" in response.error125```126127## Troubleshooting128129### Use case tests require a running database130131Business 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.132133### Circular imports between layers134135A 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/`.136137### Framework decorators appearing in domain entities138139If 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.140141### All logic ending up in controllers142143When 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.144145### Value objects raising errors too late146147Validate 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.148149### Context bleed across bounded contexts150151If 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.152153## Advanced Patterns154155For detailed DDD bounded context mapping, full multi-service project trees, Anti-Corruption Layer implementations, and Onion Architecture comparisons, see:156157- [`references/advanced-patterns.md`](references/advanced-patterns.md)158159## Related Skills160161- `microservices-patterns` — Apply these architecture patterns when decomposing a monolith into services162- `cqrs-implementation` — Use Clean Architecture as the structural foundation for CQRS command/query separation163- `saga-orchestration` — Sagas require well-defined aggregate boundaries, which DDD tactical patterns provide164- `event-store-design` — Domain events produced by aggregates feed directly into an event store165