Gli anti-pattern (o antipattern) sono, nell'ingegneria del software, dei design pattern, o, più in generale, delle procedure o modi di fare, usati durante il processo di sviluppo del software che, pur essendo lecitamente utilizzabili, si rivelano successivamente inadatti o controproducenti nella pratica. Il termine fu coniato nel 1995 da Andrew Koenig, ispirato dal libro Design Patterns: Elementi per il riuso di software ad oggetti scritto dalla Gang of Four (la banda dei quattro), i quali svilupparono il concetto di pattern nel campo del software.
Fu, tuttavia, il libro AntiPatterns del 1998 a rendere popolare l'idea e ad ampliarne l'ambito oltre il campo del design del software, includendo anche l'architettura software e la gestione dei progetti. Successivamente, altri autori hanno ulteriormente esteso il concetto per abbracciare antipattern ambientali, organizzativi e culturali.
Definizione Secondo gli autori, devono presentarsi almeno due elementi chiave per poter distinguere un anti-pattern da un semplice errore logico o cattiva abitudine: Qualche schema ricorrente di azioni, processi o strutture che inizialmente appaiono essere di beneficio, ma successivamente producono più problemi che benefici. L'esistenza di una soluzione alternativa che è chiaramente documentata, collaudata nella pratica e ripetibile, ma che non viene adottata.
Molti anti-pattern sono poco più che errori, problemi irrisolvibili o cattive pratiche da evitare quando possibile. A volte chiamati "pitfalls" (tranelli) o dark pattern (modelli oscuri) se invece sono volutamente ingannevoli, si riferiscono a classi di soluzioni di problemi reinventate in modo sbagliato.
Una guida comunemente utilizzata è la "regola del tre," simile a quella per i pattern: per essere considerato un antipattern, deve essere stato osservato almeno tre volte.
Uso Per prevenire errori che tendono a ripetersi, si può individuare la frequenza con la quale questi si ripetono, e imparare come altre persone hanno rimediato a questi cattivi pattern.
Documentare gli antipattern può essere un metodo efficace per analizzare un ambito problematico e raccogliere conoscenze esperte.
Sebbene alcune descrizioni di antipattern si limitino a documentare le conseguenze negative del pattern, una buona documentazione di un antipattern fornisce anche un'alternativa o un modo per attenuarlo.
Gli anti-pattern più comuni (Nota: il nome in inglese è stato lasciato in quanto è quello con cui i pattern, e gli anti-pattern, sono conosciuti nella lingua italiana)
Organizzativi Progettazione orientata alla commissione (design by committee): presenza di molte persone che contribuiscono a una progettazione, ma mancanza di una visione globale condivisa Corpi tiepidi (warm bodies): aggiungere a un progetto nuovi programmatori che non riusciranno a fare quasi nulla per mancanza di esperienza su di esso Paralisi da analisi (analysis paralysis): progetto fermo nella fase di analisi, ad esempio perché si sta vagliando un ventaglio di soluzioni troppo ampio senza riuscire a sceglierne una, o perché la si sta dettagliando eccessivamente Sistema a tubo da stufa (stovepipe system): organizzazione in cui ogni team è isolato dagli altri, e le comunicazioni sono rese possibili solo verso l'alto o il basso della gerarchia
Nel management Fumo e specchi (smoke and mirrors): mostrare una funzionalità del programma che in realtà non esiste ancora, ad esempio tramite schermate fittizie, senza che l'osservatore sappia che lo sono Gestione a fungo (mushroom management): team in cui ogni impiegato è tenuto isolato, con un compito specifico, senza poter comunicare con i compagni Marcia della morte (death march): progetto i cui vantaggi sono troppo scarsi rispetto alle risorse richieste per svilupparlo, che costringe i programmatori a sforzi pesantissimi e a un numero consistente di ore di straordinario, ma che è comunque destinato a fallire Elefante nella stanza (elephant in the room): ignorare o minimizzare un problema anche se ovvio e appariscente, al fine di evitarlo
Di sviluppo Ancora di nave (boat anchor): mantenere una porzione di codice sorgente diventata inutile Busy waiting: ciclo continuo di attesa di un evento Azione a distanza (action at a distance): modifica che impatta su parti di codice molto lontane tra loro Errore di cache (caching failure): non azzerare o svuotare una cache contenente un errore, dopo che è stato risolto Carica e spara (accumulate and fire): subroutine i cui input sono variabili globali Codice maleodorante (code smell): piccolo malfunzionamento, che però è sintomo di un grande problema più nascosto Colata di lava (lava flow): mantenere porzioni di codice la cui rimozione è rischiosa o può causare conseguenze non determinabili Complessità involontaria (accidental complexity): apparente necessità di sviluppare codice complesso, che invece sarebbe già disponibile in qualche libreria Enorme palla di fango (big ball of mud): sistema costruito in modo caotico, senza una struttura riconoscibile Fede cieca (blind faith): non verificare il risultato di una funzione o il manifestarsi di un errore Inerzia del codice (code momentum): presenza eccessiva di vincoli e dipendenze, che rendono difficili le modifiche Inferno delle DLL (DLL hell): presenza di conflitti tra le DLL da cui il programma dipende Nelle mani del fornitore (vendor lock-in): dipendenza troppo stretta da uno specifico fornitore, non sostituibile se non a costi elevati Input ad-hoc (input kludge): incapacità di gestire dati inseriti nell'interfaccia utente (input) non validi Interblocco ricontrollato (double-checked locking): inizializzazione parziale di un oggetto condiviso tra thread Interfaccia enorme (interface bloat): incorporare troppe operazioni in una sola interfaccia Invecchiamento rapido (continuous obsolescence): sistema le cui nuove versioni sono troppo diverse dalle precedenti, e che quindi invecchia rapidamente e di continuo Inversione di astrazione (abstraction inversion): non esporre funzionalità utili, costringendo a reimplementarle Kitchen sink: oggetto che contiene un gran numero di operazioni complesse ed eterogenee tra loro Numero magico (magic number): inserire costanti negli algoritmi senza documentarne il significato o lo scopo Oggetto Dio (God object): implementare una grossa funzionalità in un unico oggetto che esegue tutte le operazioni, invece che in più oggetti che si dividono il compito; Ottimizzazione prematura (premature optimization): scrivere codice molto ottimizzato, ma poco leggibile Poltergeist: oggetto il cui unico compito è passare informazioni a un unico altro oggetto Priorità alle estensioni (feature creep): aggiungere ulteriori caratteristiche al progetto, andando ben oltre il requisito iniziale Problema dello yo-yo (yo-yo problem): struttura eccessivamente frammentata e quindi difficile da comprendere Programmazione cargo cult (cargo cult programming): inserire una porzione di programma ignorandone scopo o principio di funzionamento Programmazione copia e incolla (copy and paste programming): implementare una funzionalità simile ad un'altra copiandone e incollandone il codice piuttosto che creando una subroutine condivisa Pulsante magico (magic pushbutton): pulsante che contiene anche la propria logica applicativa, invece che tenerla separata Punto di vista ambiguo (ambiguous viewpoint): diagramma che indica solo le parti, ma non cosa compongono, ad esempio senza distinguere tra parti di interfaccia e di implementazione Reinventare la ruota (reinventing the wheel): reimplementare un metodo che è già stato implementato, testato e ottimizzato da qualcun altro Reinventare la ruota quadrata (reinventing the Square Wheel): come reinventing the wheel, ma il risultato della reimplementazione è peggiore del metodo esistente Saltare il primo (Fencepost o anche off-by-one error): partire dall'indice iniziale sbagliato in un loop (ad esempio in Java iniziare il loop su un array partendo da 1 invece che da 0, o contare un intervallo di valori escludendo il primo, tipicamente il numero di giorni di validità compreso fra due date dimenticando che il primo giorno va considerato) Software che ingrassa (software bloat): tendenza di un'applicazione ad avere programmi di installazione che crescono a dismisura Spaghetti code (spaghetti code): codice con un flusso incomprensibile Codifica fissa (hard code): inserire costanti nel codice piuttosto che in file di configurazione Valori esterni (soft code): inserire logica applicativa in file di configurazione (ad esempio con un linguaggio di comandi) piuttosto che nel codice Vicolo cieco (Dead End): dover modificare una componente su cui il supporto da parte di chi l'ha fornita è cessato
Note
Bibliografia William J. Brown, Raphael C. Malveau, Hays W. McCormick III, e Thomas J. Mowbray. 1998. AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis. John Wiley & Sons ISBN 0-471-19713-0.
Altri progetti
Collegamenti esterni http://www.antipatterns.com
Categoria:Architettura del software