avrei voluto che il mio nuovo post trattasse ancora delle mie esperienze nel team di eXtreme Programming con cui sto lavorando ora, ma non sono stato capace di tenere un diario aggiornato. in realtà in parte è dovuto al fatto che ho trovato dei posti più adatti in cui confrontarmi su questi temi, come il journal interno al team e la mailing list di xp-italia. torno quindi a trattare un argomento tecnico, dato che è molto che non lo faccio.
stavo per rispondere a Jeremy , che è curioso di sapere quale variante di Model-View-Presenter sia maggiornente diffusa tra i suoi affezionati, indicando come nel mio caso si tratti del Passive View. però poi mi sono accorto che era uno spunto buono per un post, dato che al momento sono riuscito a far emergere dalla codebase del progetto che seguo ora una buona struttura per gestire il flusso dell'applicazione. dimenticavo, la novità è che sono tornato a lavorare in .NET: si tratta di un rich-client per PocketPc, quindi la piattaforma di riferimento è Compact Framework 2.0 SP2.
[piccola nota: il fatto che sia SP2 è fondamentale! sono incappato nel dover customizzare il comportamento di alcuni componenti grafici, partendo dall'override del metodo Paint(), cosa possibile solo dopo il secondo service pack poichè reso virtual]
primo tra i miei obiettivi era ottenere un elevato grado di testabilità del codice: il cucchiaino da caffè con cui riesco a svuotare il mare è ancora il Test-Driven Development, senza il quale mi sento perso e impaurito. per questo ho cercato di rendere testabile quante più responsabilità possibili, spostando il grosso della logica fouri dallo strato di GUI: la nuova dimora sono state quindi un insieme di comandi e i sempre più ricchi oggetti di dominio.
nell'immagine qui sopra ho mostrato la struttura delle classi che collaborano per realizzare uno dei casi d'uso dell'applicazione. le responsabilità principali (in grigetto) sono:
-
un controller, associato ad ogni operazione richiesta dell'utente. "conosce" la user interace in termini di una interfaccia, la view
-
una view, manipolata dal controller al termine di ogni operazione, per questo nell'interfaccia sono dichiarate alcune property. da notare che sono in sola scrittura
-
una form, che realizza la view utilizzando gli strumenti messi a disposizione dal namespace Windows.Form del Compact Framework, come un datagrid
-
un broker, che rappresenta l'accesso ai dati ed è in grado di costruire in modo opportuno gli oggetti di dominio. avendo scelto di scrivere a mano un OR/mapper, semplice e leggero, questa parte di codice utilizza ADO.NET e le clasi connection/command/datareader per il particolare provider scelto, nel mio caso SQL 2005 Compact Edition
-
un insieme di oggetti di dominio, custodi delle logiche principali del "mondo" in cui, si spera, l'applicazione tornerà utile
questa la distribuzione dei compiti. chiudo annotando alcune catteristiche e compromessi che ho scelto di seguire:
- nessuno stato è mantenuto sui controller, è lo strato di presentazione a memorizzarlo, in termini di oggetti di dominio.questo è emerso volendo testare separatamente e in modo semplice i diversi comportamenti, riducendo al minimo il setup dello stato iniziale: lo stato è inoltrato come parametro di ciascun metodo del controller
- le form sono sufficentemente stupide, così da non rischiare molto avendo scelto di non testarle. questo significa solo che al posto di una verifica automatizzata ho scelto di validarle manualmente: molte sono ugualmente le insidie nascoste, come la gestione di message box, alert, convalidare o annullare la chiusura della form e infine la navigazione tra form. sono tutte cose però comuni a ciascuna form, e quindi una volta trovata una buona implementazione riesco a riutilizzarla sfruttando l'ereditarietà e il pattern Layer Supertype
- anche la navigazione tra form è testata, sebbene i controller non conoscano nessuna form! ho messo in piedi un piccolo sistema, anche questo rigorosamente test-driven, per permettere ai controller di comunicare la "destinazione" in cui intendono ridirigere l'applicazione, in termini di interfacce (il target) e di parametri da inoltrare alla destinazione (gli arguments). sarà poi compito del "navigatore" tradurre ogni richiesta nella (ri)apertura della form corrispondente e (ri)agganciarla ai parametri. è una soluzione presa in prestito da un framework web per Java realizzato internamente dal team xp in cui lavoro, diventato poi un progetto open-source: Qixweb.
ultima nota, l'assenza nel Compact Framework del namespace System.Reflection.Emit ha reso impossibile utilizzare due degli strumenti che ho sempre dato per scontato: Rhino.Mocks per i mock objects (dinamici), a cui ho fatto fronte scrivendomeli a mano (statici), e il tanto amato NHibernate, che mi permesso però di rispolverare il buon vecchio SQL.
anche per oggi è tutto, spero di aver dato qualche spunto, così come fece con me janky un anno e mezzo fa ormai...
-papo-