Memento: Non ti scordar mai di me…
Tutto parte da qui, cioè fondamentalmente dalla necessità di snellire la realizzazione di un’applicazione fortemente basata su M-V-VM e dalla necessità, evidenziata qui e qui, di fornire una UX che sia decisamente consistente. In questa direzione, e al crescere dell’applicazione, risulta rapidamente evidente che vi è la necessità di snellire e automatizzare il maggior numero possibile di task: quindi, come scegliamo di utilizzare un ORM (nel mio caso NHibernate) ha molto senso scegliere di utilizzare un toolkit (nel mio caso il mio :-), ma anche Prism v2 o Caliburn) per realizzare tutte quelle parti che altrimenti cuberebbero e occuperebbero la stragrande maggioranza del tempo di sviluppo distogliendoci dal problema di business.
Se sviluppate applicazioni desktop vi rendete rapidamente conto di come la UX diventi alla svelta il nodo centrale e il succhia tempo per eccellenza, però scoprite anche che avete un potenziale vantaggio: la UX sta in “cima” all’applicazione ed è l’unica cosa a diretto contatto con l’utente è quindi il vostro “abito” ma è anche un vantaggioso punto prestazionale perchè li il collo di bottiglia è l’utente che ha un concetto di prestazioni decisamente diverso dal nostro (e per molti versi difficilmente comprensibile da un tecnico) ma sopratutto è tutto tranne che prestazionale (l’utente). La UX è quindi un area in cui soluzioni basate sull’automazione possono essere accettabilissime anche se comportano un possibile problema prestazionale, in questo caso il nostro giudice è fortunatamente diverso da uno Stopwatch ;-)
Memento
Il concetto di memento è decisamente importante per l’utente non molto per “noi”, noi inteso come parte core dell’applicazione, perchè dal punto di vista dei dati ha senso il tutto o niente (aka transazione) e non il qualcosa :-)
Il problema che però dobbiamo affrontare non è di facile soluzione. Come al solito partiamo con il guardarci in giro e in questo caso un ottimo candidato è un wordprocessor, quello che ci interessa è infatti essere in grado di supportare l’agognato ctrl+z/ctrl+y abbiamo però un inghippo, tanto per cambiare, noi abbiamo a che fare con un grafo eterogeneo di oggetti:
il nostro (aka l’utente) esegue una ricerca, visualizza la sua bella lista di risultati e sceglie una anagrafica cliente da modificare, cambia la ragione sociale, modifica l’indirizzo del sito web, aggiunge un indirizzo, modifica una delle condizioni di pagamento predefinite, elimina una coordinata bancaria… poi simpaticamente fa: ctrl+z, e giustamente si aspetta di fare roolback dell’ultima cosa modificata, e poi ancora e ancora, e ancora una volta ma poi si accorge che l’ultimo undo non era cosa da farsi e quindi ctrl+y => redo.in soldoni vuole questo:
vuole poter navigare uno stack di modifiche avanti e indietro senza limiti di sorta e, giustamente, si aspetta che le modifiche si propaghino al grafo anche perchè per lui non è un grafo ma è semplicemente la scheda dell’anagrafica cliente.
Ok, se caliamo la cosa su un singolo oggetto è concettualmente abbastanza semplice, magari tecnicamente no, ma non è questo il problema adesso, perchè possiamo immaginarci un banale Stack, interno all’oggetto, in cui l’oggetto stesso “impila” le modifiche mano a mano che vengono apportate e ne gestisce lo stato di Undo/Redo. La cosa si complica un po’ se propaghiamo il tutto ad un grafo perchè risulta sin da subito evidente che è impossibile gestire la cosa internamente agli oggetti pena la pedita di sequenzialità delle operazioni nel momento in queste “spannano” sull’intero grafo in maniera casuale.
Abbiamo quindi bisogno di un terzo attore, un qualcosa che esternamente faccia da repository per lo stack delle modifiche e a cui gli oggetti del grafo possano agganciarsi per eseguire il trace dello loro stato. E’ altrettanto evidente che questa cosa non possa in nessun modo essere implementata sulle nostre entità di dominio, ma debba essere delegata al mediatore che sta tra il dominio e lo screen di editing.
Per ora quindi quello che possiamo asserire è che ci servono:
- Un gestore superpartes delle modifiche che sia in grado di tenere traccia, anche temporalmente, di quello che succede;
- Un qualcosa che incapsuli, in maniera generica e condivisa dal gestore, il concetto di pending change;
- Un modo semplice per agganciare/sganciare un grafo di oggetti al gestore di cui sopra;
.m