Quando si parla di DDD ogni componente in gioco ha la sua importanza, ma la “visione d’insieme” e il contenuto informativo contenuto in un aggregate ricopre un ruolo fondamentale di tutto l’ecosistema.
“A collection of objects that are bound together by a root entity, otherwise known as an aggregate root. The aggregate root guarantees the consistency of changes being made within the aggregate by forbidding external objects from holding references to its members.” (fonte: wikipedia)
Partiamo da ciò che un aggregate non è, in modo da chiarire subito la strada da non intraprendere :-)
Con un’implementazione di questo tipo, abbiamo in prima battuta una “piacevolissima” sensazione di navigabilità, che ci permette, partendo potenzialmente da ogni punto, di raggiungere qualsiasi foglia del grafo.
Questo però vìola le due caratteristiche che un aggregate-root deve avere:
-
garantire la consistenza dell’aggregato
-
evitare l’accesso a nodi figli
…e se ci pensate bene anche alcuni dei principi dell’OOP, per esempio l’incapsulamento. Con un implementazione di questo genere abbiamo potenzialmente scoperto il fianco ad “attacchi” di ogni tipo, nel senso che chiunque abbia accesso ai nostri oggetti ne può manipolare lo stato, partendo da ogni punto.
In base a quanto ci siamo detti nei post precedenti, un domain model senza behaviors è un domain model monco…o meglio non è un domain model :-)
Prendiamo uno use-case “reale” che ci permetta di capire, quando parlo di behaviors, a cosa mi riferisco e come viene modificata l’implementazione di conseguenza:
- quando un utente (fisico o virtuale) del sistema modifica la sede operativa di un’azienda deve essere verificata la corretta associazione alla filiale della banca di riferimento secondo algoritmi, potenzialmente modificabili dinamicamente. Fino a che la nuova banca non ha confermato l’autorizzazione ad operare, l’azienda deve entrare in un limbo che non permetta operatività sull’azienda.
Con un “domain model anemico” ed in totale assenza di aggregate-root non abbiamo modo di garantire la consistenza dello stato dell’oggetto azienda e la conoscenza dei processi di business che vengono veicolati dalla nostra applicazione sono sparpagliati qua e là in “strati” diversi rispetto a quello che per me è l’owner assoluto di questo genere di competenze: il domain layer.
Rifattorizziamo l’object model in modo da enfatizzare il comportamento e incapsulare lo stato (due piccioni con una fava):
In questo modo chiunque voglia cambiare la sede operativa di una particolare azienda, deve passare per forza attraverso le nostre API e da quel punto in poi, il cambio di stato interno, l’interazione con altre componenti del sistema, la consistenza del “grafo” stesso è demandata all’aggregate-root in oggetto: l’unica fonte della verità del nostro dominio.
Attenzione, non è tutto oro quello che luccica, o meglio è “oro”, ma non è così facile da raggiungere: “chiudere” lo stato internamente comporta una pesante rivisitazione di diversi ambiti in cui, con il modello anemico, ci eravamo ormai assestati (vedi persistenza, unit test…). Ma con un po’ di pazienza (e tempo) vediamo tutto!
P.S. a tutti quelli che mi stanno mandando mail, interessati dai post precedenti, innanzitutto grazie per i complimenti :-) Vi chiedo di spostare/postare le vostre interessanti domande nel luogo più appropriato: il forum di guisa. Non perchè io non voglia rispondervi, anzi…ma perchè così apriamo la conversazione ad altre menti geniali (e che sia chiaro: non è che io mi reputi tale…).