Il problema: troppi oggetti per fare una cosa semplice
Per inviare un'email di conferma ordine servono sei passaggi: creare il template engine, caricare il template, renderizzare con i dati dell'ordine, creare il transport SMTP, configurare le credenziali, costruire il messaggio con mittente, destinatario, oggetto e corpo, e infine inviare. Sei oggetti, dodici metodi, venti righe di codice. Ogni controller che deve inviare un'email ripete lo stesso boilerplate, o copia-incolla da un controller precedente.
Il Facade Pattern propone di creare un'interfaccia semplificata che nasconde questa complessita. Invece di sei oggetti e dodici metodi, il controller chiama Mailer::send('order-confirmation', $order, $customer->email). Una riga. La Facade si occupa di orchestrare i sei oggetti sotto il cofano.
Cos'e il Facade Pattern: definizione formale
Il Gang of Four definisce il Facade come un pattern strutturale che "fornisce un'interfaccia unificata a un insieme di interfacce in un sottosistema. La Facade definisce un'interfaccia di livello superiore che rende il sottosistema piu facile da usare". Non nasconde il sottosistema — lo rende accessibile a chi non ha bisogno di conoscerne i dettagli.
La struttura e semplice: una classe Facade che conosce quali classi del sottosistema sono responsabili di ogni richiesta, e delega le chiamate del client alle classi appropriate. Il sottosistema non sa dell'esistenza della Facade — le sue classi sono autonome e possono essere usate direttamente quando serve un controllo fine.
Esempio teorico: un sottosistema di reportistica
Immagina un sistema di generazione report con diverse componenti:
DataExtractor: esegue query sul database e restituisce dati grezziDataTransformer: aggrega, filtra e formatta i dati per il reportChartGenerator: genera grafici SVG dai dati trasformatiPdfRenderer: combina testo e grafici in un documento PDFFileStorage: salva il PDF generato nel filesystem o nel cloudNotificationService: notifica l'utente che il report e pronto
Senza Facade, il controller deve orchestrare tutti questi oggetti manualmente: estrarre i dati, trasformarli, generare i grafici, renderizzare il PDF, salvarlo e notificare l'utente. Sei dipendenze nel controller, sei passaggi da coordinare, sei punti dove qualcosa puo andare storto.
La Facade ReportFacade espone un metodo: generate(string $type, array $params, int $userId): string. Internamente orchestra tutti e sei i passaggi e restituisce il path del report generato. Il controller ha una sola dipendenza e una sola riga di codice.
La Facade non imprigiona
Un malinteso comune e che la Facade impedisca l'accesso diretto al sottosistema. Non e cosi: la Facade e un in piu, non un invece di. Se un caso d'uso specifico richiede il controllo fine sul ChartGenerator — ad esempio per generare un grafico senza il PDF — il codice puo usare direttamente ChartGenerator senza passare dalla Facade. La Facade semplifica il caso comune, non limita i casi speciali.
Esempio teorico: Facade per l'autenticazione
L'autenticazione coinvolge molti componenti: verifica credenziali, hashing password, gestione sessione, generazione token, verifica 2FA, logging dei tentativi. Una AuthFacade espone:
attempt(string $email, string $password): bool— verifica credenziali, logga il tentativo, avvia la sessioneverify2FA(string $code): bool— verifica il codice TOTP e completa l'autenticazionelogout(): void— invalida sessione e tokencheck(): bool— verifica se l'utente e autenticato
Ogni metodo della Facade coordina 3-4 componenti interni. Il middleware di autenticazione chiama AuthFacade::check() senza sapere che sotto il cofano vengono verificati sessione, token JWT e timestamp di scadenza.
Facade vs Service: la differenza
La distinzione tra Facade e Service e sottile ma importante:
- Facade: semplifica l'accesso a un sottosistema esistente. Non aggiunge logica di business: orchestra componenti gia esistenti. Se rimuovi la Facade, le classi del sottosistema funzionano ancora.
- Service: contiene logica di business propria. Puo usare componenti del sottosistema, ma aggiunge regole, validazioni e decisioni che non esistono altrove.
Se il metodo della tua "Facade" contiene 50 righe di logica di business con condizioni e calcoli, probabilmente e un Service, non una Facade. Se orchestra 6 chiamate a componenti diversi senza aggiungere logica, e una Facade pura.
Facade in Laravel e il malinteso
Le Facade di Laravel (Cache::get(), DB::table(), Auth::check()) non sono il Facade Pattern del Gang of Four. Sono static proxy: classi che risolvono un service dal container e delegano la chiamata statica a un'istanza. La confusione di nomenclatura e storica, ma e importante capire la differenza: il Facade Pattern originale crea un'interfaccia semplificata per un sottosistema complesso. Le "Facade" di Laravel sono un meccanismo di risoluzione dal container con sintassi statica.
Quando usare il Facade Pattern
- Usa la Facade quando un sottosistema ha molte classi e il caso d'uso comune richiede di coordinarle sempre nello stesso modo
- Usa la Facade quando vuoi ridurre le dipendenze del codice client: una Facade al posto di sei classi
- Usa la Facade quando vuoi creare un punto di ingresso chiaro per un modulo o package
- Non usare la Facade per nascondere un cattivo design: se il sottosistema e confuso, semplificarlo con una Facade non risolve il problema strutturale
- Non usare la Facade se il sottosistema ha una sola classe: stai aggiungendo un layer di indirezione senza beneficio
Il Facade Pattern e il pattern della cortesia: rende un sistema complesso accessibile senza semplificarlo oltre misura. Non elimina la complessita — la nasconde dietro un'interfaccia pulita per chi non ha bisogno di vederla, e la lascia accessibile per chi ne ha bisogno.