Cosa ho capito del domain-driven design
Il Novembre 15, 2021 da adminDDD 101
Più grande è il progetto, più difficile è mantenerlo. Un modo per aiutare in questo è rompere l’applicazione in aree più piccole secondo le loro regole di business, conosciute come domini.
Fondamentalmente, un dominio è un’area di conoscenza, sia pubblica, come le regole degli scacchi, o privata, come le regole di business di un’organizzazione non profit.
Un dominio complesso è probabile che usi la conoscenza da altri domini. Per esempio, una ONP che insegna gli scacchi online saprà degli scacchi, dell’insegnamento attraverso piattaforme online, e, anche se non vi è addebitato come studente, delle sue finanze.
Ogni sottodominio del vostro dominio è noto in DDD come contesti delimitati, ognuno ha il proprio modello del mondo costruito con unità specializzate di codice, note come building blocks. Qui mi concentrerò sulle entità e sugli oggetti-valore, entrambi possono essere referenziati come oggetti.
Le entità sono oggetti destinati ad essere unici all’interno del dominio. Questo si ottiene usando una o più proprietà per identificare una data entità. Per esempio, due utenti che usano lo stesso nome in un sistema avranno sempre email diverse perché le email non possono essere ripetute – più spesso che no, le entità sono differenziate da un id, e a volte da una combinazione di proprietà.
Gli oggetti-valore, d’altra parte, non hanno un’identità, quindi solo le loro proprietà possono essere usate per distinguere tra due istanze. Prendete per esempio due pedoni (la pedina degli scacchi), hanno lo stesso aspetto se provengono dallo stesso set di gioco e hanno lo stesso colore, quindi non importa se li scambiate. In DDD, gli oggetti-valore sono immutabili, quindi è più facile ragionare con loro.
Integrità dei dati
Un contesto delimitato non espone tutti i suoi oggetti per garantire la sua integrità dei dati. Invece, espone alcune radici aggregate come una specie di interfaccia pubblica a se stesso.
Un aggregato non è altro che un’entità composta da altri oggetti. Per essere più precisi, un aggregato è un gruppo di oggetti associati che trattiamo come un’unità quando cambiamo i dati.
In termini pratici, gli aggregati assumeranno la forma della struttura dati nota come albero. E per questo motivo, tutti gli aggregati hanno una radice.
L’unico membro di un aggregato a cui gli altri oggetti possono fare riferimento è la sua radice, e quindi questo è ciò che esponiamo. Si fa così perché impedisce ad altri oggetti di modificare i dati in un modo che l’aggregato non può controllare.
È importante chiarire che un contesto delimitato potrebbe usare molti aggregati anche quando le loro radici non sono direttamente esposte al mondo esterno.
Gestione di più contesti delimitati
Ma le cose possono diventare più complicate, giusto? Ogni contesto delimitato ha un modello leggermente diverso degli stessi oggetti, con proprietà e comportamenti diversi. Così un utente in un contesto di gioco può avere una proprietà per gestire il suo punteggio che in un contesto finanziario è irrilevante e quindi non esiste.
E non è tutto. È anche possibile che un concetto di dominio, rappresentato come un’entità in un contesto delimitato, sia rappresentato come un oggetto-valore in un altro, o semplicemente sia completamente omesso.
Per esempio, mentre il contesto di insegnamento richiede che gli insegnanti siano rappresentati come entità in modo che possano essere assegnati agli studenti tramite i loro id, il contesto finanziario preferisce vedere “insegnante” come un valore per la proprietà di posizione dell’entità dipendente.
Alcuni degli altri blocchi di costruzione DDD sono servizi, depositi, fabbriche ed eventi. Cercherò di descriverli brevemente.
I servizi sono capacità di un dominio che non si adattano naturalmente alle entità o agli oggetti-valori. Attenzione che sono servizi di dominio, non servizi di applicazione o di infrastruttura.
I depositi sono ponti verso unità di memorizzazione – ciao CRUD!.
Le fabbriche sono metodi per creare oggetti di dominio in modo che non abbiano mai valori non validi. Questa parte è quella che mi ha fatto iniziare a pensare ai test guidati dal prodotto.
Gli eventi sono oggetti che rappresentano qualcosa che è successo nel dominio – i suoi esperti se ne preoccupano. Grandi opportunità per creare un’applicazione event-driven.
Anche se non ricordo che Evans l’abbia detto, i bounded contexts sono una bella opportunità per dividere il tuo codice in microservizi, dove ogni servizio è un contesto a sé stante. Il primo passo potrebbe essere una suddivisione “virtuale” dove ogni contesto è messo in un modulo diverso sulla stessa app, e poi se si scopre che sono davvero isolati, spostarli in altri.
Un linguaggio per governarli tutti
Una delle prime cose che la gente impara quando studia DDD è che il loro sistema dovrebbe essere descritto da un linguaggio onnipresente. Cioè, dovremmo scrivere codice usando gli stessi verbi (per i metodi o servizi) e sostantivi (per gli oggetti) che gli esperti del dominio usano quando parlano con noi.
Scrivere codice in questo modo ha il vantaggio di chiudere il gap di comunicazione tra sviluppatori ed esperti quando parlano, ma è una semplificazione eccessiva della vita reale, quindi personalmente la uso come linea guida ma non come soluzione finale.
L’ho conservato per ultimo perché, per me, la cosa più importante di DDD di solito non si legge, come è nella parte “complessa” del libro.
Recentemente ho saputo che l’autore stesso ha detto che l’ordine in cui presenta le cose nel libro non è ottimale, e quello che ho descritto qui è più vicino a quello che sarebbe stato ideale 😍. L’ho sentito in un podcast che si riferisce a questo
.
Lascia un commento