Quando il provider cambia nome
sendinblue/api-v3-sdk e diventato getbrevo/brevo-php. Non un aggiornamento: un rebranding. Il namespace e passato da SendinBlue\Client a Brevo\Client. Senza un adapter, ogni punto del codice che usava l'SDK avrebbe dovuto cambiare — e in un'applicazione reale, quei punti possono essere decine. Un rebranding del vendor non dovrebbe mai causare un refactoring nel codice applicativo. Se lo causa, manca un livello di astrazione.
L'Adapter Pattern wrappa l'interfaccia di un componente esterno in un'interfaccia che il nostro codice conosce. MailService espone send() con i nostri tipi — MailMessage, MailRecipient — e traduce internamente verso l'SDK di Brevo. Il codice applicativo chiama MailService::make()->send($message) e non sa se sotto c'e Brevo, SendGrid, Mailgun o un file di log. L'adapter e il confine tra il nostro dominio e il mondo esterno.
Cos'e l'Adapter Pattern: definizione e varianti
Il Gang of Four definisce l'Adapter come un pattern strutturale che "converte l'interfaccia di una classe in un'altra interfaccia che il client si aspetta. L'Adapter permette a classi con interfacce incompatibili di collaborare". Esistono due varianti classiche: l'Object Adapter (usa la composizione, wrappando l'oggetto adattato) e il Class Adapter (usa l'ereditarieta multipla, non disponibile in PHP).
In PHP, la variante naturale e l'Object Adapter: la classe adapter ha una proprieta privata che contiene l'oggetto adattato, e i metodi dell'adapter delegano all'oggetto adattato dopo aver tradotto i parametri e i valori di ritorno. Il MailService di Soft PHP MVC e un Object Adapter puro: mantiene un'istanza del client Brevo come dipendenza interna e traduce ogni chiamata dal vocabolario del framework al vocabolario dell'SDK.
La struttura del MailService come adapter
Il MailService nel framework separa tre responsabilita:
- Interfaccia pubblica — metodi come
send(),sendTemplate()con tipi del framework (MailMessage,MailRecipient) - Traduzione — conversione da
MailRecipientaBrevo\Client\Model\SendSmtpEmailTo, daMailMessagealla struttura richiesta dall'API - Comunicazione — la chiamata effettiva all'SDK di Brevo con error handling specifico del provider
Questa separazione permette di cambiare il provider senza toccare ne l'interfaccia pubblica ne il codice applicativo — si riscrive solo la traduzione e la comunicazione.
Il valore dell'Adapter si misura al momento del cambiamento
Il valore dell'Adapter non e immediatamente visibile — si manifesta quando qualcosa cambia. Quando SendinBlue e diventato Brevo, l'unico file da toccare e stato l'adapter. Nessun controller modificato, nessun service riscritto, nessun test aggiornato (a parte quello dell'adapter stesso). Il resto del codice ha continuato a funzionare come se nulla fosse accaduto — perche per il codice applicativo, nulla e accaduto.
Questa protezione dal cambiamento ha un nome nel mondo dei design pattern: Information Hiding. L'adapter nasconde l'identita del provider dietro un'interfaccia stabile. Domani Brevo potrebbe cambiare di nuovo nome, cambiare la versione dell'API, o essere sostituito interamente da un altro servizio. L'adapter assorbe il cambiamento, e il codice applicativo resta intatto. E il ritorno sull'investimento di un'astrazione ben posizionata.
Adapter e altri pattern: collaborazioni naturali
L'Adapter collabora naturalmente con altri pattern. Con lo Strategy: se hai piu provider email (Brevo per la produzione, un logger per lo sviluppo), ogni adapter diventa una strategia intercambiabile. Con il Factory Method: MailService::make() decide quale adapter istanziare in base alla configurazione. Con il Facade: il MailService semplifica un'API complessa (l'SDK di Brevo ha decine di metodi) in un'interfaccia minimale con solo i metodi che il framework usa davvero.
Questa composizione di pattern non e accidentale — e il risultato di una progettazione guidata dai principi SOLID. L'adapter rispetta il Single Responsibility (traduce, non fa logica di business), l'Open/Closed (nuovo provider = nuovo adapter, zero modifiche altrove), il Dependency Inversion (il codice applicativo dipende dall'astrazione MailService, non dal concreto Brevo). I pattern e i principi si rinforzano a vicenda.
Quando usare l'Adapter Pattern
L'Adapter e la scelta giusta in questi scenari:
- Integrazione con SDK di terze parti — API di pagamento, mail, storage cloud, social login
- Legacy code — wrappare codice vecchio con un'interfaccia moderna senza riscriverlo
- Cambio di provider — quando prevedi (o vuoi prepararti per) il cambio di un servizio esterno
- Testing — sostituire l'adapter reale con uno che scrive su file o su array in memoria
Non usare l'Adapter quando l'integrazione e banale e il provider non cambiera mai (raro, ma possibile). L'overhead di un adapter inutile e minimo ma reale — una classe in piu da mantenere, un livello di indirezione in piu da navigare nel debugging. Come sempre, il pragmatismo guida la scelta: se il costo dell'adapter e inferiore al costo di un futuro cambio di provider, l'adapter si ripaga.