1
Faça a análise inicial (igual ao Clean)
- Liste os fluxos e funcionalidades principais do sistema.
- Extraia entidades e modele o domínio.
- Defina os casos de uso e identifique integrações necessárias.
2
Nomeie as PORTS (Interfaces do Core)
- Ports de entrada (inbound): Contratos que o core aceita receber (ex: comandos/consultas, APIs, filas).
- Ports de saída (outbound): Contratos que o core usa para acessar o mundo externo (ex: repositórios, gateways, notificadores).
-
Inbound Example:
user_service.py, trading_api.py...
-
Outbound Example:
user_repository.py, price_history_repository.py, binance_gateway.py, email_notifier.py...
3
Estruture o diretório Hexagonal
- Separe o core e as dependências em camadas claras.
- Implemente adapters de entrada e saída conforme as ports.
src/
domain/ # Entidades e regras de negócio puras
user/
operation/
market_data/
...
application/ # Casos de uso, orquestração do core
user/
operation/
market_data/
...
ports/
inbound/ # Interfaces de entrada (contratos)
user_service.py
trading_api.py
...
outbound/ # Interfaces de saída (contratos)
user_repository.py
price_history_repository.py
binance_gateway.py
email_notifier.py
...
adapters/
inbound/ # Implementações de entrada (ex: REST, CLI)
fastapi/
routers/
schemas/
cli/
commands/
outbound/ # Implementações de saída (banco, API, etc)
db/
user_repository_impl.py
price_history_repository_impl.py
binance/
binance_gateway_impl.py
email/
email_notifier_impl.py
shared/ # Utilitários, log, exceptions, helpers
logging/
utils/
...
4
Como projetar nomes/camadas sem erro?
- Tudo que depende do core = port de saída + adapter de saída
- Tudo que conversa com o core = port de entrada + adapter de entrada
- O core nunca importa de adapters, só de ports!
- Cada entidade/fluxo/caso de uso identificado vira classe/módulo do core, com port e adapter quando necessário.
5
Exemplo prático: Simular estratégia de grid
- domain/operation/entities/grid_simulation.py — Entidade da simulação
- application/operation/simulate_grid_use_case.py — Caso de uso/orquestração
- ports/inbound/grid_simulation_service.py — Interface de entrada (ex: simulate_grid(...))
- ports/outbound/price_history_repository.py — Interface para obter preços externos
- adapters/inbound/fastapi/routers/grid_simulation_router.py — REST que chama a port de entrada
- adapters/outbound/db/price_history_repository_impl.py — Repo banco
- adapters/outbound/binance/binance_gateway_impl.py — Integração Binance
- shared/logging/logger_factory.py — Logger compartilhado
6
Resumo e mentalidade hexagonal
- Liste fluxos e funcionalidades principais
- Extraia entidades e casos de uso
- Modele domínio e contratos (ports)
- Defina adapters por dependência externa
- Monte a estrutura pensando: "O core é cego, não importa de fora"
- Adapters plugam portas do core no mundo real
Dicas de Ouro:
- Use nomes claros: "port" para contratos, "adapter" para implementações.
- O core NUNCA depende de adapter/concreto, só de contratos!
- Para evoluir, crie/adapte ports e adapters sem mexer no core.
- Desenhe a estrutura antes de codar, evita retrabalho!
🔎 Analise entidades e casos de uso
🚪 Defina ports (contratos)
🔌 Implemente adapters
🧠 Core sem dependência externa
📁 Diretórios claros, desacoplados
💡 Facilidade para crescer e testar