Il fanatismo della centralizzazione e il mito dei design pattern perfetti

Quando il coltellino svizzero ha troppe funzioni

L’over-abstraction è il male supremo dello sviluppo software, l’equivalente di quei coltellini svizzeri con cinquanta funzioni di cui ne usi regolarmente solo due, mentre le altre servono solo a renderti la vita difficile quando cerchi disperatamente il cavatappi. Eppure, ogni giorno, migliaia di sviluppatori cadono nella trappola di vedere pattern ovunque, come chi inizia a vedere facce nelle nuvole e dopo un po’ ogni ammasso di vapore acqueo diventa un potenziale ritratto.

La prematura astrazione sembra una grande idea per evitare future complicazioni, ma probabilmente è un disastro annunciato. Gli sviluppatori junior, e ammettiamolo anche quelli senior in giornate particolarmente ottimistiche, spesso cadono nella trappola di applicare design pattern appena li leggono, senza riflettere a fondo sul contesto e sulle specificità della situazione. Il risultato? Codice che complica anziché semplificare.

Il DRY trasformato in dogma religioso

L’origine di questa mania deriva da un principio fondamentalmente corretto: il DRY (Don’t Repeat Yourself). È una regola aurea dello sviluppo software, come lavarsi le mani prima di cucinare. Il problema nasce quando questo principio viene interpretato con lo stesso fanatismo di chi decide che, siccome mangiare verdure fa bene, allora dovremmo nutrirci esclusivamente di broccoli.

Il DRY dovrebbe essere più un suggerimento che un comandamento inciso sulla pietra. Prima di lanciarvi in un’astrazione complessa, fermatevi e chiedetevi: “Sto davvero risolvendo un problema, o sto solo spostando la complessità da una parte all’altra come in un gioco di prestigio particolarmente elaborato?”

La verità è che alcune duplicazioni nel codice sono come i gemelli: possono sembrare identici a prima vista, ma hanno personalità distinte che meritano di essere rispettate. La vera arte sta nel saper distinguere quando la duplicazione è effettivamente un problema da risolvere e quando invece è semplicemente la naturale espressione di logiche di business genuinamente diverse.

L’apocalisse del centralizzatore ossessivo

Il centralizzatore ossessivo è una figura mitologica del mondo dello sviluppo software. Arriva sul progetto e osserva il codice esistente con lo sguardo di chi ha appena trovato un nido di peccatori. “Perché questo codice non è centralizzato?” chiede, come se avesse scoperto un crimine contro l’umanità.

Non importa che gli si spieghi che quelle funzioni, apparentemente simili, hanno in realtà cruciali differenze. Lui vede solo duplicazione, come un martello che vede chiodi ovunque. E così inizia la sua crociata.

Prima cerca di creare una gerarchia di oggetti così complessa che farebbe sembrare l’albero genealogico delle case reali una lista della spesa. Classi astratte si moltiplicano, interfacce si accumulano, e ogni pattern viene stiracchiato fino al punto di rottura.

Ma quando si rende conto che la realtà è troppo complessa per una bella gerarchia ordinata, passa alla fase due: l’apocalisse degli IF. Aggiunge condizionali come se fossero punteggiatura. Il codice si trasforma in un labirinto di branch logic.

Il risultato? Un mostro di codice dove ogni funzione è tecnicamente centralizzata ma è diventata così complessa che capirne il comportamento richiede un dottorato. Il codice originale occupava cento righe? Ora ne occupa trecento, ma è centralizzato!

Poi arriva il momento della verità: bug emergono dal nulla, gli unit test passano perché verificano quello che il codice fa, non quello che dovrebbe fare. Ma il centralizzatore non è più qui per vedere il caos seminato, lasciando sviluppatori che imprecano mentre cercano di capire perché una modifica causa effetti collaterali in altri dieci punti.

Il divario tra teoria e pratica

Per i programmatori alle prime armi, applicare correttamente i design pattern rappresenta una delle sfide più grandi. Sulla carta sembrano concetti chiari, soluzioni standard a problemi comuni. Tuttavia, nella pratica, integrarli nel proprio codice in modo efficace è tutt’altro che semplice.

Spesso la difficoltà risiede nella mancanza di esperienza nel riconoscere quale pattern si adatti realmente a un determinato problema. I principianti possono essere tentati di applicare subito un design pattern appena lo leggono, finendo per forzare una soluzione che non è necessaria e che paradossalmente complica il codice.

Il divario tra teoria e realtà si fa evidente guardando come i pattern vengono presentati nei manuali: esempi semplici e isolati che non riescono a rendere conto della complessità reale. In un ambiente di programmazione vero, ci si trova ad affrontare vincoli, interdipendenze e requisiti mutevoli che rendono difficile applicare un pattern senza introdurre ulteriori difficoltà.

La curva di apprendimento risulta ripida, perché ogni pattern porta con sé implicazioni concettuali non immediatamente intuibili. Un ulteriore aspetto critico è la difficoltà nel trovare un equilibrio tra flessibilità e semplicità. Alcuni pattern possono migliorare modularità e riusabilità, ma per un principiante sembrano un’aggiunta inutile rispetto a una semplice funzione.

I pericoli nascosti dell’astrazione eccessiva

La ridotta leggibilità del codice troppo astratto è subdola. Quando ogni concetto è nascosto dietro tre layer di interfacce e classi astratte, capire cosa fa realmente il codice diventa un’impresa archeologica. Devi scavare attraverso strati di astrazione come un archeologo, sperando di arrivare alla logica effettiva prima che il budget del progetto finisca.

L’elevato accoppiamento che risulta da astrazioni mal pensate è ironico: nel tentativo di rendere il codice più modulare, si finisce per creare dipendenze così intricate che modificare una classe richiede di toccare altre venti. Trovare il giusto compromesso, evitando sia il codice spaghetti sia una sovra-astrazione che appesantisce il sistema, è una sfida che si supera solo con il tempo e l’esperienza.

La moderazione come chiave del successo

La lezione fondamentale è che la centralizzazione è uno strumento, non un dogma. A volte, un po’ di duplicazione controllata è preferibile a una centralizzazione forzata che trasforma il codice in un puzzle multidimensionale.

Applicare i design pattern è una sfida anche per sviluppatori esperti, poiché la programmazione reale raramente segue uno schema da manuale. Il consiglio più valido è concentrarsi prima sulla scrittura di codice funzionante e leggibile, per poi imparare a riconoscere gli schemi ricorrenti e applicare i design pattern solo dove risultino veramente utili.

La prossima volta che sarete tentati di creare un’astrazione elaborata, ricordatevi che il miglior codice non è quello con meno ripetizioni, ma quello che racconta la storia più chiara. E se questo significa avere qualche duplicazione, che sia. Dopotutto, anche la natura si ripete, e nessuno cerca di rifattorizzare i fiori perché usano tutti lo stesso pattern di crescita.

Il vero problema non è usare i design pattern, è trasformarli in feticci da applicare ovunque senza criterio. La soluzione sta nell’esperienza, nel giudizio, e nella volontà di accettare che a volte la soluzione più semplice è anche quella migliore.


Questo articolo è tratto da “Non funziona niente! – I progetti IT in crisi”, il primo libro della collana Nothing Works! — una tragicommedia aziendale per chi ha visto troppi Gantt chart trasformarsi in fiction.

Scopri la collana completa, gli altri libri e le prossime uscite su nothingworks.it

Vuoi il libro subito? Compralo su Amazon

Potrebbe interessarti anche