Use Cases
O interactor
Seção intitulada “O interactor”Um interactor é a implementação concreta de um caso de uso. Ele contém as Application Business Rules: a sequência de passos necessária para cumprir um objetivo do usuário (ex.: criar pedido, transferir valor). Ele não sabe de HTTP, de SQL nem de JSON — só coordena Entities e portas.
Regra de ouro: um interactor por caso de uso mantém a OCP — adicionar um novo caso de uso é adicionar uma classe, não editar uma existente.
Boundaries: input port e output port
Seção intitulada “Boundaries: input port e output port”As fronteiras do caso de uso são interfaces definidas dentro do próprio anel de use cases, o que permite a inversão da A Regra da Dependência.
- Input port (input boundary): a interface que o mundo externo chama para acionar o caso de uso. O controller depende dela; o interactor a implementa.
- Output port (output boundary): a interface que o interactor chama para entregar o resultado. O interactor depende dela; o presenter a implementa.
graph LR
C["Controller<br/>(Interface Adapter)"] -->|chama| IP["InputPort<br/>(interface, núcleo)"]
IP -. implementado por .- I["Interactor<br/>(Use Case)"]
I -->|chama| OP["OutputPort<br/>(interface, núcleo)"]
OP -. implementado por .- P["Presenter<br/>(Interface Adapter)"]
Observe que as duas setas de dependência de código apontam para dentro (para as interfaces do núcleo), mesmo que o fluxo de controle atravesse controller → interactor → presenter.
Request e response models
Seção intitulada “Request e response models”Os dados que cruzam as boundaries são estruturas simples e desacopladas:
- Request model: DTO de entrada montado pelo controller e recebido pelo input port. Não é o
@RequestBody; não é a Entity. - Response model: DTO de saída produzido pelo interactor e entregue ao output port. Não é a Entity; não é
ResponseEntity.
Isso mantém a Entity protegida e evita que a forma de UI ou de persistência contamine o núcleo (ver DTOs cruzando fronteiras em A Regra da Dependência).
O presenter
Seção intitulada “O presenter”O presenter vive no anel de Interface Adapters e implementa o output port. Ele recebe o response model e o transforma no view model — a forma exata que a tela ou a resposta HTTP precisa (strings formatadas, datas locais, flags de exibição). A vantagem do presenter sobre um simples return é permitir que o interactor não dependa da forma de apresentação; a lógica de formatação fica testável e fora do núcleo.
Em muitos projetos Spring pragmáticos, o output port é simplificado para um valor de retorno do interactor e um mapper no controller. A forma canônica com presenter separado é preferível quando a apresentação tem lógica própria ou múltiplas saídas (web, CLI, relatório).
Relação com a Hexagonal
Seção intitulada “Relação com a Hexagonal”Os casos de uso da Clean são exatamente os casos de uso expostos pelas driving Ports da Arquitetura Hexagonal:
- Input port da Clean = driving port (porta de entrada) hexagonal.
- Output port / gateway da Clean = driven port (porta de saída) hexagonal.
- O interactor é o núcleo aplicacional que a Hexagonal esconde atrás das portas.
Ver Driving e Driven para a simetria e Comparação - Hexagonal vs Clean vs Camadas para o mapeamento completo.
Exemplo de assinatura
Seção intitulada “Exemplo de assinatura”public interface CriarPedidoInputPort { void executar(CriarPedidoRequest request);}
public interface CriarPedidoOutputPort { void apresentar(PedidoResponse response);}
public record CriarPedidoRequest(String clienteId, List<ItemRequest> itens) {}
public record ItemRequest(String produtoId, int quantidade, BigDecimal precoUnitario) {}
public record PedidoResponse(String pedidoId, String status, BigDecimal total) {}O interactor completo, com gateway e Entity, aparece em Exemplo Clean com Spring.
Anti-padrões e erros comuns
Seção intitulada “Anti-padrões e erros comuns”- Interactor que retorna
ResponseEntityou fala JSON: o caso de uso sabendo de web. - God interactor: uma classe orquestrando vários casos de uso, ferindo SRP e OCP.
- Request model = Entity: reaproveitar a Entity como DTO de entrada, acoplando a API ao domínio.
- Regra de negócio no interactor que deveria estar na Entity: o interactor orquestra; a regra corporativa é da Entity.
- Output port ignorado: interactor com dependência direta do presenter concreto em vez da interface, quebrando a inversão.
Relações
Seção intitulada “Relações”- Fronteiras e inversão: A Regra da Dependência, DIP, OCP.
- Onde os use cases moram: Camadas da Clean Architecture.
- Origem hexagonal: Arquitetura Hexagonal, Ports, Adapters, Driving e Driven.
- Núcleo que os interactors orquestram: Entidades, Value Objects, Repositórios, Domain-Driven Design.
- O mesmo papel no vocabulário DDD: Application Services.
- Implementação: Exemplo Clean com Spring.
- Índice: Clean Architecture, Comparação - Hexagonal vs Clean vs Camadas, Home.
Perguntas de revisão
Seção intitulada “Perguntas de revisão”1. Quem implementa o input port e quem depende dele?
Resposta
O interactor implementa o input port; o controller depende dele. Como a interface está no núcleo, a dependência do controller aponta para dentro.
2. Qual a diferença entre request model e a Entity?
Resposta
O request model é um DTO simples de transporte, na forma conveniente ao caso de uso, sem comportamento de negócio. A Entity carrega regras de negócio corporativas. Nunca se usa a Entity como DTO de fronteira.
3. Para que serve o presenter em vez de um simples return?
Resposta
Para desacoplar a formatação de apresentação do interactor. O presenter (anel de adapters) implementa o output port e produz o view model, mantendo o núcleo independente da forma de exibição e permitindo múltiplas saídas.
4. Como um caso de uso da Clean se mapeia na Hexagonal?
Resposta
O input port equivale a uma driving port (entrada) e o output port/gateway a uma driven port (saída). O interactor é o serviço de aplicação escondido atrás dessas portas.