Architettura software .NET per smettere di rincorrere il codice e tornare a governarlo

Qui trovi come usare design pattern, DDD e CQRS per prendere decisioni strutturali migliori, tagliare debito tecnico inutile e costruire software .NET che non si sbriciola appena cambia il dominio.

I design pattern non sono ricette da copiare: sono risposte a problemi reali

Ogni volta che vedo un progetto con classi chiamate FactoryManagerHelperService ho la certezza di trovarmi davanti a un uso del pattern sbagliato: qualcuno ha imparato il nome senza capire il problema che quel pattern dovrebbe risolvere.

Un design pattern è una soluzione consolidata a un problema che si ripete.

Il Repository non esiste per soddisfare un requisito architetturale astratto: esiste perché separare la logica di dominio dall'accesso ai dati rende il codice testabile, sostituibile e leggibile da chiunque conosca il pattern.

Se nel tuo progetto nessuno sa spiegare perché esiste un certo layer, quel layer probabilmente non dovrebbe esistere.

Il mio approccio ai pattern è pragmatico.

Prima capisco quale problema c'è, poi valuto se un pattern noto lo risolve meglio di una soluzione ad hoc.

Molto spesso la risposta è sì: non perché i pattern siano magia, ma perché rappresentano il risultato di decenni di errori che altri hanno già fatto.

Questa categoria esiste per aiutarti a capire i pattern come strumenti di pensiero, non come checklist.

Quando sai perché Repository, CQRS, Mediator o Specification esistono, smetti di applicarli meccanicamente e inizi a usarli dove portano valore reale.

Quando l'architettura diventa un problema economico

L'architettura software non è un tema accademico.

È un problema economico che si manifesta nel tempo.

Un sistema progettato male non crolla il giorno uno.

Regge.

Poi rallenta.

Poi ogni modifica richiede il doppio del tempo.

Poi le persone chiave diventano insostituibili perché solo loro conoscono i punti oscuri del codice.

Poi il testing diventa impossibile.

Poi arriva il refactoring di emergenza, che di solito costa cinque volte quello che sarebbe costato fare le cose bene all'inizio.

Quando un team mi chiede aiuto su un sistema in difficoltà, quasi sempre trovo le stesse radici: accoppiamento eccessivo tra componenti, assenza di confini chiari tra dominio e infrastruttura, logica di business dispersa ovunque, nessuna coerenza nei nomi.

Sono tutti sintomi che indicano l'assenza di un modello architetturale consapevole.

I pattern non eliminano la complessità del dominio.

La rendono governabile.

E la differenza tra complessità governabile e complessità caotica è spesso la differenza tra un'azienda che riesce a rilasciare e una che ha paura di cambiare qualcosa.

SintomoCausa archittetturale frequenteIntervento con pattern
Ogni modifica rompe qualcosa di inaspettatoAccoppiamento forte tra moduliSeparazione con Repository, Mediator, eventi di dominio
Nessuno riesce a testare le funzioni chiaveLogica mescolata con infrastrutturaClean Architecture, Dependency Inversion
I bug si moltiplicano sotto stressStato condiviso e mancanza di confiniAggregate Root, Bounded Context, CQRS
Il team rallenta man mano che il sistema cresceNessun linguaggio condiviso sul codiceDDD e Ubiquitous Language

DDD, CQRS e Clean Architecture: quando usarli e quando evitarli

Uno degli errori più costosi che vedo nei team è adottare DDD, CQRS o Clean Architecture perché «si fa così» o perché li hanno visti in un talk su YouTube.

Questi sono pattern ad alta complessità strutturale: portano benefici reali solo quando il dominio li giustifica.

DDD ha senso quando la complessità del sistema sta nel dominio di business, non nell'infrastruttura. Se stai costruendo un sistema di gestione contratti, workflow di approvazione o logica di pricing complessa, DDD ti dà gli strumenti per modellare quel dominio in modo esplicito e condiviso con il business. Se stai costruendo un CRUD con qualche validazione, DDD è overkill.

CQRS ha senso quando i modelli di lettura e scrittura hanno requisiti molto diversi: performance, proiezioni denormalizzate, scalabilità asimmetrica. Se applichi CQRS a un sistema dove lettura e scrittura hanno la stessa semplicità, stai aggiungendo layer senza aggiungere valore.

Clean Architecture ha senso quando vuoi che il dominio non dipenda dall'infrastruttura e che il sistema sia testabile indipendentemente dal database, dal framework o dall'UI. Ma richiede disciplina: senza una comprensione profonda delle dipendenze tra layer, diventa un labirinto di interfacce inutili.

Il principio che uso sempre è: applica la complessità strutturale solo dove la complessità del problema la giustifica.

Il codice semplice che funziona è meglio del codice complesso che segue un pattern.

Come introdurre i pattern in un progetto esistente senza bloccare il team

Nessuno ha il lusso di riscrivere tutto da zero.

I pattern devono entrare nei sistemi esistenti in modo incrementale, senza bloccare le consegne e senza terrorizzare il team.

Il mio approccio è sempre per priorità di rischio e impatto.

Non inizio dal layer più bello da refactorizzare: inizio dal codice che causa più problemi, che nessuno vuole toccare, che rallenta ogni sprint.

Spesso è la logica di business dispersa nei controller, oppure l'accesso diretto al database dappertutto, oppure una classe da tremila righe che fa tutto.

Il primo passo non è introdurre un pattern: è capire dove il codice produce attrito e perché.

Solo dopo si sceglie lo strumento.

A volte basta estrarre un metodo.

A volte serve un Repository.

A volte il problema è un Bounded Context non riconosciuto che mescola responsabilità incompatibili.

Quello che non funziona è imporre un'architettura dall'alto e aspettarsi che il team la rispetti senza capirla.

I pattern si adottano quando il team capisce il problema che risolvono.

La formazione è parte del processo, non un prerequisito separato.

Come leggere gli articoli di questa categoria

Gli articoli che trovi qui non sono tutorial che ti insegnano a implementare un pattern in venti minuti.

Sono analisi di problemi reali, con il ragionamento che porta alla scelta di una certa struttura e le conseguenze che quella scelta produce nel tempo.

Alcuni articoli partono da un sintomo: un sistema che non scala, un test impossibile da scrivere, una funzione che nessuno riesce a modificare senza paura.

Da lì arrivano al pattern che risolve quel problema specifico, spiegando perché funziona e dove smette di funzionare.

Se vuoi usare questa categoria nel modo più efficace, ti consiglio di non leggerla in ordine alfabetico per pattern.

Parti dal sintomo che riconosci nel tuo sistema, trova l'articolo che lo affronta, capisce il ragionamento e poi valuta se il contesto è abbastanza simile da rendere applicabile la stessa soluzione.

I pattern non si copiano.

Si capiscono e si adattano.

Analisi, casi e articoli su design pattern, DDD, CQRS e architettura .NET

11 articoli trovati

Quando l'architettura smette di essere teoria

L'architettura smette di essere teoria quando il software deve essere mantenuto per anni, coordinato da piu persone e modificato senza paura. In quel momento pattern, confini e responsabilita non servono a fare bella figura: servono a evitare costi nascosti, regressioni e decisioni improvvisate.

Domande frequenti

I design pattern sono soluzioni consolidate a problemi ricorrenti nella progettazione del software. Non vanno applicati per abitudine, ma quando il problema che risolvono e effettivamente presente: complessita nella gestione delle dipendenze, accoppiamento eccessivo tra moduli, logica duplicata. Usarli a prescindere aumenta la complessita invece di ridurla.

I design pattern, come Singleton, Repository o Factory, riguardano la struttura a livello di classi e componenti. I pattern architetturali, come CQRS, DDD o Clean Architecture, riguardano l'organizzazione dell'intero sistema: come i layer si relazionano, dove risiedono le responsabilita, come i dati fluiscono. I primi si usano dentro i secondi.

Domain-Driven Design in .NET si applica strutturando il codice attorno al dominio di business: entita, value object, aggregati e repository rispecchiano il linguaggio del business. In pratica significa scegliere nomi significativi per classi e metodi, isolare la logica di dominio dai dettagli infrastrutturali e costruire un bounded context chiaro prima di pensare ai pattern tecnici.

No. CQRS separa i modelli di lettura e scrittura e puo essere utile anche in forma semplice, senza Event Sourcing. Event Sourcing aggiunge la persistenza degli eventi come fonte di verita invece dello stato corrente: e una complessita significativa che si giustifica solo quando la storia delle operazioni ha valore di business autonomo. Combinarli senza un motivo solido crea overhead senza benefici.

Fonti e riferimenti

Martin Fowler, Patterns of Enterprise Application Architecture

Il testo di riferimento assoluto per chi lavora su sistemi enterprise. Fowler cataloga i pattern con un rigore che pochi autori hanno eguagliato. Lo consiglio non per memorizzare le ricette, ma per capire il ragionamento che sta dietro ogni scelta strutturale: perche un certo confine esiste, quando diventa un vincolo e quando una liberazione.

Eric Evans, Domain-Driven Design

Il libro che ha cambiato il modo in cui i team tecnici parlano con il business. DDD non e una checklist di classi da creare, ma un modo di costruire modelli che riflettono davvero il dominio. Lo cito perche ogni volta che un progetto diventa difficile da spiegare, il problema e quasi sempre nell'assenza di un linguaggio condiviso tra chi sviluppa e chi decide.