Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use when architecting complex backend systems or refactoring existing applications for better maintainability.
.claude/skills/asymmetric-al-architecture-patterns/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-16 | ✗→✓ | ▲ Improved | 157% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 263% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 125% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 87% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 90% | 0% |
Master proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design to build maintainable, testable, and scalable systems.
Layers (dependency flows inward):
Key Principles:
Components:
Benefits:
Strategic Patterns:
Tactical Patterns:
app/
├── domain/ # Entities & business rules
│ ├── entities/
│ │ ├── user.py
│ │ └── order.py
│ ├── value_objects/
│ │ ├── email.py
│ │ └── money.py
│ └── interfaces/ # Abstract interfaces
│ ├── user_repository.py
│ └── payment_gateway.py
├── use_cases/ # Application business rules
│ ├── create_user.py
│ ├── process_order.py
│ └── send_notification.py
├── adapters/ # Interface implementations
│ ├── repositories/
│ │ ├── postgres_user_repository.py
│ │ └── redis_cache_repository.py
│ ├── controllers/
│ │ └── user_controller.py
│ └── gateways/
│ ├── stripe_payment_gateway.py
│ └── resend_email_gateway.py
└── infrastructure/ # Framework & external concerns
├── database.py
├── config.py
└── logging.pypython# domain/entities/user.py from dataclasses import dataclass from datetime import datetime from typing import Optional @dataclass class User: """Core user entity - no framework dependencies.""" id: str email: str name: str created_at: datetime is_active: bool = True def deactivate(self): """Business rule: deactivating user.""" self.is_active = False def can_place_order(self) -> bool: """Business rule: active users can order.""" return self.is_active # domain/interfaces/user_repository.py from abc import ABC, abstractmethod from typing import Optional, List from domain.entities.user import User class IUserRepository(ABC): """Port: defines contract, no implementation.""" @abstractmethod async def find_by_id(self, user_id: str) -> Optional[User]: pass @abstractmethod async def find_by_email(self, email: str) -> Optional[User]: pass @abstractmethod async def save(self, user: User) -> User: pass @abstractmethod async def delete(self, user_id: str) -> bool: pass # use_cases/create_user.py from domain.entities.user import User from domain.interfaces.user_repository import IUserRepository from dataclasses import dataclass from datetime import datetime import uuid @dataclass class CreateUserRequest: email: str name: str @dataclass class CreateUserResponse: user: Optional[User] success: bool error: Optional[str] = None class CreateUserUseCase: """Use case: orchestrates business logic.""" def __init__(self, user_repository: IUserRepository): self.user_repository = user_repository async def execute(self, request: CreateUserRequest) -> CreateUserResponse: # Business validation existing = await self.user_repository.find_by_email(request.email) if existing: return CreateUserResponse( user=None, success=False, error="Email already exists" ) # Create entity user = User( id=str(uuid.uuid4()), email=request.email, name=request.name, created_at=datetime.now(), is_active=True ) # Persist saved_user = await self.user_repository.save(user) return CreateUserResponse( user=saved_user, success=True ) # adapters/repositories/postgres_user_repository.py from domain.interfaces.user_repository import IUserRepository from domain.entities.user import User from typing import Optional import asyncpg class PostgresUserRepository(IUserRepository): """Adapter: PostgreSQL implementation.""" def __init__(self, pool: asyncpg.Pool): self.pool = pool async def find_by_id(self, user_id: str) -> Optional[User]: async with self.pool.acquire() as conn: row = await conn.fetchrow( "SELECT * FROM users WHERE id = $1", user_id ) return self._to_entity(row) if row else None async def find_by_email(self, email: str) -> Optional[User]: async with self.pool.acquire() as conn: row = await conn.fetchrow( "SELECT * FROM users WHERE email = $1", email ) return self._to_entity(row) if row else None async def save(self, user: User) -> User: async with self.pool.acquire() as conn: await conn.execute( """ INSERT INTO users (id, email, name, created_at, is_active) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (id) DO UPDATE SET email = $2, name = $3, is_active = $5 """, user.id, user.email, user.name, user.created_at, user.is_active ) return user async def delete(self, user_id: str) -> bool: async with self.pool.acquire() as conn: result = await conn.execute( "DELETE FROM users WHERE id = $1", user_id ) return result == "DELETE 1" def _to_entity(self, row) -> User: """Map database row to entity.""" return User( id=row["id"], email=row["email"], name=row["name"], created_at=row["created_at"], is_active=row["is_active"] ) # adapters/controllers/user_controller.py from fastapi import APIRouter, Depends, HTTPException, Request from use_cases.create_user import CreateUserUseCase, CreateUserRequest from adapters.repositories.user_repository import PostgresUserRepository from pydantic import BaseModel router = APIRouter() class CreateUserDTO(BaseModel): email: str name: str def get_create_user_use_case(request: Request) -> CreateUserUseCase: """FastAPI dependency provider for CreateUserUseCase.""" repository = PostgresUserRepository(request.app.state.db_pool) return CreateUserUseCase(user_repository=repository) @router.post("/users") async def create_user( dto: CreateUserDTO, use_case: CreateUserUseCase = Depends(get_create_user_use_case) ): """Controller: handles HTTP concerns only.""" request = CreateUserRequest(email=dto.email, name=dto.name) response = await use_case.execute(request) if not response.success: raise HTTPException(status_code=400, detail=response.error) return {"user": response.user}
python# Core domain (hexagon center) import asyncio class OrderService: """Domain service - no infrastructure dependencies.""" def __init__( self, order_repository: OrderRepositoryPort, payment_gateway: PaymentGatewayPort, notification_service: NotificationPort ): self.orders = order_repository self.payments = payment_gateway self.notifications = notification_service async def place_order(self, order: Order) -> OrderResult: # Business logic if not order.is_valid(): return OrderResult(success=False, error="Invalid order") # Use ports (interfaces) payment = await self.payments.charge( amount=order.total, customer=order.customer_id ) if not payment.success: return OrderResult(success=False, error="Payment failed") order.mark_as_paid() saved_order = await self.orders.save(order) await self.notifications.send( to=order.customer_email, subject="Order confirmed", body=f"Order {order.id} confirmed" ) return OrderResult(success=True, order=saved_order) # Ports (interfaces) class OrderRepositoryPort(ABC): @abstractmethod async def save(self, order: Order) -> Order: pass class PaymentGatewayPort(ABC): @abstractmethod async def charge(self, amount: Money, customer: str) -> PaymentResult: pass class NotificationPort(ABC): @abstractmethod async def send(self, to: str, subject: str, body: str): pass # Adapters (implementations) class StripePaymentAdapter(PaymentGatewayPort): """Primary adapter: connects to Stripe API.""" def __init__(self, api_key: str): self.stripe = stripe self.stripe.api_key = api_key async def charge(self, amount: Money, customer: str) -> PaymentResult: try: # Stripe Python client call is synchronous; run it off the event loop. charge = await asyncio.to_thread( self.stripe.Charge.create, amount=amount.cents, currency=amount.currency, customer=customer, ) return PaymentResult(success=True, transaction_id=charge.id) except stripe.error.CardError as e: return PaymentResult(success=False, error=str(e)) class MockPaymentAdapter(PaymentGatewayPort): """Test adapter: no external dependencies.""" async def charge(self, amount: Money, customer: str) -> PaymentResult: return PaymentResult(success=True, transaction_id="mock-123")
python# Value Objects (immutable) from dataclasses import dataclass from typing import Optional @dataclass(frozen=True) class Email: """Value object: validated email.""" value: str def __post_init__(self): if "@" not in self.value: raise ValueError("Invalid email") @dataclass(frozen=True) class Money: """Value object: amount with currency.""" amount: int # cents currency: str def add(self, other: "Money") -> "Money": if self.currency != other.currency: raise ValueError("Currency mismatch") return Money(self.amount + other.amount, self.currency) # Entities (with identity) class Order: """Entity: has identity, mutable state.""" def __init__(self, id: str, customer: Customer): self.id = id self.customer = customer self.items: List[OrderItem] = [] self.status = OrderStatus.PENDING self._events: List[DomainEvent] = [] def add_item(self, product: Product, quantity: int): """Business logic in entity.""" item = OrderItem(product, quantity) self.items.append(item) self._events.append(ItemAddedEvent(self.id, item)) def total(self) -> Money: """Calculated property.""" if not self.items: raise ValueError("Cannot calculate total for empty order") total = self.items[0].subtotal() for item in self.items[1:]: total = total.add(item.subtotal()) return total def submit(self): """State transition with business rules.""" if not self.items: raise ValueError("Cannot submit empty order") if self.status != OrderStatus.PENDING: raise ValueError("Order already submitted") self.status = OrderStatus.SUBMITTED self._events.append(OrderSubmittedEvent(self.id)) # Aggregates (consistency boundary) class Customer: """Aggregate root: controls access to entities.""" def __init__(self, id: str, email: Email): self.id = id self.email = email self._addresses: List[Address] = [] self._orders: List[str] = [] # Order IDs, not full objects def add_address(self, address: Address): """Aggregate enforces invariants.""" if len(self._addresses) >= 5: raise ValueError("Maximum 5 addresses allowed") self._addresses.append(address) @property def primary_address(self) -> Optional[Address]: return next((a for a in self._addresses if a.is_primary), None) # Domain Events @dataclass class OrderSubmittedEvent: order_id: str occurred_at: datetime = field(default_factory=datetime.now) # Repository (aggregate persistence) class OrderRepository: """Repository: persist/retrieve aggregates.""" async def find_by_id(self, order_id: str) -> Optional[Order]: """Reconstitute aggregate from storage.""" pass async def save(self, order: Order): """Persist aggregate and publish events.""" await self._persist(order) await self._publish_events(order._events) order._events.clear()
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 9,300 | 10,330 | +11% | 1 | 1 | 0% | 1,651 | 5,708 | +246% | 0 | 0 | — |
case-02 | pass→pass | 8,454 | 7,027 | -17% | 1 | 1 | 0% | 1,377 | 4,993 | +263% | 0 | 0 | — |
case-03 | pass→pass | 14,055 | 10,149 | -28% | 1 | 1 | 0% | 2,539 | 5,705 | +125% | 0 | 0 | — |
case-04 | pass→pass | 17,241 | 14,753 | -14% | 1 | 1 | 0% | 3,530 | 6,604 | +87% | 0 | 0 | — |
case-05 | pass→pass | 18,692 | 14,520 | -22% | 1 | 1 | 0% | 3,400 | 6,460 | +90% | 0 | 0 | — |
case-06 | pass→pass | 18,240 | 15,114 | -17% | 1 | 1 | 0% | 3,271 | 6,555 | +100% | 0 | 0 | — |
case-07 | pass→pass | 13,372 | 11,530 | -14% | 1 | 1 | 0% | 2,399 | 6,075 | +153% | 0 | 0 | — |
case-08 | pass→pass | 14,452 | 11,640 | -19% | 1 | 1 | 0% | 2,642 | 5,855 | +122% | 0 | 0 | — |
case-09 | pass→pass | 12,017 | 8,749 | -27% | 1 | 1 | 0% | 2,136 | 5,431 | +154% | 0 | 0 | — |
case-10 | fail→fail | 12,704 | 11,808 | -7% | 1 | 1 | 0% | 2,367 | 5,993 | +153% | 0 | 0 | — |
case-11 | fail→fail | 13,577 | 12,369 | -9% | 1 | 1 | 0% | 2,105 | 5,919 | +181% | 0 | 0 | — |
case-12 | pass→pass | 14,679 | 14,423 | -2% | 1 | 1 | 0% | 2,748 | 6,709 | +144% | 0 | 0 | — |
case-13 | pass→pass | 12,702 | 11,275 | -11% | 1 | 1 | 0% | 2,170 | 5,893 | +172% | 0 | 0 | — |
case-14 | pass→pass | 14,212 | 14,865 | +5% | 1 | 1 | 0% | 2,593 | 6,542 | +152% | 0 | 0 | — |
case-15 | pass→pass | 14,658 | 12,485 | -15% | 1 | 1 | 0% | 2,534 | 6,123 | +142% | 0 | 0 | — |
case-16 | fail→pass | 16,211 | 16,879 | +4% | 1 | 1 | 0% | 2,791 | 7,179 | +157% | 0 | 0 | — |
case-17 | pass→pass | 14,380 | 11,203 | -22% | 1 | 1 | 0% | 2,341 | 5,828 | +149% | 0 | 0 | — |
case-18 | pass→pass | 16,698 | 13,622 | -18% | 1 | 1 | 0% | 2,935 | 6,191 | +111% | 0 | 0 | — |
case-19 | pass→pass | 10,205 | 8,882 | -13% | 1 | 1 | 0% | 1,975 | 5,376 | +172% | 0 | 0 | — |
case-20 | pass→pass | 9,219 | 9,636 | +5% | 1 | 1 | 0% | 1,689 | 5,346 | +217% | 0 | 0 | — |
case-21 | pass→pass | 5,046 | 6,465 | +28% | 1 | 1 | 0% | 1,274 | 5,206 | +309% | 0 | 0 | — |
case-22 | pass→pass | 11,943 | 10,833 | -9% | 1 | 1 | 0% | 2,562 | 6,056 | +136% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +5 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.