Pular para o conteúdo

Gateway

“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.

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ê.

  • 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.
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.

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.
public interface PagamentoGateway {
ResultadoCobranca cobrar(BigDecimal valor, String token);
}
@Component
public 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.

  • Vazar a API externa na interface: expor StripeChargeResponse para 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).

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.