Per un viaggio non si rifanno le prese di casa

  • software
  • metodo

Quando ti serve un phon, lo compri e basta. Non ti chiedi se la spina entrerà nelle prese inglesi: lo userai a casa e a casa la spina entra. Ha senso così. Prepararsi per un viaggio che non farai è solo fatica sprecata.

Se invece un viaggio in Inghilterra lo metti in conto, ti serve qualcosa che faccia funzionare il tuo phon anche con un’altra presa. Lo stesso vale per l’Asia o per l’America: ovunque tu vada, ti serve un adattatore. È uno strato tra il phon e la presa che ti lascia fare le tue cose senza preoccuparti di come arriva la corrente.

Nel software funziona allo stesso modo. Un programma raramente vive isolato. Parla con il catalogo di un fornitore, con un servizio di pagamento, con il gestionale di un’altra azienda. Ognuno di questi sistemi ha le sue “prese”: i suoi nomi, i suoi formati, le sue regole.

La tentazione immediata è usare quello che ci mandano così come arriva, ovunque nel nostro codice. Finché la presa è una sola e non cambia, va bene. Quando le prese diventano più di una, o cominciano a cambiare, serve l’adattatore.

Nel pezzo sul meccanico ho scritto come si decide cosa entra nel dominio. Qui la domanda è un’altra: cosa succede quando è quello che sta fuori a cambiare?

Il conto arriva al primo viaggio

Usare quello che arriva così com’è, all’inizio, è la scelta più comoda. Il sistema esterno ci consegna i suoi dati già pronti e tradurli sembra lavoro sprecato: perché inventare nomi nostri per concetti che un nome ce l’hanno già?

Il conto, però, arriva al primo viaggio. In Inghilterra il phon non entra nella presa. Nemmeno il caricabatterie del telefono, nemmeno il rasoio. Senza adattatore resta solo cambiare la spina a ognuno, oppure ricomprarli. Al viaggio successivo, negli Stati Uniti, si ricomincia da capo. Funzionava tutto finché la presa era una sola.

Nel software non siamo noi a cambiare paese: è il paese che cambia attorno a noi, senza preavviso. Il fornitore rinumera il catalogo, il servizio di pagamento rilascia una nuova versione, un campo cambia nome. Se i loro nomi e i loro formati sono sparsi in tutto il nostro codice, ogni loro modifica diventa una modifica nostra, in cento posti diversi. E non decidiamo noi quando farla: lo decide qualcun altro, con i suoi tempi.

Cambiare tutte le spine a ogni viaggio costa così tanto che a un certo punto si smette e ci si arrangia. Al phon si attaccano due spine sullo stesso filo, quella inglese e quella americana. Prima di usarlo bisogna ricordarsi quale delle due serve. Lo stesso per il caricabatterie e per il rasoio. Al terzo viaggio le spine diventano tre.

Nel codice l’arrangiarsi ha una forma precisa: la condizione, l’if. Se il dato arriva dalla versione vecchia fai così, se arriva da quella nuova fai cosà. Ogni if da solo sembra innocuo e risparmia la fatica di rifare tutto da capo. Dopo qualche cambiamento, però, ogni parte del programma deve sapere con quale versione sta parlando. Le condizioni si moltiplicano, si annidano una dentro l’altra e il codice diventa sempre più difficile da leggere. Ancora di più da cambiare.

È questo il punto. Se ci portiamo dentro le cose di fuori, ci portiamo dentro anche tutti i loro cambiamenti.

Con l’adattatore va diversamente. Cambi paese e cambi adattatore; la casa non se ne accorge. Il punto in cui il mondo esterno incontra il nostro è uno solo: quando fuori cambia qualcosa, si interviene esclusivamente lì.

Due riquadri. Senza adattatore: phon, telefono e rasoio hanno ognuno la spina inglese, tre spine da cambiare. Con l’adattatore: gli stessi apparecchi tengono la spina di casa, vanno in una ciabatta e un solo adattatore la collega alla presa inglese.

La presa di casa la scegliamo noi

L’adattatore funziona perché ha due facce. Da una parte entra nella presa del paese in cui sei. Dall’altra offre la presa di casa, la stessa forma che il phon conosce da sempre. Il phon non sa niente dell’Inghilterra: sa solo che davanti ha la sua presa.

Nel software quella presa di casa si chiama interfaccia. È il modo in cui il nostro programma dice di cosa ha bisogno, con le sue parole: dammi i prodotti del catalogo, registra questo pagamento. Il resto del codice conosce solo lei, non il sistema che c’è dietro.

Conta chi la decide. La presa non la sceglie il paese in cui vai: è quella di casa tua. È l’adattatore ad adeguarsi. Allo stesso modo l’interfaccia la scrive chi la usa, non chi sta fuori. L’adattatore la rispetta da una parte e parla con il sistema esterno dall’altra.

È anche quello che toglie di mezzo gli if. Per un paese nuovo non si tocca il phon: si prende un altro adattatore con la stessa presa di casa. Nel codice, per un fornitore nuovo si scrive un altro adattatore che offre la stessa interfaccia. Il resto del programma non se ne accorge.

Alistair Cockburn ha costruito un’intera architettura su questa idea e nel 2005 le ha dato il nome Ports and Adapters: porte e adattatori. Vale anche per il database, come racconto nel test impossibile.

La spina è la parte facile

L’adattatore è l’esempio più semplice perché cambia solo la forma della spina. In viaggio, però, le differenze sono anche altre. I prezzi sono in un’altra valuta, le distanze in miglia, le taglie seguono un’altra scala.

Le prime due si convertono con un conto. Le taglie no: una M americana non corrisponde per forza a una M italiana e le tabelle per le scarpe cambiano da marca a marca. Qualcuno deve decidere cosa vuol dire quel numero per te. È una decisione, non un calcolo.

Nel software la parte difficile è la stessa. Collegare i fili (i parametri, i tipi) è facile. Il lavoro vero è capire cosa intende l’altro sistema, che può chiamare con la stessa parola una cosa che per noi è diversa, o con due parole ciò che per noi è un concetto unico. Tradurre vuol dire decidere cosa significa, con le nostre parole, ogni cosa che arriva da fuori.

Il pezzo che cambia solo la forma della spina, nel software, ha un nome preciso: Adapter, uno dei pattern descritti nel 1994 in Design Patterns. Prende una richiesta scritta in una forma e la riscrive nella forma che l’altro sistema capisce. Il significato resta quello di prima: come l’adattatore in valigia, fa passare la corrente ma non decide cosa vuol dire una M americana.

Le infiltrazioni non le decide nessuno

Non è un’idea mia. Eric Evans, nello stesso libro del 2003 che ho citato per il pezzo sul meccanico, chiama Anticorruption Layer lo strato che si occupa della spina e delle taglie insieme: in pratica, uno strato di traduzione. Isola il nostro programma: parla con il sistema esterno attraverso quello che offre già, senza chiedergli di cambiare, ma al nostro programma restituisce tutto con le parole del nostro modello. Traduce nei due sensi.

Dentro lo strato Evans mette proprio l’Adapter, ma lo tiene separato dal traduttore. L’Adapter sa come fare la richiesta all’altro sistema. Il traduttore decide cosa significa per noi quello che torna indietro. Un Adapter da solo cambia la spina. Lo strato traduce anche le taglie.

Se funziona, è l’unico posto del programma che conosce la “lingua di fuori”.

Quello da cui ci protegge sono le infiltrazioni. Un viaggio dopo l’altro, senza adattatore, a casa ti ritrovi un phon con la spina inglese, un caricabatterie con quella americana e un adattatore dietro ogni presa. Senza uno strato che traduca al confine, i nomi e le regole dell’altro sistema si infiltrano allo stesso modo, finché il nostro programma smette di ragionare con la propria testa e inizia a ragionare come l’altro. Nessuno l’ha deciso: è successo, una scorciatoia dopo l’altra.

Quando l’adattatore non serve

L’adattatore, tuttavia, ha un costo. Va scritto e mantenuto. Ogni traduzione è una decisione di cui qualcuno deve rispondere. Non sempre ne vale la pena.

Il phon comprato senza pensare all’Inghilterra è la scelta giusta finché non parti. Evans ha un nome anche per questo: Conformist. Si adotta il modello dell’altro sistema così com’è e si rinuncia a tradurre. L’integrazione diventa molto più semplice, in cambio di meno libertà sul proprio modello. Ha senso quando quel sistema è l’unico con cui si parla, cambia poco e il suo modello basta per quello che serve.

È una scelta legittima, a patto che sia una scelta consapevole. Chi si conforma deve sapere cosa sta comprando: ogni volta che cambia l’altro, cambia anche lui.

Chi scrive software ci riconosce un principio più generale: YAGNI (You Aren’t Gonna Need It, non ne avrai bisogno). Non si costruisce quello che nessuno ha ancora chiesto. L’adattatore si prende quando il viaggio è in programma, non per ogni viaggio possibile.

Tradurre non è controllare

Il nome inglese inganna un po’: anticorruption fa pensare a un filtro che tiene fuori i dati cattivi. Non lo è.

L’app di conversione ti dice quanto fanno 20 sterline in euro, non se 20 sterline per un panino sono troppe. Allo stesso modo, lo strato traduce quello che arriva: se il sistema esterno manda un dato sbagliato, arriva tradotto e resta sbagliato. Controllare che i dati abbiano senso è un altro lavoro.

Lo strato non protegge i dati: protegge il nostro modo di ragionare.

Se hai un caso in cui un adattatore ti ha salvato, o uno in cui era decisamente meglio farne a meno, scrivimi.

Riferimenti

  • Eric Evans, Domain-Driven Design: Tackling Complexity in the Heart of Software, Addison-Wesley Professional, 2003 (scheda dell’editore): l’Anticorruption Layer come strato che traduce tra due modelli (con Adapter e traduttori distinti) e il Conformist come scelta di adottare il modello dell’altro sistema.
  • Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley Professional, 1994 (scheda dell’editore): il pattern Adapter, che fa parlare due interfacce incompatibili senza cambiare il significato della richiesta.
  • Alistair Cockburn: l’architettura esagonale, che nel 2005 ha ribattezzato Ports and Adapters, in cui il programma parla con l’esterno solo attraverso porte e adattatori.
  • You Aren’t Gonna Need It (YAGNI): il principio dell’Extreme Programming per cui non si sviluppa quello che non è stato esplicitamente richiesto.