Pular para o conteúdo

Facade

Fornecer uma interface unificada para um conjunto de interfaces de um subsistema. O Facade define uma interface de mais alto nível que torna o subsistema mais fácil de usar.

Um subsistema (ex: processar um pedido) costuma envolver várias classes colaborando: validação de estoque, cobrança, emissão de nota, notificação. Se cada cliente precisa orquestrar todas essas peças na ordem certa, o conhecimento da orquestração vaza para fora e o acoplamento explode: qualquer mudança interna quebra todos os chamadores.

O Facade concentra essa orquestração em um único ponto de entrada. O cliente chama um método de alto nível; a fachada coordena as classes internas.

public class Checkout {
public void finalizar(String cliente, String produto, int qtd) {
Estoque estoque = new Estoque();
if (!estoque.disponivel(produto, qtd)) {
throw new IllegalStateException("Sem estoque");
}
Pagamento pagamento = new Pagamento();
String transacao = pagamento.cobrar(cliente, produto, qtd);
estoque.reservar(produto, qtd);
NotaFiscal nf = new NotaFiscal();
String nota = nf.emitir(cliente, produto, qtd, transacao);
Notificador notificador = new Notificador();
notificador.enviar(cliente, "Pedido confirmado: " + nota);
}
}

Toda tela ou API que finaliza um pedido reescreveria essa sequência, ficando acoplada a Estoque, Pagamento, NotaFiscal e Notificador — e à ordem correta entre elas.

public class Estoque {
public boolean disponivel(String produto, int qtd) { return qtd <= 10; }
public void reservar(String produto, int qtd) {
System.out.println("Reservado " + qtd + "x " + produto);
}
}
public class Pagamento {
public String cobrar(String cliente, String produto, int qtd) {
System.out.println("Cobrando " + cliente);
return "TX-" + System.nanoTime();
}
}
public class NotaFiscal {
public String emitir(String cliente, String produto, int qtd, String transacao) {
return "NF-" + transacao;
}
}
public class Notificador {
public void enviar(String cliente, String msg) {
System.out.println("Para " + cliente + ": " + msg);
}
}

A fachada:

public class PedidoFacade {
private final Estoque estoque;
private final Pagamento pagamento;
private final NotaFiscal notaFiscal;
private final Notificador notificador;
public PedidoFacade(Estoque estoque, Pagamento pagamento,
NotaFiscal notaFiscal, Notificador notificador) {
this.estoque = estoque;
this.pagamento = pagamento;
this.notaFiscal = notaFiscal;
this.notificador = notificador;
}
public String finalizarPedido(String cliente, String produto, int qtd) {
if (!estoque.disponivel(produto, qtd)) {
throw new IllegalStateException("Sem estoque para " + produto);
}
String transacao = pagamento.cobrar(cliente, produto, qtd);
estoque.reservar(produto, qtd);
String nota = notaFiscal.emitir(cliente, produto, qtd, transacao);
notificador.enviar(cliente, "Pedido confirmado. Nota: " + nota);
return nota;
}
}

Uso:

var facade = new PedidoFacade(new Estoque(), new Pagamento(),
new NotaFiscal(), new Notificador());
String nota = facade.finalizarPedido("Ana", "Teclado", 2);

O cliente depende de um único método coeso. O subsistema pode ser reorganizado por dentro sem afetar quem consome a fachada.

classDiagram
    class Cliente
    class PedidoFacade {
        +finalizarPedido(cliente, produto, qtd) String
    }
    class Estoque
    class Pagamento
    class NotaFiscal
    class Notificador
    Cliente --> PedidoFacade : ponto de entrada único
    PedidoFacade --> Estoque
    PedidoFacade --> Pagamento
    PedidoFacade --> NotaFiscal
    PedidoFacade --> Notificador

Facade, Use Cases e a “fachada de aplicação”

Seção intitulada “Facade, Use Cases e a “fachada de aplicação””

A ideia de fachada aparece em escalas maiores. Uma fachada de aplicação (application facade / service layer) é um objeto que expõe as operações de negócio de alto nível de um sistema, escondendo a colaboração interna entre serviços de domínio, repositórios e infraestrutura.

Isso se relaciona diretamente com Use Cases: um caso de uso da Clean Architecture é, em essência, uma fachada de granularidade fina — um ponto de entrada por operação de negócio (“Finalizar Pedido”, “Cancelar Assinatura”) que orquestra entidades e serviços. Onde o Facade do GoF é um padrão tático para embrulhar um subsistema técnico, o Use Case é a materialização arquitetural dessa mesma intenção de simplificação, com o benefício adicional de expressar a intenção do domínio.

Facade e Port podem parecer semelhantes — ambos são interfaces de alto nível — mas resolvem problemas distintos:

Aspecto Facade Port (Hexagonal)
Natureza Padrão de design; geralmente uma classe concreta que simplifica um subsistema Elemento arquitetural; uma interface (contrato) na fronteira do núcleo
Direção da dependência O cliente depende da fachada, que depende do subsistema (mesma direção) Inverte a dependência: a infraestrutura implementa o port definido pelo núcleo
Objetivo Reduzir complexidade/acoplamento de uso Isolar o núcleo de tecnologia e satisfazer a regra de dependência
Substituibilidade Não visa necessariamente múltiplas implementações Existe justamente para permitir múltiplos Adapters

Em resumo: uma fachada simplifica; um port inverte a dependência e define uma fronteira. Um Use Case pode ser modelado como uma fachada que também atua como driving port da aplicação — daí a confusão frequente entre os conceitos.

  • A favor: desacopla clientes do subsistema, oferece um ponto de entrada legível, facilita evolução interna, encapsula a ordem de orquestração.
  • Contra: a fachada pode virar um ponto de acoplamento central; se acumular lógica de negócio própria, degenera em God Object. O Facade não deve impedir o acesso direto ao subsistema quando necessário — ele adiciona conveniência, não uma barreira imposta.
  • Facade God Object: a fachada acumula regras de negócio em vez de apenas coordenar/delegar, tornando-se um monólito de responsabilidades.
  • Fachada que só repassa (pass-through): se cada método apenas chama um único método do subsistema sem coordenação real, a fachada é indireção inútil.
  • Confundir Facade com Port: tratar uma fachada concreta como se ela invertesse a dependência arquitetural (ver tabela acima).
  • Fachada que bloqueia acesso legítimo ao subsistema: o padrão simplifica o caso comum; forçar tudo por ela quando um cliente precisa de controle fino é rigidez desnecessária.

1. Qual é a intenção do Facade e o que ele reduz?

Resposta

Fornecer uma interface unificada de mais alto nível para um subsistema de muitas classes, reduzindo o acoplamento entre clientes e detalhes internos e encapsulando a ordem de orquestração. Ele simplifica o uso comum, mas não impede o acesso direto ao subsistema quando necessário.

2. Como Facade se relaciona com Use Cases da Clean Architecture?

Resposta

Um Use Case é, em essência, uma fachada de granularidade fina: um ponto de entrada por operação de negócio que orquestra entidades e serviços internos. É a materialização arquitetural da mesma intenção de simplificação do Facade, expressando adicionalmente a intenção do domínio. Ver Use Cases.

3. Qual a diferença essencial entre Facade e Port?

Resposta

Facade é um padrão de design, tipicamente uma classe concreta que simplifica um subsistema — o cliente e a fachada dependem do subsistema na mesma direção. Port é um contrato (interface) na fronteira do núcleo que inverte a dependência, permitindo múltiplos Adapters. Facade simplifica; Port define fronteira e inverte dependência.

4. Como uma fachada degenera em anti-padrão?

Resposta

Quando acumula lógica de negócio própria em vez de apenas coordenar e delegar, virando um God Object; quando só repassa chamadas 1-para-1 sem coordenação real (indireção inútil); ou quando bloqueia o acesso legítimo ao subsistema, transformando conveniência em rigidez.