# Swe Architecture

> Diretrizes de arquitetura de software para projetos Python. Use quando o usuário pedir para estruturar um projeto, aplicar SOLID, DDD, Clean Architecture, revisar camadas, definir boundaries de domínio, projetar APIs, criar entidades/value objects, organizar módulos, ou qualquer tarefa relacionada à estrutura e design do sistema.

- Skill: `nxs-cafi/swe-architecture` (Agent Skill)
- Install (CLI): `npx skillmds@latest add nxs-cafi/swe-architecture`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nxs-cafi/swe-architecture/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: nxs-cafi (https://skillmd.com/u/nxs-cafi)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/nxs-cafi/swe-architecture

---


# Arquitetura de Software — Python SWE Agent

## Modelo de Camadas (Clean Architecture adaptada para Python)

```
src/
├── domain/              # Núcleo — zero dependências externas
│   ├── entities/        # Entidades com identidade
│   ├── value_objects/   # Imutáveis, comparados por valor
│   ├── aggregates/      # Raiz de consistência transacional
│   ├── repositories/    # Interfaces (ABC) — não implementações
│   ├── services/        # Domain services (lógica que não cabe em entidade)
│   └── exceptions.py    # Exceções de domínio tipadas
│
├── application/         # Casos de uso — orquestra domínio
│   ├── use_cases/       # Um arquivo por caso de uso
│   ├── dtos/            # Data Transfer Objects (entrada/saída)
│   └── ports/           # Interfaces para infra (email, cache, etc.)
│
├── infrastructure/      # Implementações concretas
│   ├── persistence/     # ORM models, repositories concretos
│   ├── http/            # Clients HTTP externos
│   ├── cache/           # Redis, Memcached
│   ├── messaging/       # Kafka, SQS, Celery
│   └── config/          # Settings, env vars
│
└── interfaces/          # Adaptadores de entrada
    ├── api/             # FastAPI/Django routers, serializers
    ├── cli/             # Click commands
    └── workers/         # Background jobs
```

## SOLID em Python — Aplicação Prática

### S — Single Responsibility
```python
# ❌ RUIM: classe faz tudo
class UserService:
    def create_user(self, data): ...
    def send_welcome_email(self, user): ...  # não é responsabilidade dela
    def hash_password(self, password): ...   # não é responsabilidade dela

# ✅ BOM: responsabilidades separadas
class UserService:
    def __init__(self, repo: UserRepository, hasher: PasswordHasher):
        self._repo = repo
        self._hasher = hasher

    def create_user(self, data: CreateUserDTO) -> User:
        hashed = self._hasher.hash(data.password)
        user = User(email=data.email, password_hash=hashed)
        return self._repo.save(user)

class WelcomeEmailService:
    def send(self, user: User) -> None: ...
```

### O — Open/Closed
```python
# Use Protocol ou ABC para extensão sem modificação
from abc import ABC, abstractmethod

class NotificationChannel(ABC):
    @abstractmethod
    def send(self, recipient: str, message: str) -> None: ...

class EmailChannel(NotificationChannel):
    def send(self, recipient: str, message: str) -> None: ...

class SlackChannel(NotificationChannel):
    def send(self, recipient: str, message: str) -> None: ...

# Novo canal = nova classe, sem tocar no existente
```

### D — Dependency Inversion
```python
# ❌ RUIM: depende de concreção
class OrderService:
    def __init__(self):
        self.db = PostgreSQLRepository()  # acopla a infra

# ✅ BOM: depende de abstração
class OrderService:
    def __init__(self, repo: OrderRepository):  # injeta interface
        self._repo = repo
```

## Domain-Driven Design — Padrões Essenciais

### Entidade vs. Value Object
```python
from dataclasses import dataclass
from uuid import UUID, uuid4

# ENTIDADE — identidade importa, estado muda
class Order:
    def __init__(self, id: UUID, customer_id: UUID):
        self.id = id
        self.customer_id = customer_id
        self._items: list[OrderItem] = []
        self._status = OrderStatus.PENDING

    def add_item(self, item: OrderItem) -> None:
        if self._status != OrderStatus.PENDING:
            raise OrderNotEditableError(self.id)
        self._items.append(item)

# VALUE OBJECT — imutável, sem identidade, comparado por valor
@dataclass(frozen=True)
class Money:
    amount: Decimal
    currency: str

    def __post_init__(self):
        if self.amount < 0:
            raise ValueError("Amount cannot be negative")

    def add(self, other: "Money") -> "Money":
        if self.currency != other.currency:
            raise CurrencyMismatchError()
        return Money(self.amount + other.amount, self.currency)
```

### Exceções de Domínio Tipadas
```python
# domain/exceptions.py
class DomainError(Exception):
    """Base para todos os erros de domínio."""

class OrderNotEditableError(DomainError):
    def __init__(self, order_id: UUID):
        super().__init__(f"Order {order_id} cannot be edited in current status")
        self.order_id = order_id

class InsufficientStockError(DomainError):
    def __init__(self, product_id: UUID, requested: int, available: int):
        super().__init__(
            f"Insufficient stock for product {product_id}: "
            f"requested {requested}, available {available}"
        )
```

### Repository Pattern
```python
# domain/repositories.py — INTERFACE (sem import de ORM)
from abc import ABC, abstractmethod

class OrderRepository(ABC):
    @abstractmethod
    def find_by_id(self, order_id: UUID) -> Order | None: ...

    @abstractmethod
    def save(self, order: Order) -> Order: ...

    @abstractmethod
    def find_pending_by_customer(self, customer_id: UUID) -> list[Order]: ...

# infrastructure/persistence/order_repository.py — IMPLEMENTAÇÃO
class DjangoOrderRepository(OrderRepository):
    def find_by_id(self, order_id: UUID) -> Order | None:
        try:
            model = OrderModel.objects.get(id=order_id)
            return self._to_domain(model)
        except OrderModel.DoesNotExist:
            return None
```

## Estrutura FastAPI — Padrão Recomendado

```python
# interfaces/api/orders/router.py
from fastapi import APIRouter, Depends, HTTPException, status
from application.use_cases.create_order import CreateOrderUseCase
from application.dtos.order import CreateOrderRequest, OrderResponse
from interfaces.api.dependencies import get_create_order_use_case

router = APIRouter(prefix="/orders", tags=["orders"])

@router.post("/", response_model=OrderResponse, status_code=status.HTTP_201_CREATED)
async def create_order(
    request: CreateOrderRequest,
    use_case: CreateOrderUseCase = Depends(get_create_order_use_case),
) -> OrderResponse:
    try:
        order = await use_case.execute(request)
        return OrderResponse.from_domain(order)
    except InsufficientStockError as e:
        raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(e))
    except DomainError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
```

## Anti-Patterns — Sempre Evitar

| Anti-Pattern | Problema | Solução |
|---|---|---|
| Fat Model (Django) | Domínio vaza para ORM | Separar domain entity do ORM model |
| Service como namespace | Funções estáticas sem coesão | Use cases com dependências explícitas |
| Import circular | Arquitetura quebrada | Invertir dependências com ABC |
| God object | Viola SRP, dificulta teste | Decomposição por responsabilidade |
| Anemic Domain Model | Lógica de negócio fora do domínio | Encapsular comportamento nas entidades |

## Para Referências Detalhadas

- `~/.cursor/skills/references/solid-python.md` — exemplos completos de cada princípio
- `~/.cursor/skills/references/ddd-patterns.md` — Aggregates, Domain Events, Specifications
- `~/.cursor/skills/references/clean-arch-django.md` — adaptação para projetos Django existentes
- `~/.cursor/skills/references/fastapi-structure.md` — estrutura completa de projeto FastAPI

