Gateway
Definição (Fowler)
Seção intitulada “Definição (Fowler)”“An object that encapsulates access to an external system or resource.”
O Gateway traduz entre a API “estranha” do recurso externo e uma interface conveniente e estável para a aplicação. Ele esconde os detalhes de protocolo, serialização e conexão.
Problema que resolve
Seção intitulada “Problema que resolve”Recursos externos têm APIs próprias, verbosas e instáveis. Consumi-las diretamente espalha esse acoplamento pela aplicação. O Gateway concentra a tradução num único ponto: se o recurso muda, só o Gateway muda; e em testes, ele pode ser substituído por um dublê.
Quando usar
Seção intitulada “Quando usar”- Integração com APIs REST/SOAP, filas/tópicos de mensageria, cache, sistemas legados.
- Acesso a dados de baixo nível por tabela (variantes abaixo).
- Sempre que quiser uma fronteira testável entre sua aplicação e o mundo externo.
Trade-offs
Seção intitulada “Trade-offs”| Vantagem | Custo |
|---|---|
| Isola o acoplamento externo | Uma camada de indireção |
| Interface no vocabulário da app | Pode virar mero repasse fino |
| Facilita testes com dublês | Risco de vazar a API externa na interface |
Ponto-chave: Gateway como driven port / adapter secundário
Seção intitulada “Ponto-chave: Gateway como driven port / adapter secundário”Na Arquitetura Hexagonal, a aplicação define uma porta (Ports) — uma interface no seu próprio vocabulário — e o Gateway é o adapter (Adapters) que a implementa contra a tecnologia concreta. Por ser dirigido pela aplicação (a aplicação chama o recurso), é um port/adapter secundário (driven). Ver Driving e Driven.
graph LR
App[Aplicação / Service Layer] -->|depende da porta| Port[[interface PagamentoPort]]
Port -.implementada por.-> GW[StripePagamentoGateway]
GW --> Ext[(API externa Stripe)]
Assim, o DIP - Dependency Inversion Principle é respeitado: a aplicação depende da abstração (port), e o detalhe (Gateway) depende da abstração.
Row Data Gateway vs Table Data Gateway
Seção intitulada “Row Data Gateway vs Table Data Gateway”Fowler descreve duas variantes para acesso a dados:
- Row Data Gateway — uma instância por linha da tabela; expõe os campos como propriedades e métodos de acesso. Um objeto = um registro.
- Table Data Gateway — uma instância para a tabela inteira; métodos recebem/retornam conjuntos (ex.:
findById,findAll), sem estado por linha. É o parente próximo do DAO - Data Access Object.
Exemplo Java/Spring
Seção intitulada “Exemplo Java/Spring”public interface PagamentoGateway { ResultadoCobranca cobrar(BigDecimal valor, String token);}@Componentpublic class StripePagamentoGateway implements PagamentoGateway {
private final RestClient client;
public StripePagamentoGateway(RestClient.Builder builder, @Value("${stripe.base-url}") String baseUrl, @Value("${stripe.api-key}") String apiKey) { this.client = builder .baseUrl(baseUrl) .defaultHeader("Authorization", "Bearer " + apiKey) .build(); }
@Override public ResultadoCobranca cobrar(BigDecimal valor, String token) { StripeChargeRequest body = new StripeChargeRequest( valor.movePointRight(2).longValueExact(), "brl", token);
StripeChargeResponse resp = client.post() .uri("/v1/charges") .body(body) .retrieve() .body(StripeChargeResponse.class);
if (resp == null || !"succeeded".equals(resp.status())) { return ResultadoCobranca.recusada(); } return ResultadoCobranca.aprovada(resp.id()); }
private record StripeChargeRequest(long amount, String currency, String source) {} private record StripeChargeResponse(String id, String status) {}}A aplicação depende só de PagamentoGateway (a porta), no vocabulário do domínio (cobrar, ResultadoCobranca). Detalhes da Stripe (centavos, source, status) ficam contidos no adapter.
Anti-padrões e erros comuns
Seção intitulada “Anti-padrões e erros comuns”- Vazar a API externa na interface: expor
StripeChargeResponsepara os clientes anula o isolamento. - Gateway anêmico repasse: se a interface espelha 1:1 a API externa, não houve tradução para o vocabulário da aplicação.
- Sem tratamento de falhas: recursos externos falham; faltam timeout, retry, circuit breaker.
- Lógica de domínio no Gateway: o Gateway integra; regra pertence ao Domain Model.
- Acoplar a aplicação à implementação concreta em vez de à porta (fere o DIP - Dependency Inversion Principle).
Relações
Seção intitulada “Relações”- É o conceito por trás de adapter secundário / driven port na Arquitetura Hexagonal (ver Driving e Driven).
- Respeita o DIP - Dependency Inversion Principle e o OCP - Open-Closed Principle.
- Table Data Gateway é parente do DAO - Data Access Object.
- Consumido pelo Service Layer.
- Índice: PoEAA.
Perguntas de revisão
Seção intitulada “Perguntas de revisão”1. Qual a intenção do Gateway?
Resposta
Encapsular o acesso a um sistema/recurso externo por trás de uma interface simples no vocabulário da aplicação, isolando protocolo, serialização e conexão.
2. Como o Gateway se relaciona com Ports & Adapters?
Resposta
Ele é o adapter secundário que implementa um driven port (interface definida pela aplicação). A aplicação depende da porta; o Gateway depende dessa abstração, cumprindo o DIP.
3. Qual a diferença entre Row Data Gateway e Table Data Gateway?
Resposta
O Row Data Gateway tem uma instância por linha (objeto = registro); o Table Data Gateway tem uma instância para a tabela inteira, com métodos que operam sobre conjuntos — próximo de um DAO.
4. Que sinal indica um Gateway mal projetado?
Resposta
Quando ele vaza a API externa (tipos/DTOs do fornecedor) para os clientes ou espelha 1:1 a API, sem traduzir para o vocabulário da aplicação — perdendo o isolamento.