Domain Model e compromessi tecnologici

Approfitto di questo commento sul mio post dell'altro ieri, per scrivere due parole, perchè l'argomento meritava di essere approfondito.

Mario dice:

"...L'unico passaggio su cui non concordo proprio in pieno, se l'ho capito bene, è questo:
...ma si vede che cmq in ogni caso, qualche "pezzo" di pulizia del modello di dominio, in un modo o nell'altro bisogna cederlo.
Mi ricordo l'illuminante chiacchierata con te sulle collection; quando hai detto che utilizzare IList<T> non era un vincolo di NH ma la scelta migliore di design ci ho pensato su 10 secondi e ti ho risposto "Vero! Hai ragione!" e da allora nelle mie entities compare IList<T>..."

Cioè si parla di come alcuni O/RM possano incidere in qualche modo sul disegno delle classi.

Il mio pensiero è questo (cerco di espanderlo):

Sia con NHibernate che con Linq to SQL, ma con qualsiasi sistema di persistenza c'è la necessità di adattare (con impatti magari diversi) il proprio Domain Model in modo che possa funzionare a puntino.

Chiavi primarie
In un mondo puramente teorico, uno potremme immaginare di modellare delle Entity, senza l'informazione della chiave primaria. Ques'ultima è un dato che serve solo ed esclusivamente al sistema di storage. Anche NHibernate potrebbe funzionare senza chiavi primarie (pratica sconsigliatissima).
Il contesto di persistenza (la sua session) potrebbe, una volta tirati su gli oggetti, tenere in memoria l'accoppiata Entity/Chiave. La responsabilità della gestione di una chiave che arriva dal database (o anche generata sul client poco importa) non dovrebbe essere della entità, poichè quest'ultima dovrebbe essere ignorante al modo in cui viene persistita.
Ma ovviamente i contraccolpi sarebbero pesantissimi. I contesti di persistenza sarebbero costretti a sopravvivere a tutta la conversazione applicativa, e questo (in alcuni casi) non è per niente una bella soluzione.

Gestione dei Proxy
Se il Domain Model è costituito da un grafo complesso in cui alcuni dei nodi non vengono caricati immediatamente perchè non servono allo scenario corrente, devo disegnare le classi in modo che una factory ci possa costruire sopra dei proxy. E quindi devo evitare sealed, usare metodi virtual oppure inventarmi delle interfacce. Cambio il disegno, e l'unico motivo per cui lo faccio è perchè devo abilitare il mio domain model alla persistenza.

Identità
NHibernate per garantire l'identità (così come espressa nel CLR) entity che hanno chiavi composite impone che la entity in questione implementi i metodi Equals() e GetHashcode(). Ma ancora è un problema di persistenza. Non di dominio.

Avrei altri esempi in termini di serializzazione, stati e tracking, ma non mi dilungo.

In pratica, ci sono molte problematiche di persistenza che intaccano in un modo o nell'altro il disegno della propria entity, su questo non vi è dubbio. Poi ci possono essere soluzioni più o meno eleganti. L'uso di EntityRef su Linq to SQL per esempio non è una soluzione malvagia. E' la rappresentazione del concetto di proxy o wrapper, e non è riferita al sistema di persistenza. Vedo molto meno l'uso di EntitySet. Al suo posto avrei visto una soluzione un po più alla NHibernate, cioè lasciare che la gente scriva le proprie entity usanto interfacce e poi iniettando la collection corretta a seconda dello scenario (Devo ancora approfondire...magari qualcosa si può fare).

La conclusione è che, non necessariamente si deve essere totalmente "puristi".
Bisogna saggiamente valutare il valore aggiunto apportato ad esempio da una chiave primaria su una entity, o dell'aggiunta di virtual per garantire la creazione di proxy, o di qualsiasi altra cosa, e bilanciarlo con la pulizia concettuale del domain model, arrivando ne più ne meno ad un compromesso tecnologico.

Print | posted on venerdì 29 giugno 2007 19:46

Comments have been closed on this topic.