Domain Driven Design 🧩

“Domain-Driven Design is an approach to software development that centers the development on programming a domain model that has a rich understanding of the processes and rules of a domain.” ― Martin Fowler

Ah, il Domain Driven Design! Quel magnifico approccio che promette di trasformare il caos aziendale in eleganti modelli di dominio. Ma non fatevi ingannare dalla sua apparente semplicità: è come tentare di insegnare l’italiano a un gruppo di pinguini - possibile, ma richiede molta pazienza! 🐧

“The heart of software is its ability to solve domain-related problems for its user.” ― Eric Evans

Fondamenti del Domain-Driven Design 🏗️

La base di tutto: il problema di dominio 🎯

Prima di tuffarci nella teoria, parliamo del problema fondamentale: il problema di dominio. È il problema specifico che il tuo software sta cercando di risolvere. Non quello tecnico (“Come configuro Kubernetes?”), ma quello aziendale (“Come gestiamo gli ordini dei clienti internazionali?”).

Come diceva saggiamente Steve Smith: “As developers, we fail in two ways: we build the wrong thing, or we build the thing wrong.” Il DDD ci aiuta ad evitare entrambi questi fallimenti.

Core domain: il cuore del business 💎

“When you focus on the core domain and domain logic, you can push the design of the software to a higher level.” ― Eric Evans

Il core domain rappresenta il vero valore aggiunto dell’azienda, ciò che la rende unica e competitiva. Tutto il resto (supporting e generic subdomains) serve solo a supportare il core. Investire tempo e risorse nel modellare bene il core domain è fondamentale: qui si gioca la partita dell’innovazione e della differenziazione.

Identificare il core domain non è sempre immediato: spesso richiede di scavare tra le attività aziendali, distinguendo ciò che è davvero strategico da ciò che è solo operativo. Un buon core domain è quello che, se realizzato male, mette a rischio il successo dell’intero progetto.

Modellazione e collaborazione 👥

Interazione con gli esperti di dominio e modellazione dei subdomini 🧑‍💼

Il DDD parte da una verità scomoda: non puoi modellare bene ciò che non comprendi. Ecco perché l’interazione continua con gli esperti di dominio è fondamentale. Non si tratta solo di raccogliere requisiti, ma di coltivare la capacità di comunicare e modellare insieme, un subdominio alla volta. Prima regola del DDD Club: devi parlare davvero con gli esperti di dominio, non limitarti ad annuire mentre ti spiegano processi complicatissimi che sembrano usciti da un romanzo di Kafka.

Event storming: brainstorming con i post-it 🌪️

L’event storming è una tecnica di modellazione collaborativa che coinvolge tutto il team (sviluppatori, analisti, esperti di dominio) in una sessione creativa. Si usano post-it colorati per rappresentare eventi, comandi, attori e regole, aiutando a scoprire rapidamente le dinamiche del dominio e a individuare i bounded context. Spesso emergono problemi, dipendenze e opportunità che sarebbero rimaste invisibili in un classico documento di analisi. Per approfondire: eventstorming.com

Separation of concerns: ognuno al suo posto 🧹

Separare le responsabilità significa evitare che la logica di dominio venga contaminata da dettagli tecnici o infrastrutturali. Questo principio si applica a tutti i livelli: dal codice alle architetture, fino all’organizzazione dei team. Solo così si ottiene un sistema flessibile, testabile e facilmente evolvibile.

Ad esempio, la validazione dei dati dovrebbe risiedere nel dominio, mentre la gestione della connessione al database dovrebbe essere delegata all’infrastruttura. Questa separazione permette di cambiare tecnologia senza dover riscrivere la logica di business.

Modellazione: come decifrare ogni subdominio 🧩

La modellazione non è mai un processo lineare. Si parte da una visione d’insieme, si raccolgono storie e casi d’uso, si costruiscono modelli e si rivedono continuamente. Strumenti come Event Storming ed Event Modeling aiutano a visualizzare i processi e a scoprire regole nascoste. Ogni subdominio va modellato in modo indipendente, rispettando i suoi confini e il suo linguaggio.

Un buon esercizio è chiedersi: “Se dovessi spiegare questo subdominio a un nuovo collega, quali concetti e regole non potrebbero mancare?”. Questo aiuta a individuare le entità chiave e le regole fondamentali.

Pattern e strumenti DDD 🧰

Il linguaggio ubiquo: parole, parole, parole 📚

“A model is not just a knowledge-level description of a domain; it is also the backbone of a language used by all team members to connect their activities with the software.” ― Eric Evans

Il linguaggio ubiquo è come l’esperanto del tuo progetto, ma che funziona davvero! Deve essere utilizzato ovunque: nel codice, nelle discussioni, nella documentazione.

Come dice Eric Evans: “A project faces serious problems when its language is fragmented.” Se il tuo esperto di dominio parla di “Preventivo” e tu nel codice lo chiami “Quote”, stai già creando confusione!

Bounded contexts: recinti di senso 🏰

I bounded contexts sono come stati sovrani nel tuo dominio. Ogni stato ha:

  • Le sue leggi (regole di business)
  • La sua lingua (linguaggio ubiquo)
  • I suoi confini (interfacce ben definite)
  • I suoi passaporti (context maps)

Definizione dei bounded context 🏷️

“If the design, or some central part of it, does not map to the domain, then the model is not doing its job.” ― Eric Evans

Stabilire confini chiari è spesso la parte più difficile del DDD. Serve esperienza, dialogo e la capacità di riconoscere quando un concetto ha smesso di essere utile in un contesto e deve essere riformulato o isolato. Un buon confine protegge la coerenza interna del modello e facilita la manutenzione.

Un errore comune è pensare che un bounded context corrisponda sempre a un microservizio: in realtà, un bounded context è un concetto logico, che può essere implementato anche in un monolite.

Context mapping: la diplomazia del software 🗺️

Il context mapping è l’arte di far comunicare i vari bounded contexts tra loro. È come essere un diplomatico delle Nazioni Unite, ma invece di prevenire guerre, previeni inconsistenze nei dati!

La context map mostra come i bounded context si connettono e comunicano tra loro, supportando la collaborazione tra team. Attenzione: condividere database tra contesti diversi è una ricetta per il disastro!

Tipi di relazioni tra contexts:

  • 🤝 Partnership: collaborazione stretta tra team
  • 🎭 Customer-Supplier: relazione unidirezionale
  • 🛡️ Conformist: un context si adegua all’altro
  • 🌐 Shared Kernel: codice condiviso (usare con cautela!)
  • 🏗️ Anti-corruption Layer: traduci e proteggi

Ubiquitous language: la lingua che unisce 🗣️

Il linguaggio ubiquo si applica a un singolo bounded context e permea ogni conversazione, modello e riga di codice. All’inizio può sembrare un esercizio di terminologia, ma è la chiave per una comprensione condivisa e per evitare fraintendimenti fatali.

Layer di dominio: il cuore pulsante 🫀

Il domain layer è il livello dove si concentrano le regole di business, le entità, i value object, i servizi di dominio e gli aggregati. Qui si trova la vera intelligenza del software. Tutto ciò che riguarda la persistenza, la comunicazione o l’infrastruttura deve restare fuori da questo layer.

Un domain layer ben progettato permette di testare la logica di business senza dipendere da database o framework esterni, rendendo il sistema più robusto e adattabile ai cambiamenti.

Aggregati e radici 🌳

Un aggregate è un insieme di oggetti che vengono trattati come un’unica unità di coerenza per le modifiche ai dati. La root dell’aggregato è l’unico punto di accesso dall’esterno. Questo pattern aiuta a mantenere la consistenza e a semplificare le regole di business.

Ad esempio, in un sistema di ordini, l’ordine può essere l’aggregate root e le righe d’ordine ne fanno parte: nessuno può modificare una riga d’ordine senza passare dall’ordine stesso.

Value objects vs entità 💎

Le entità sono come persone: hanno un’identità che persiste nel tempo, anche se cambiano. I value objects sono come i numeri: sono definiti dai loro attributi e sono immutabili.

  • Entità: oggetti mutabili con identità propria, usati per il tracciamento e la persistenza.
  • Value Object: oggetti immutabili, definiti solo dai loro attributi (es. una data). La loro logica è facilmente testabile e riutilizzabile.

Entità, value object e servizi di dominio 🏷️

Servizi di dominio 🏷️

I domain service rappresentano operazioni di business che non appartengono né a una singola entità né a un value object. Sono stateless e spesso orchestrano più oggetti del dominio.

Un esempio tipico è il calcolo di una tariffa che coinvolge più entità: la logica non appartiene a una sola di esse, ma al dominio nel suo insieme.

Repository: l’astrazione della persistenza 🗄️

I repository forniscono un’interfaccia per accedere agli oggetti del dominio senza esporre i dettagli della persistenza. Questo pattern favorisce la separation of concerns e rende il dominio indipendente dalla tecnologia di storage.

Un buon repository permette di scrivere test di unità sul dominio senza dover configurare un database reale, velocizzando lo sviluppo e aumentando la qualità del software.

Specification pattern: regole riutilizzabili 📏

Le specifiche sono oggetti che incapsulano regole di validazione o selezione. Sono riutilizzabili, testabili e aiutano a mantenere la logica di business fuori dal layer di persistenza.

Ad esempio, una specifica può rappresentare la regola “cliente premium” e può essere usata sia per filtrare i dati che per validare operazioni di business.

Eventi di dominio: il telegiornale del business 📢

Gli eventi di dominio sono notifiche che segnalano cambiamenti significativi nello stato del sistema. Sono fondamentali per integrare bounded context diversi e per implementare architetture reattive o event-driven.

Un evento di dominio ben progettato è immutabile, descrive qualcosa che è già accaduto e usa il linguaggio ubiquo del bounded context di riferimento.

Consistenza eventuale: la pazienza è una virtù ⏳

In sistemi distribuiti, la consistenza immediata non è sempre possibile né desiderabile. La consistenza eventuale permette di scalare e di mantenere le performance, accettando che i dati si sincronizzino con un certo ritardo.

Questo approccio è particolarmente utile quando si lavora con microservizi o sistemi che devono garantire alta disponibilità e resilienza.

Domini anemici: il grande male 🧟‍♂️

Un dominio anemico si verifica quando le classi del modello contengono solo dati e nessuna logica di business. È un anti-pattern che porta a duplicazione delle regole, difficoltà di manutenzione e perdita di significato del modello. Le cause principali sono l’eccessiva influenza di ORM/framework, la separazione forzata tra dati e logica e la scarsa collaborazione con gli esperti di dominio.

Le conseguenze? Modello povero, regole sparse ovunque, bug difficili da tracciare e testabilità ridotta.

Per evitarlo, porta la logica di business dentro il dominio, collabora con chi conosce davvero il business e usa i servizi di dominio solo per operazioni che coinvolgono più entità. Un dominio ricco rende il codice più espressivo, robusto e facile da evolvere.

Approfondimenti pratici, benefici e limiti del DDD ⚖️🧠

Quando (e perché) usare DDD

Il Domain-Driven Design offre il massimo valore quando:

  • Il dominio è complesso e ricco di regole di business
  • È fondamentale una comunicazione chiara tra team e stakeholder
  • Il progetto è a lungo termine e richiede manutenibilità
  • Il problema principale è di dominio, non solo tecnico

Benefici principali:

  • Flessibilità nell’adattarsi ai cambiamenti del business
  • Visione del cliente sempre al centro
  • Percorso chiaro attraverso problemi complessi
  • Codice ben organizzato e facilmente testabile
  • La logica di business vive in un unico posto
  • Possibilità di sfruttare pattern consolidati (Aggregates, Repositories, Specification, ecc.)

Limiti, errori comuni e quando evitarlo

Il DDD non è la soluzione per tutto. Meglio evitarlo quando:

  • Il dominio è semplice o puramente CRUD
  • Il progetto è piccolo o a breve termine
  • Il team non ha tempo o competenze per investire nella modellazione
  • La complessità è solo tecnica e non di business

Errori comuni:

  • Over-engineering su domini semplici
  • Confondere bounded context con microservizi
  • Non coinvolgere davvero gli esperti di dominio
  • Modello anemico (solo dati, niente logica)
  • Linguaggio ubiquo non condiviso tra team e codice

Strategie avanzate e consigli pratici

  • Strategic vs Tactical Design: Parti sempre dalla strategia (confini, linguaggio, relazioni) e solo dopo scendi nei dettagli tecnici (pattern come entità, value object, repository, ecc.).
  • Anti-Corruption Layer (ACL): Proteggi il tuo modello traducendo i dati tra bounded context diversi.
  • Event Sourcing e CQRS: Utili solo in domini complessi dove portano reali benefici.
  • Testabilità: Separa la logica di dominio dall’infrastruttura per testare facilmente le regole di business.
  • Cultura e team: Il DDD funziona solo con collaborazione continua tra sviluppatori e stakeholder e una cultura di dialogo e revisione costante.

In sintesi

Il DDD è una cassetta degli attrezzi potente: usala dove serve davvero, coinvolgi sempre gli esperti di dominio e non aver paura di rivedere i modelli man mano che il business evolve. Non è una bacchetta magica, ma se applicato con criterio, porta chiarezza, robustezza e soddisfazione (come un buon caffè espresso!).

FAQ e miti da sfatare su DDD ❓

DDD è solo per grandi aziende? No, ma dà il meglio di sé in domini complessi e progetti a lungo termine. Per progetti semplici o a breve termine, può risultare eccessivo.

DDD = Microservizi? No! I bounded context sono concetti logici, non necessariamente microservizi. Puoi applicare DDD anche in un monolite.

Serve sempre Event Sourcing o CQRS? No, sono pattern avanzati da usare solo se portano reali benefici. Il cuore del DDD è la modellazione del dominio, non la tecnologia.

DDD è troppo complicato! DDD richiede impegno, ma aiuta a gestire la complessità. Puoi adottarlo gradualmente, partendo dal linguaggio ubiquo e dalla collaborazione con gli esperti di dominio.

Per approfondire 📚

  • Domain-Driven Design: Tackling Complexity in the Heart of Software – Eric Evans (il libro fondamentale, detto anche il “Blue Book”)
  • Implementing Domain-Driven Design – Vaughn Vernon (pratico e moderno)
  • Domain-Driven Design Distilled – Vaughn Vernon (versione compatta e accessibile)
  • domainlanguage.com – Il sito ufficiale di Eric Evans
  • DDD Europe – Conferenza europea dedicata al DDD
  • Event Storming di Alberto Brandolini – Tecnica di modellazione collaborativa
  • YouTube: DDD Europe Talks – Video e presentazioni di esperti
  • Awesome DDD (GitHub) – Raccolta di risorse, esempi e tool open source
Ultimo aggiornamento il