Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesArquitetura hexagonal, também chamada de Ports and Adapters, organiza o código para que as regras de negócio e os casos de uso dependam de contratos que expressam o que eles precisam, enquanto banco de dados, HTTP, CLI, filas e APIs externas ficam nas bordas do sistema. Na prática, o domínio não sabe qual classe o persiste nem qual interface iniciou a operação. Isso não elimina a necessidade de um ponto em que os objetos concretos são montados e conectados: esse ponto existe, mas fica fora do núcleo.
O que significa “o domínio não sabe quem o chama”
Na documentação de orientação prescritiva da AWS, o núcleo da aplicação é descrito como o lugar das regras de negócio, e as portas são abstrações para a interação com o mundo exterior. Um adaptador faz a tradução entre uma tecnologia externa e o contrato da aplicação. Há dois sentidos de uso:
As an Amazon Associate I earn from qualifying purchases.
- Adaptador primário (entrada): conduz uma solicitação para dentro do núcleo. Exemplos: uma rota HTTP, um comando de terminal ou um worker que consome uma fila.
- Adaptador secundário (saída): atende a uma necessidade do núcleo para fora. Exemplos: persistência em banco, envio de e-mail ou chamada a um serviço de pagamento.
A mudança em relação a uma arquitetura em camadas tradicional está na direção da dependência. Em vez de a regra de negócio importar o ORM, o cliente de nuvem ou o framework web, o contrato pertence à necessidade do núcleo e a implementação concreta é que conhece esse contrato. Assim, trocar uma integração não exige alterar a regra que a utiliza, desde que o comportamento do contrato continue o mesmo.
A AWS formula a ideia de duas maneiras que valem ser citadas literalmente:
#1 Best Overall
- “Ports are technology-agnostic entry points into an application component.”
- “A port can have multiple adapters without any risk to the port or to the application component.”
O formato hexagonal do diagrama é só uma convenção visual para representar várias fronteiras. Não há exatamente seis portas nem seis componentes. Para explicar a arquitetura a outra pessoa, use setas e nomes de contratos, não a geometria.
Roteiro para construir do zero em Python
- Descreva uma regra ou caso de uso concreto. Comece pela linguagem do problema: entidades, valores e as operações que o usuário precisa realizar. Não comece escolhendo FastAPI, um ORM ou uma estrutura de pastas.
- Mantenha as regras de domínio sem I/O. No núcleo, evite importar framework, cliente de banco, SDK ou leitura de variáveis de ambiente. O livro Architecture Patterns with Python enfatiza que o modelo de domínio não deve carregar dependências de infraestrutura.
- Identifique as dependências externas de cada caso de uso. Um repositório, um relógio ou um gateway de pagamento pode virar porta de saída, mas só se o caso de uso realmente precisar dele. Criar abstrações sem uma fronteira que as justifique é um erro comum.
- Declare um contrato pequeno. Em Python, uma porta costuma ser uma classe base abstrata (
ABC) com métodos abstratos. O tutorial AWS declara as portas em um pacotedomain/portse faz o handler receber a dependência pelo tipo da porta. Outras formas de tipagem estrutural são possíveis, mas o material que serviu de base não compara mecanismos entre si. - Implemente adaptadores para tecnologias específicas. No tutorial AWS, há um adaptador para DynamoDB e a entrada é feita por Lambda e API Gateway. Para aprender localmente, uma implementação em memória permite testar o caso de uso sem provisionar serviço algum.
- Conecte as implementações na composição. Na inicialização da aplicação, construa os adaptadores concretos e injete-os nos casos de uso e handlers. A borda conhece as implementações; o domínio recebe o que precisa e não procura nada por conta própria.
- Teste por fronteira. Teste o domínio e os casos de uso com dependências falsas. Teste cada adaptador separadamente contra o contrato da porta e acrescente testes de integração quando o comportamento do sistema externo for relevante para a regra.
Um exemplo mínimo: porta, caso de uso e adaptador em memória
O exemplo abaixo é ilustrativo e foi escrito apenas para mostrar a direção das dependências. Ele assume que a entidade Pedido, com um método confirmar() e um atributo id, está definida no domínio.
Rank #2
from abc import ABC, abstractmethod
class PedidoRepository(ABC): # porta de saída
@abstractmethod
def salvar(self, pedido) -> None: ...
@abstractmethod
def buscar(self, pedido_id: str): ...
class ConfirmarPedido: # caso de uso
def __init__(self, pedidos: PedidoRepository):
self._pedidos = pedidos
def executar(self, pedido_id: str) -> None:
pedido = self._pedidos.buscar(pedido_id)
if pedido is None:
raise ValueError("pedido não encontrado")
pedido.confirmar()
self._pedidos.salvar(pedido)
class RepositorioEmMemoria(PedidoRepository): # adaptador de saída
def __init__(self):
self._dados = {}
def salvar(self, pedido) -> None:
self._dados[pedido.id] = pedido
def buscar(self, pedido_id: str):
return self._dados.get(pedido_id)
Na composição, em um arquivo como bootstrap.py, a escolha da implementação acontece em uma única linha. Trocar a memória por um adaptador de banco muda só essa linha e o novo adaptador, nunca ConfirmarPedido:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchrepositorio = RepositorioEmMemoria()
confirmar = ConfirmarPedido(repositorio)
Uma estrutura de pastas possível
Pastas são uma representação possível, não uma exigência do padrão. O critério é proteger a direção das dependências, de modo que nada em domain ou application importe algo de adapters.
src/
app/
domain/ # entidades e regras puras
application/ # casos de uso e contratos (portas)
adapters/
inbound/ # HTTP, CLI, worker
outbound/ # banco, API externa, filesystem
bootstrap.py # composição das implementações
tests/
unit/
integration/
O tutorial AWS usa uma divisão própria, com domain, ports, adapters e entrypoints, e um exemplo orientado a Lambda. Ele indica Python 3.7 ou posterior e lista dependências do próprio exemplo, como CDK v2, Poetry 1.1.13, pytest 7.1.1, Moto 3.1.9, Pydantic 1.9.0 e Boto3 1.22.4. Essas são versões de uma época específica e não devem ser tomadas como versões atuais nem como requisitos universais; confirme a compatibilidade antes de reproduzir o tutorial. O próprio guia informa que o exemplo foi testado em ambiente de prova de conceito e que exige revisão de segurança antes de qualquer implantação produtiva.
Como testar um domínio sem banco de dados
Esse é o benefício mais concreto da separação. A AWS afirma que, como a lógica da aplicação não depende de fatores externos, o teste fica simplificado e dependências se tornam mais fáceis de substituir por mocks. Na prática, a estratégia costuma ser esta:
- Testes unitários do caso de uso: usam um repositório em memória ou um fake. Não há banco, rede nem variável de ambiente envolvidos, então rodam rapidamente e em qualquer máquina.
- Testes de contrato do adaptador: executam a mesma bateria de testes contra cada implementação da porta, incluindo a em memória e a real. Isso garante que as implementações se comportem da mesma forma.
- Testes de integração: entram quando o comportamento do sistema externo é parte da regra, como uma consulta com filtro específico ou uma transação. O tutorial AWS usa Moto para simular o DynamoDB nos testes do adaptador, o que dispensa uma conta real na nuvem para esse nível de teste.
Quando a arquitetura compensa e quando é excesso
A AWS considera o padrão especialmente adequado quando clientes diferentes compartilham a mesma lógica de domínio, quando há múltiplas entradas e saídas, ou quando a interface de usuário ou a tecnologia de persistência precisam mudar sem reescrever as regras. A mesma orientação ressalta que o código extra de adaptadores só se justifica quando essas variações existem ou são prováveis. Use a tabela abaixo como critério inicial.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →| Eixo | Pergunta a fazer | Sinal de que a abstração vale o custo |
|---|---|---|
| Entradas | Quantas formas de iniciar a operação existem? | Mais de uma entrada, como API e worker, usando o mesmo caso de uso |
| Saídas | Quantos destinos o núcleo precisa alcançar? | Banco, API externa ou fila com chance real de substituição |
| Volatilidade | Algum sistema externo deve mudar com o tempo? | Troca de fornecedor, de banco ou de protocolo prevista |
| Testes | A regra só pode ser verificada com infraestrutura real? | Regras complexas que se beneficiam de testes sem I/O |
| Custo | Quanto código de composição e tradução a equipe vai manter? | Custo aceitável frente aos ganhos de fronteira |
Uma aplicação pequena, com uma única interface e persistência estável, pode começar com uma estrutura menor. Não crie uma interface para cada função. Crie uma porta quando houver uma dependência externa ou uma fronteira de substituição ou teste que de fato beneficie o sistema.
Best Value
O custo tem características conhecidas. A AWS alerta para complexidade, manutenção e possível latência adicional causada pela camada extra. Um exemplo em Python também aponta a repetição de operações CRUD em cada porta e o crescimento do ponto de composição à medida que o sistema cresce. Esses efeitos aparecem com frequência em projetos médios e grandes, e merecem ser planejados desde o início.
Evidência e limites do que se pode afirmar
As fontes consultadas para este texto são de orientação e de exemplo, e não trazem medições públicas de produtividade, qualidade de código ou custo atribuídas ao padrão. Por isso, o argumento aqui é de design e de custo de mudança, não de ganho numérico. Os exemplos de tecnologia, como versões de bibliotecas e serviços em nuvem, descrevem um momento específico e devem ser revalidados antes de uso.
Leituras complementares
- Guia de orientação prescritiva da AWS sobre arquitetura hexagonal, com introdução conceitual e comparação com a arquitetura em camadas.
- Tutorial AWS de exemplo completo com Lambda, API Gateway e DynamoDB. Trate-o como estudo de caso específico, e não como arquitetura obrigatória para todo serviço Python.
- Architecture Patterns with Python, uma leitura complementar sobre esses mesmos princípios aplicados a Python.
A ideia central é simples de enunciar e exige disciplina para aplicar: o domínio define o que precisa, a borda decide como isso é feito, e a composição é o único lugar onde essas escolhas se encontram.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




