Sebbene affascinante l’analogia con materia e antimateria, in realtà, finisce presto. Nel software concetto e ruolo degli antipattern è molto più concreto e pratico che l’antimateria in fisica. Il valore degli antipattern è circa/uguale a quello dei pattern. La chiara differenza è che gli sviluppatori sono chiamati ad avvicinarsi ai pattern positivi e, ovviamente, a fuggire quelli negativi. Né più né meno di quello che diceva la nonna a proposito delle amicizie da adolescenti.
La miglior definizione di antipattern che abbia mai letto (e dubito fortemente che ne possa esistere una alternativa) è sul wiki di Ward Cunningham—il popolare c2.com. Essa recita quanto segue:
An antipattern is a pattern that tells you how to go from a problem to a bad solution
Un’altra definizione dello stesso Cunningham, più discorsiva e un po’ meno formale, invita a chiamare gli antipattern per quello che realmente sono. Un antipattern è semplicemente una cattiva idea a cui è stato assegnato un nome politically-correct che non offenda istantaneamente colui che l’ha avuta.
Ha senso preparare e studiare un catalogo di pattern negativi?
A mio parere un catalogo di pattern negativi ha non solo senso ma ha, se possibile, ancora più senso di un catalogo di pattern positivi. Gli esempi negativi nella vita possono talvolta sortire effetti indesiderati e scatenare pericolosi istinti di emulazione. Ma nel software è tutta un’altra storia.
Sebbene lontana dall’essere la panacea di tutti i male, nel software la programmazione difensiva è molto efficace nell’economia di progetti reali. Sapere cosa evitare è di gran lunga preferibile che sapere cosa fare ma non essere sicuri di saperlo fare.
Evitare un antipattern significa evitare almeno un macroscopico errore. Se ne possono fare di sicuro altri, ma se non catalogati come antipattern si tratta probabilmente errori meno gravi e macroscopici, se non addirittura rimediabili.
L’importanza degli antipattern discende da una considerazione persino un po’ banale ma sottilmente pericolosa.
Nessun programmatore inserisce deliberatamente errori nel codice o fa volutamente scelte sbagliate. Se capita, si tratta evidentemente di errori in buona fede. Uno ha un’idea, gli sembra buona, e la implementa. Poi di solito quando è troppo tardi per non pagar dazio ci si rende conto che la scelta fatta è clamorosamente fuori luogo.
Un antipattern è raramente una chiara cattiva idea. A rendere pericolosi gli antipattern è il fatto che spesso un antipattern sembra una buona idea. E probabilmente chi li ha chiamati antipattern lo ha fatto per averne sperimentato direttamente sulla pelle del proprio progetto i nefasti effetti.
Vi sono antipattern per ogni scenario software per cui vi sono pattern: architettura, design, servizi, testing, refactoring. A differenza dei pattern, non si può non notare che talvolta gli antipattern sono messi lì in maniera quasi scherzosa.
Un esempio di soluzione che la maggioranza dei protagonisti considera un antipattern, ma che comunque conta un buon numero di sostenitori, è il cosiddetto Anemic Domain Model. Si tratta di un modello a oggetti (ma davvero?) in cui gli oggetti componenti hanno solo dati e nessun behavior. In sostanza si tratta di meri contenitori di proprietà get/set. Secondo questo modello, la logica di dominio viene implementata in uno strato di domain services dove la logica applicativa e logica di dominio finiscono inesorabilmente per mescolarsi. L’Anemic Domain Model è considerato un antipattern per via del fatto che rinnega ogni tentativo (serio) di costruire un modello a oggetti. E’ il classico caso in cui si hanno classi, ma non object-orientation.
Un esempio di antipattern su cui tutti si dicono d’accordo salvo cadere in tentazione troppo spesso è Architecture-as-a-Requirement. L’antipattern si manifesta quando in un team uno dei membri più prominenti si innamora perdutamente di una particolare tecnologia o di uno specifico prodotto ed insiste per adottarlo anche contro ogni logica e necessità.
E vogliamo allora parlare di Design-for-the-Sake-of-Design? Come narcisi allo specchio del nostro codice, non ci capita mai di innamorarci di una soluzione e di volerla pura e illibata come e meglio dell’archetipo della Bellezza. Per descrivere un design si possono usare tanti aggettivi, ma di sicuro:
a) Un design software deve essere finito, ovvero completato in un tempo finito;
b) Non deve essere bello. Semmai elegante, facile da evolvere, testabile, scalabile, etc;
Una volta oltrepassata la soglia di narciso le cose possono solo peggiorare. Ed ecco dietro l’angolo il temuto Over-Use-of-Patterns, in cui per amor di astrazione si arriva a creare una classe factory che restituisce un oggetto che risulta essere un proxy a un delegate che tramite una lambda crea al volo una classe che wrappa un metodo che alla fine si registra come observer di un command che alla fine esegue le sole tre righe di codice che si doveva realmente eseguire.
Dopo questo livello ve n’è solo un altro: Analysis-Paralysis. Che in italiano potrebbe suonare come Astrazione/Castrazione.


Commenti