Ho appena letto un paio di post, uno di Andrea ed uno di Raf, sul domain model e sulla effettiva necessità di un dominio non solo "persistence ignorant" ma infrastructure ignorant. Decisamente poter creare un dominio infrastructure ignorant è una sfida interessante, e non posso che dire di essere daccordo con Andrea. D'altra parte come Raf fa notare, pensare di usare proxy potrebbe essere veramente dannoso per le prestazioni.
Personalmente non vorrei preoccuparmi a priori delle prestazioni, a parte il "premature optimization is the root of all evil", preferisco avere una architettura più manutenibile, e tenere sotto controllo le prestazioni durante lo sviluppo per capire se le soluzioni adottate siano in linea con i requisiti. La generazione di proxy a runtime può essere interessante (ci ho lavorato e la reflection.emit è decisamente divertente), ma a mio avviso non è adatta per questo genere di cose, si è vero, posso generare un proxy che supporti INotify... e quello che mi pare, ma poi è una classe che a design time non esiste, non posso interagirci, etc etc.
Un approccio decisamente migliore è la generazione del codice design time, un po come il dataset Strongly typed. In questo modo ad esempio si potrebbe scrivere un generatore di DTO a partire dagli oggetti di dominio. L'approccio dei DTO è infatti quello che preferisco, anche perchè è possibile in questo modo ridurre i dati da trasmettere. Se ho un oggetto con 10 proprietà e mi serve una lista di tali oggetti da mostrare su una griglia che binda solo 3 proprietà su 10, avere un DTO specializzato allo scopo è sicuramente la cosa migliore.
Il problema dei Dto è naturalmente che: se li gestisci a mano, puoi farlo per un dominio di poche entità, altrimenti diventi matto, se usi un generatore, questo deve essere il più possibile automatizzato. A suo tempo pensai ad esempio ad usare codesmith, ma c'è bisogno di qualche cosa di più efficiente. La cosa migliore sarebbe avere un designer simile a quello delle classi o dei dataset strongly typed, potere fare drag and drop di classi, decidere quali proprietà spostare e generare tutto il codice a design time, magari utilizzando anche delle partial property per potersi intrufolare in mezzo al codice generato se possibile. Il problema maggiore di un approccio fortemente DTO oriented è che, come dice raf
Il costo di creazione e manutenzione dei proxy e del codice che serve a fare quelle stesse cose (ma dall'esterno dell'entity) non è poco: maggiore complessità e ciclo di vita più lungo del software
Però in certi casi sono cose che tolleriamo senza problemi, il lazy load NHibernate lo fa con Castle.DynamicProxy (Nhibernate 2.0 dovrebbe essere portato a DynamicProxy2) ed è una cosa che non ha mai sollevato troppe obiezioni. D'altra parte ci fidiamo del fatto che il generatore di codice sia corretto, per cui l'unica manutenzione è al massimo quella di mantenere i file di mapping o qualsiasi artefatto sia stato creato per stabilire come il codice debba essere generato.
Il problema di fondo è che raggiungere la completa ignoranza dell'infrastruttura è sicuramente utopico e forse anche troppo radicale, quello che vorrei è solamente poter limitare al minimo questa intrusione. NHibernate riesce a fare persistenza richiedendo poche specifiche alle nostre classi (membri virtuali per i proxy, un costrutture di default, ..), per cui è sicuramente possibile fare librerie di infrastruttura poco intrusive ;). Mi piacerebbe che quando qualcuno progetta infrastrutture cercasse di realizzarle nel modo meno intrusivo per le entità di dominio, se poi questo non è possibile bene, ma almeno provare.
Il rischio è che ci si trovi ad avere la classe X che implementa 10 interfacce solo per il piacere di essere usata da EntityFramework, Reporting Services, Crap Library, bla bla.
alk.