Design Patterns: Facade (Parte 6)

·3 min de leitura

Contexto

Na Parte 5 falamos de State. Agora voltamos a um padrão estrutural que aparece muito em código de aplicação: Facade. A dor que ele resolve é mais “humana” do que acadêmica: quando um subsistema cresce, consumir esse subsistema passa a exigir que você saiba demais (ordem das chamadas, detalhes, dependências indiretas). O Facade cria um ponto de entrada mais simples.

A intenção é esconder a complexidade de um subsistema atrás de uma interface amigável. Isso não elimina a complexidade; ele só organiza o acesso. Em vez de dez classes e vinte métodos “espalhados” pela base chamando serviços em ordens diferentes, você concentra um fluxo típico num lugar só, com um nome que faz sentido para quem lê.

É útil também não confundir com Adapter. Adapter existe para compatibilizar interfaces incompatíveis. Facade existe para reduzir o número de pontos de contato com um subsistema e oferecer uma API mais simples para consumo.

Exemplo na prática

Imagine um fluxo de checkout que, internamente, fala com estoque, pagamento e notificação:

<?php

final readonly class InventoryService
{
    public function reserve(string $sku, int $qty): void
    {
        // ...
    }
}

final readonly class PaymentGateway
{
    public function charge(int $amountCents, string $token): string
    {
        // ...
        return 'ch_123';
    }
}

final readonly class Mailer
{
    public function sendReceipt(string $email, string $chargeId): void
    {
        // ...
    }
}

final readonly class CheckoutFacade
{
    public function __construct(
        private InventoryService $inventory,
        private PaymentGateway $payments,
        private Mailer $mailer,
    ) {}

    public function placeOrder(string $sku, int $qty, int $amountCents, string $token, string $email): string
    {
        $this->inventory->reserve($sku, $qty);
        $chargeId = $this->payments->charge($amountCents, $token);
        $this->mailer->sendReceipt($email, $chargeId);

        return $chargeId;
    }
}

Repare no papel do CheckoutFacade: ele não tenta “virar o sistema todo”. Ele só dá um caminho de uso comum com um nome claro (placeOrder) e orquestra a sequência. Cada serviço (InventoryService, PaymentGateway, Mailer) continua coeso no próprio papel, enquanto o restante da aplicação para de depender da ordem exata e dos detalhes dessas chamadas. Em sistemas reais, você ainda vai pensar em transação, compensação, idempotência e afins (saga/outbox etc.), mas a ideia do Facade permanece: reduzir atrito de consumo.

O risco do Facade “gordo”

O cuidado aqui é o Facade virar um God Object: o lugar onde tudo acontece e onde regras de negócio de tudo se acumulam. Um bom Facade costuma ser “fino”: ele coordena, mas não tenta absorver responsabilidade que pertence ao domínio ou aos serviços especializados. Se o Facade começa a ter decisões complexas e regras centrais, pode ser sinal de que você está misturando orquestração com modelagem.

Conclusão

Facade melhora ergonomia e reduz barreira cognitiva para consumir subsistemas. Use quando muitas classes precisam ser usadas juntas de forma repetida.

Referências

  • Design Patterns (GoF).