nei commenti all’ultimo post mi sembra sia emerso un dettaglio importante, ho la sensazione che ci sia la convinzione, a mio modo di vedere errata, che un ViewModel sia (o debba essere) un DTO.
Ho anche la sensazione che questo errore, o presunto tale, derivi dalla migrazione che molti sviluppatori stanno facendo, o pensano di fare, da altri pattern di presentazione dei dati, come ad esempio MVC portandosi dietro l’esperienza acquisita con questo modello.
In MVC, in particolare se calato nel mondo web, c’è una forte disconnessione tra la View e il Controller, disconnessione derivante dalla natura di http; è quindi molto sensato che in MVC, in particolare in contesti web-based, i dati che viaggiano dal Controller verso la View e viceversa siano sottoforma di DTO.
image
Se notate anche per MVC il modello è completamente mediato dal Controller, non per questo il Controller è un DTO.
ViewModel == Orchestrator
Un ViewModel ha lo stesso ruolo di mediatore nel rapporto tra il modello e la view la differenza fondamentale è che in M-V-VM non c’è forte disconnessione ma, al contrario, c’è forte connessione e quindi viene sfruttato il potentissimo motre di Data Binding di Wpf.
Perchè quindi un ViewModel non è un DTO?
Perchè un ViewModel ha un ruolo con ben più responsabilità e comportamenti (behavior) oltre a quelle del mero DTO, tipicamente anemico, il cui scopo è quello di trasportare i dati in forma “leggera”.
Facciamo un paio di esempi di responsabilità che io assegno molto volentiari al ViewModel e che non vedo in che modo possano essere assegnate al modello:
  • Validazione contestuale al caso d’uso: ci sono regole di validazione che sono valide up-front a priori e che quindi possono essere verificate direttamente, anche, sul modello:
  • e.g.: Person.FiscalCode: il codice fiscale, se c’è, ha un formato ben preciso quindi, se c’è, lo possiamo validare a fronte di un set di regole staticamente note… ma cosa stabilisce che ci deve essere? probabilmente il caso d’uso. In un sistema di commercio elettronico il codice fiscale è obbligatorio solo ed esclusivamente in fase d’acquisto se stai richiedendo fattura come privato… quanti se :-); questa cosa è, e io sono convinto che così debba essere, totalmente ignara al modello mentre è molto nota al ViewModel che rappresenta quello specifico caso d’uso;
  • Change Tracking: la gestione del tracking delle modifiche durante l’editing, il classico undo/redo, ha molto senso che sia gestita direttamente dal ViewModel e non dal modello;
  • INotifyPropertyChanged: credo che nessuno pensi di implementare il motore di notifica direttamente sul modello o di avere un modello che espone delle ObservableCollection al posto di mere IList;

Ci sono molti altri esempi che si potrebbero portare a favore di questa tesi, dall’altra parte qualcuno potrebbe obiettare che rischiate di passare la vita a scrivere ViewModel… Certo ma non è un problema perchè in realtà non sono dei DTO ma si portano dietro un sacco di logica che altrimenti non troverebbe posto, questa logica è la vostra logica di business o meglio ancora la logica che orchestra la logica di business.

In questo scenario è possibile avere dei Wrapper automatici per velocizzare la scrittura di molta parte dei ViewModel, ci ho provato e in parte ci sono anche riuscito, ad oggi C# 4.0 con dynamic probabilmente offre anche qualche possibilità in più… resta il fatto che AutoMapper, ad esempio, non è minimamente applicabile in questo scenario perchè i DTO non vi servono proprio, avete un’interazione decisamente più ricca tra ViewModel e View.

.m