La programmazione ad oggetti spinge verso l’incapsulamento ed il riuso di codice attraverso l’individuazione di oggetti, purtroppo però in progetti complessi il rischio è che, anche adottando alla perfezione i principi alla base dell’OOP, ci si trovi in una situazione poco gestibile. Solitamente si inizia con degli oggetti ben definiti e siamo molto soddisfatti di come tutto procede.
A questo punto ogni volta che dobbiamo implementare una nuova logica nel dominio, prima di tutto capiamo a quale oggetto compete svolgere quella logica, poi determiniamo gli oggetti con cui deve dialogare e quindi procediamo all’implementazione di nuovi oggetti o alla modifica di oggetti esistenti. Al crescere degli oggetti e della complessità del dominio, inevitabilmente cresce la complessità del codice, e ci troviamo con una ragnatela di oggetti che rischia di diventare troppo complessa per poter essere gestita.
Immaginate ora di continuare ad aggiungere entità al dominio, molto probabilmente vi ritroverete ad un certo punto in una situazione molto meno ordinata e gestibile di quello che inizialmente pensavate.
Piano piano vi ritroverete che modificare un singolo oggetto scatena modifiche a cascata in quasi tutto il dominio, una situazione che chiaramente è meno che ottimale e che vanifica praticamente tutti i vantaggi dell’OOP.
In DDD questa situazione viene evitata grazie all’uso di BOUNDED CONTEXT. Purtroppo nel libro di Evans questo concetto viene enunciato quasi alla fine e non ha l’importanza che merita (qualche paginetta scarsa), e lo stesso Evans al NDC2010 nella sua presentazione dice che il BOUNDED CONTEXT in una ipotetica nuova edizione del libro sarebbe il primo o il secondo capitolo.
Quello che si cerca di trovare è un contesto all’interno del quale l’UBIQUITOUS LANGUAGE abbia un significato preciso, non ambiguo e proprio di quel contesto. Per fare un esempio potremmo prendere il concetto di Ordine e riflettere sul fatto che per l’amministrazione e per lo spedizioniere questo termine ha una finalità ed un contenuto completamente differente. All’amministrazione interessa ad esempio che l’ordine sia pagato in tempo, allo spedizioniere che tutte le parti dell’ordine siano spedite, etc.
La convenienza di un simile ragionamento è che all’interno di un singolo BOUNDED CONTEXT ci si preoccupa solo della parte di dominio identificata in quel contesto, ignorando quindi tutto quello che sta all’esterno. In questo modo il problema viene suddiviso in sottoproblemi isolati, e quindi di più semplice gestione. La prima domanda che viene fatta è però sempre la stessa, come comunicare tra i vari BOUNDED CONTEXT visto che inevitabilmente avremo la necessità di comunicare tra BOUNDED CONTEXT. La risposta in DDD sono i DOMAIN EVENTS e gli oggetti in un BOUNDED CONTEXT si registrano agli eventi che si generano in altri contesti al quale essi sono interessati. Il concetto è simile ad una “bacheca”, quando accade qualche cosa di interessante nel mio contesto, io lo segnalo nella bacheca, senza preoccuparmi se qualcuno poi lo leggerà.
Facciamo un caso pratico preso da un talk di Udi Dahan. Supponiamo che io voglia annullare un ordine (contesto del piazzamento ordini tramite ecommerce) e che ci siano regole di business relative all’annullare un ordine già spedito. Il contesto del piazzamento ordini, alla ricezione del comando annulla ordine xyz verifica che nel suo contesto sia possibile effettuare questa operazione, poi annulla l’ordine e lancia nel bus un evento di Ordine Annullato. Nel contesto delle spedizioni esisterà un handler in ascolto su questo evento e se un ordine annullato è già stato spedito eseguirà una ulteriore regola di business che potrebbe essere.
- accredita il 10% del costo dell’ordine sulla carta del cliente per ammortizzare le spese di spedizione sostenute
- genera un evento di Rollback Annullamento Ordine, che verrà recepito dal Bounded context precedente, l’ordine viene riaperto ed al cliente viene mandata una mail dicendo “ci spiace, ma l’ordine è già stato spedito, per cui non può essere annullato”
- Viene inviata una mail al cliente che da la possibilità di decidere se annullare con la penale del 10% o se annullare l’annullamento
- Etc. etc.
Chiaramente quando l’utente annulla l’ordine, il sistema può solamente dire “l’ordine è in fase di annullamento, verrà avvisato per mail dell’esito dell’operazione”.
A parte questo caso specifico, l’aspetto importante è che quando siamo nel contesto delle spedizioni, non dobbiamo preoccuparci delle entità che sono in gioco in altri contesti, ma semplicemente ci “mettiamo in ascolto” sugli eventi “che ci interessano” che provengono dagli altri contesti per implementare le logiche di business relative a quel solo contesto (Annullamento ordine già spedito).
Nel DDD campus abbiamo veramente discusso di tantissime cose, ma sempre di più rimango dell’idea che il “pattern” più importante che viene dal DDD sia il BOUNDED CONTEXT perchè ci permette di sopravvivere.
Gian Maria.