Indice dei contenuti dell'articolo:
Viviamo in un’epoca in cui la tecnologia è ovunque, a portata di mano, e apparentemente in grado di risolvere qualsiasi problema. Framework, librerie, architetture e strumenti di automazione nascono e si evolvono a ritmo vertiginoso. Chiunque, oggi, può imparare a costruire un’app distribuita con microservizi, orchestrazione automatica, code asincrone, pipeline di CI/CD e infrastruttura in cloud – tutto questo, spesso, prima ancora di aver capito se l’utente finale ha davvero bisogno di quel prodotto.
Ed è proprio qui che nasce uno dei problemi più gravi, ma più sottovalutati, del nostro settore: l’over-engineering.
Una tendenza distruttiva, subdola, che si nasconde dietro buone intenzioni, ma che finisce per ostacolare ciò che dovrebbe essere l’obiettivo primario di ogni progetto: funzionare, essere utile, generare valore reale.
Negli ultimi 15 anni, ho osservato da vicino decine di progetti – interni, clienti, consulenze, startup e aziende strutturate – affondare sotto il peso di scelte tecniche troppo sofisticate. Quasi mai il problema è stata la mancanza di strumenti o competenze. Quasi sempre, invece, il fallimento è stato causato dal voler costruire un’astronave per fare un lavoro da bicicletta.
L’ego dietro ogni decisione tecnica
Troppo spesso la tecnologia viene scelta non per risolvere un problema, ma per dimostrare qualcosa.
Dimostrare di essere aggiornati, capaci, visionari. Dimostrare al team, al cliente, a sé stessi che si è in grado di gestire Kubernetes, adottare architetture a eventi, lavorare con stack distribuiti. Ma tutto questo, senza un’esigenza concreta, diventa puro esercizio di stile.
- Quanti progetti hanno adottato microservizi per applicazioni usate da poche centinaia di utenti al giorno?
- Quanti team hanno impiegato mesi a costruire sistemi iper-scalabili… per un gestionale interno con accesso limitato?
- Quanti frontend headless, SPA e PWA sono stati messi online senza nemmeno un backend solido o una base utenti reale?
Il punto non è sminuire queste tecnologie, ma contestualizzarle. Se l’obiettivo è impressionare, forse la complessità ha un senso. Ma se l’obiettivo è rilasciare un prodotto funzionante, utile e manutenibile, allora la semplicità è spesso la scelta più coraggiosa e professionale.
La realtà quotidiana nei team di sviluppo
L’over-engineering non è un concetto astratto o teorico. È qualcosa che si manifesta ogni giorno, all’interno dei team tecnici, sotto forma di scelte sbagliate che rallentano tutto: decisioni che sembrano sensate sulla carta, ma che alla prova dei fatti si trasformano in ostacoli alla delivery.
È facile cedere al fascino delle soluzioni complesse, soprattutto quando si è convinti che “fare le cose per bene” significhi strutturare il progetto come se dovesse reggere milioni di utenti sin dal giorno zero. Ma questa convinzione, nella pratica, diventa il punto di partenza per una serie di inefficienze che bloccano lo sviluppo e consumano tempo, risorse ed entusiasmo.
Nella pratica, l’over-engineering si traduce in ritardi, inefficienze, incomprensioni e frustrazione.
Capita spesso di assistere a scenari come questi:
-
Una startup che spende mesi a progettare infrastrutture “pronte a scalare” prima di avere un MVP.
-
Un team che discute per settimane su quale pattern architetturale adottare, senza aver definito il modello dati.
-
Un’app che si basa su eventi asincroni distribuiti… ma non riesce a inviare un’email di conferma.
-
Repository separati per ogni microservizio, ognuno con le sue pipeline, che si rompono a ogni commit.
Nel frattempo, il cliente aspetta. Il mercato si muove. Le esigenze cambiano.
E il progetto rimane fermo, avvolto nella sua elegante complessità.
Il falso mito della scalabilità anticipata
Una delle motivazioni più ricorrenti che giustificano l’adozione di architetture troppo complesse, soprattutto nei progetti agli stadi iniziali, è la presunta necessità di “essere pronti a scalare”. È una frase che si sente ovunque, dalle startup ai team corporate, e che suona sempre razionale. Nessuno vuole trovarsi impreparato nel momento in cui il traffico cresce o il progetto esplode. Il problema, però, è che la maggior parte dei progetti non arriva mai a quel punto. E nel frattempo, la scelta di strutturare tutto come se il successo fosse garantito diventa una zavorra.
Inseguire una scalabilità prematura è, nella realtà, una delle forme più pericolose di over-engineering.
Significa dedicare tempo, budget e risorse a ottimizzare per un futuro ipotetico, mentre il presente è ancora tutto da costruire. È come progettare un’autostrada a 12 corsie per una città che non è ancora stata fondata.
Una delle giustificazioni più comuni dell’over-engineering è questa:
“Facciamolo così, perché dopo dobbiamo scalare.”
Ma la verità è che scalare non serve, se prima non hai utenti reali.
Non serve progettare un’infrastruttura distribuita se il tuo carico è gestibile con una singola istanza.
Non serve introdurre Kafka o RabbitMQ se puoi ottenere lo stesso risultato con un semplice cron job.
Non serve orchestrare 10 container se il tuo stack può girare in locale con un docker-compose
.
Quando si parla di scalabilità, è importante ricordare che:
-
La semplicità è il miglior punto di partenza: si scala meglio ciò che si capisce e si controlla.
-
I problemi di performance vanno affrontati quando esistono, non previsti con mesi di anticipo.
-
Modulare non significa complicare, ma prepararsi in modo naturale alla crescita.
Scalare è un’esigenza che si conquista, non una scusa per complicare tutto fin dall’inizio.
Cosa funziona davvero in un progetto software
Nel mondo dello sviluppo software, il concetto di “seniority” è spesso frainteso. Troppo spesso viene associato alla quantità di tecnologie conosciute, alla capacità di usare strumenti complessi o al numero di pattern architetturali che si sanno applicare a memoria. In realtà, la vera maturità professionale emerge in un’altra forma, molto meno appariscente, ma decisamente più utile per i progetti: la capacità di riconoscere quando una soluzione è eccessiva. E soprattutto, di saperlo dire chiaramente.
Essere senior non significa rincorrere la complessità. Significa avere la lucidità per capire quando non serve, e l’autorevolezza per fermarsi.
Significa scrivere codice semplice, ma robusto.
Significa progettare pensando alla manutenzione futura, non solo alla soddisfazione personale.
Significa scegliere strumenti affidabili, familiari e ben supportati, anche se non sono gli ultimi usciti.
Essere senior, nella pratica, è anche dire:
-
“Non ci serve un Redis cluster, possiamo gestire la logica a livello applicativo.”
-
“Evitiamo di frammentare in otto microservizi: siamo solo in tre, ci complicherebbe la vita.”
-
“Conosciamo bene PHP e MariaDB, e con questi possiamo andare online in sicurezza.”
Saper dire “no” non è un limite tecnico. È una scelta progettuale consapevole.
È rinunciare alla complessità per garantire stabilità.
È mettere al centro il risultato, non la forma.
È consegnare oggi, senza compromettere la possibilità di scalare domani.
In un mondo in cui molti rincorrono la novità, chi sa difendere la semplicità è, oggi più che mai, un vero professionista.
Conclusione: costruisci soluzioni, non monumenti
Quando si sviluppa un progetto digitale, è facile lasciarsi affascinare dalla tecnologia in sé: dall’idea di usare uno stack all’avanguardia, di creare una struttura altamente modulare, di mostrare soluzioni architetturali eleganti e “da manuale”. Ma è fondamentale ricordare che il fine ultimo non è dimostrare competenze, bensì risolvere problemi reali.
Il cliente non paga per vedere la tua architettura a microservizi.
Non gli interessa quanti container stai orchestrando, né se usi GraphQL, gRPC o event sourcing.
Paga per un’app che funziona, un sito che carica velocemente, una dashboard che restituisce i dati corretti in tempo utile.
Paga per un risultato, non per l’infrastruttura che ci sta sotto.
Il tuo valore come sviluppatore, architetto o team lead non si misura in base alla quantità di strumenti che conosci, ma nella tua capacità di scegliere quelli giusti nel contesto giusto.
E soprattutto, nella tua capacità di sapere quando non usarne nessuno in più del necessario.
Quindi, la prossima volta che stai progettando una nuova soluzione, fermati e chiediti:
-
Serve davvero?
-
È il modo più semplice per risolvere il problema?
-
Il team sarà in grado di mantenerla tra sei mesi, senza ansia o blocchi?
Se anche solo una di queste risposte è “no”, è probabile che tu stia costruendo una cattedrale tecnologica per piantare una tenda.
E in quel caso, forse è il momento di tornare alle basi:
Scrivere codice chiaro.
Usare ciò che serve.
Rilasciare in fretta.
Far funzionare le cose.
Perché alla fine, quello che resta è la soluzione. Non solo e sempre l’architettura.