Design does matter

October 3 2008

oggi a pranzo con qualche collega discutevamo di come risolvere un esercizio di logica (ad esempio, trovare l’intersezione tra array, e valutarne la complessità), che il nostro coach ognitanto ci lascia come stimolo per tenere allenata la mente, e per favorire il confronto tra tutti noi del team. io non ho ancora dato la mia di soluzione – non ci ho ancora lavorato – ma ho commentato dicendo qualcosa come “userei una qualche Collection, che di sicuro fornisce l’intersect”. spiazzante, lo so. e sbagliato, dato che non è quello lo scopo di questo tipo di esercizi.

il fatto è che, come ho poi spiegato, non nutro una particolare passione per gli algoritmi, il loro confronto, la loro ottimizzazione. ho anche aggiunto che (e forse questa è la cosa più interessante) se non avessi scoperto l’ingegneria del software, probabilmente non sarei mai diventato uno sviluppatore. durante gli anni di università infatti, ho sempre odiato programmare. se non fosse per l’amore della progettazione del software, del suo ciclo di vita, delle architetture, del paradigma ad oggetti, della complessità associata, sicuramente non avrei mai scelto di fare questo mestiere.

pausa, e respiro.

qualche tempo fa, chiaccherando con un mio amico-quasi-collega che provava a lusingarmi per le mie doti di programmatore, mi sono trovato a rispondergli dicendo che si sbagliava, e che anzi di fatto doveva considerarmi “un designer a cui tocca programmare”. ripensandoci, devo dire di aver proprio fatto centro – in vino veritas.

eppure, il mio lavoro quotidiano altro non è che scrivere codice. e lo adoro. com’è potuto accadere? in realtà non è difficile capirlo, almeno per me.

un primo cambiamento è arrivato quando, nel mio primo impiego come informatico (inizialmente un quasi sistemista), mi è stato chiesto di iniziare a sviluppare un prototipo di un sistema complesso (per me, per la mia esperienza, per la ridotta dimensione del gruppo di lavoro): una base di dati, un front-end web, un servizio di autenticazione, mettendo insieme software e hardware per un back-end di telefonia, agganciandosi infine ad un application server che fornisse un servizio di hosting. provando a documentarmi per capire come affrontare il progetto, in quel periodo è iniziato a nascere il mio amore per le architetture software. mi sono cimentato in letture come il classico “Desing-Patterns” della GoF (che nello stesso periodo stavo anche studiando in università), “Applying UML and Patterns” di Larman e “Patterns of Enterprise Application Architecture” di Fowler.

inevitabile, con l’entusiasmo arriva anche il fallimento: impossibile gestire la complessità senza avere feedback che quanto si sta disegnando funzioni realmente. ricordo benissimo lo sconforto di non riuscire a “far combaciare” tutti i pezzi, dopo averli pensati, nonostante la fatica e l’impegno messo per arrivare ad una soluzione soddisfacente. e ancora peggio, la difficoltà nel far adattare la struttura esistente ai continui cambi di requisiti. in fase di ricerca infatti, lavorando per un prototipo e non un prodotto, è lecito che il committente si svegli la mattina con una nuova geniale idea e ti chieda “e se facessimo così e così? e magari dopo potremmo anche attaccarci un servizio XYZ, che ne dici? proviamo?”.

il secondo grande cambiamento per me poi è stato quando ho scoperto il testing automatico (anche questo visto per la prima volta in università). il vero traguardo però è stato imparare a sviluppare guidato dal testing; col tempo, facendo un sacco di errori, partendo dall’usare test di integrazione per grandi pezzi dell’applicazione (“ma come faccio a testare ancora più in dettaglio?”) ho imparato a focalizzarmi su test unitari di singole piccole responsabilità. il Test-Driven Development mi ha insegnato che è possibile far evolvere il disegno partendo da una situazione più semplice e aggiungendo complessità di volta in volta: si chiama design evolutivo e incrementale. ci ho dedicato (a posteriori, direi con scarso successo) la mia tesi di laurea.

l’ultimo traguardo è sicuramente stato quando, infine, sono riuscito a fare mio il concetto che il codice sorgente di un’applicazione è il design del sistema. è stato grazie all’articolo di Jack Reeves “What is software design?”, che affronta il tema in dettaglio e in modo davvero chiaro (è riportato anche in appendice nello splendido “Agile Principles, Patterns and Practices in C#” di Robert Martin). leggendo quell’articolo, ho finalmente avuto chiaro qualcosa a cui da sempre cercavo di dare forma, senza riuscirci: nel software, un’idea e valida se funziona, altrimenti rimane solo un’idea. e il nostro mestiere è davvero bello perchè ci permette di provare se le nostre idee sono valide: disegno e codifica non sono altro che due momenti diversi di uno stesso processo creativo. Kent Beck, nel suo “Smalltalk Best Practice Patterns” dice:

“To me, development consists of two process that feed each other. First you figure out what you want the computer to do. Then you instruct it to do it. Trying to write those instructions inevitably changes what you want the computer to do, and so it goes.
In this model, coding isn’t the poor handmaiden of design or analysis. Coding is where your fuzzy comfortable ideas awaken in the harsh dawn of reality. It is where you learn what your computer can do. If you stop coding, you stop learning.”

come progetto il software? discuto, disegno qualcosa su carta, scrivo un test. come mi rendo conto se l’idea funziona? scrivo tutto e solo il codice che serve a far passare il test.
e poi semplifico, rifattorizzando.

questa settimana è arrivato un nuovo tassello nel mosaico dell’applicazione Java che il mio team sta sviluppando in questo periodo. è ormai in code complete la user-story che ho preso in carico, che si occupa di realizzare l’aggancio ad una coda, realizzata da sviluppatori di un altro team interno, e di supportare il formato dei dati concordato con loro. dato che per me rappresentava la possibilità di fare esperienza con una tecnologia che conosco ancora poco, lo standard Java Message Service (JMS), mi sono subito proposto, a inizio iterazione, per prendere io la carta.

la nostra parte di applicazione è particolare rispetto a quanto stanno sviluppando gli altri team sul progetto, dato che si tratta di un motore di regole per elaborare dati provenienti da diverse sorgenti, e notificare via posta elettronica agli utenti gli eventi che corrispondo ai criteri da loro scelti. è un dominio molto ricco, in cui la parte di infrastruttura è secondaria.

il porre in secondo piano l’aspetto di infrastruttura è stata, oltre che una scelta, un’esigenza dettata da requisiti non funzionali ancora in parte incompleti: quali sorgenti dati usare, quali standard usare, o in alcuni casi anche “chi” realizzerà determinati sistemi esterni. per i servizi offerti invece dagli altri team interni, volevamo renderci quanto più indipendenti dalla loro pianificazione, riducendo cioè al minimo i vincoli temporali inter-team.

queste condizioni hanno quindi favorito la nascita, in modo incrementale, di un’architettura in cui al centro si pone un Domain Model indipendente, slegato quanto più possibile dagli aspetti di infrastruttura: ogni volta che una storia richiedeva l’accesso ad un servizio (anche se non ancora definito) aggiungevamo nel dominio un’interfaccia per disaccoppiare i due sistemi – un provider, broker o sender – nell’ottica di realizzare in seguito un adattatore al servizio, quando questo fosse stato pronto. si tratta dell’architettura esagonale descritta da Cockburn.

per poter disaccoppiare da tutto il cuore del sistema, ad un certo punto abbiamo trovato naturale applicare il principio di inversione delle dipendenze (Dependency-Inversion Principle), in modo che la logica di alto livello (domain) fosse slegata dai dettagli di implementazione (adapters e infrastructure) e che questi dettagli dipendessero invece da un’astrazione (le interfacce, dichiarate all’interno del domain). rispetto ad uno schema di layering canonico, in cui il livello applicativo dipende da quello di infrastruttura, abbiamo ottenuto una struttura in cui il layer applicativo non dipende da nulla, ma sono invece UI e infrastruttura a dipendere dallo strato applicativo.

la forza che ha guidato l’emergere di questa struttura è stata, nuovamente, la necessità di rendere il sistema testabile in isolamento. la realizzazione di ciascuna storia è stata così guidata da una ricca suite di test:

  • test unitari delle classi di dominio e del motore di regole, usando test-doubles (fake, stub o mock) delle interfacce dei servizi
  • test unitari degli adattatori (quando possibile), usando test-doubles delle API esterne
  • test di integrazione degli adattatori, usando istanze in memoria dei servizi
  • test di accettazione, usando adattatori e servizi in memoria

[ sulla terminologia usata – dummy, fake, stub e mock – c’è ancora molta confusione in letteratura, per questo uso il termine più generico di test-double. io in genere faccio riferimento al lavoro di riorganizzazzione di Meszaros. ad esempio, un fake è una implementazione alternativa di una interfaccia (ma dal comportamento consistente), usata solo a scopi di test, come il classico Gateway al database realizzato con una hashmap in memoria. uno stub invece è un oggetto programmabile, che altrimenti implementa un comportamento di default. un mock, infine, realizza l’endo-testing o testing delle interazioni, con cui verificare le interazioni tra oggetti. ]

per i test di integrazione ci siamo affidati a implementazioni leggere dei vari servizi, realizzate in memoria, avviabili programmaticamente in fase di setUp e disattivati al termine della suite durante il tearDown. finora, siamo riusciti a collezionare un buon numero di tool open-source, ad esempio:

  • come web-container, l’ultra leggero e versatile Jetty, abbandonando il ServletContainer di HttpUnit, ma solo dopo esserci scontrati con alcuni suoi limiti (primo tra tutti, il content-type a text/plain)
  • come server SMTP, abbiamo scelto Dumbster, in ascolto sulla canonica porta 25 locale
  • come broker JMS, si è dimostrato davvero ottimo ActiveMQ, che offre code in memoria non persistenti e visibili da tutta la virtual machine (url del tipo vm://localhost), oppure accessibili anche da client esterni (url del tipo tcp://localhost)
  • come dataSource, non avendo ancora a disposizione un sistema di deploy automatico di schemi e stored-procedure (ma ci stiamo lavorando!), abbiamo scelto di usare direttamente l’ambiente di test condiviso, affidandoci però al supporto di transazionalità nei test offerto da Spring

il punto forza di questo approcio, a cui si aggiungono Dependency-Injection (ottenuta come effetto collaterale del TDD) e uso degli standard (come JMS, servlet-container, JDBC e STMP), ci ha inoltre permesso di ottenere un ulteriore enorme risultato: realizzare sulle macchine di sviluppo delle demo al cliente andando ad agganciarci alle istanze reali dei servizi. scrivendo solo una diversa configurazione – breve e localizzata – grazie al supporto di IoC fornita da Spring abbiamo potuto usare un vero application server, un vero broker JMS, un vero server SMTP e un vero database.

la nostra particolare situazione (requisiti ancora parziali sull’integrazione ai servizi esterni) e, non lo nego, una grossa flessibilità da parte dei customer interni, ci hanno permesso di consegnare e farci approvare tutte le user-stories sviluppato fino ad ora, nonostante manchino ancora intere parti di integrazione (DAO esterni, alcuni servizi SOAP e l’infrastruttura di Single Sign-On).

per questo, oltre che estremamente interessante, divertente e pieno di sfide, non posso che considerare finora questo progetto un successo, sia per il cliente che si è visto un po’ alla volta consegnare pezzettini di funzionalità, sia per il team, che ha dato alla luce una architettura flessibile, in modo del tutto incrementale, usando come ferri del mestiere testabilità, disaccopiamento e semplicità.

Feedback, feedback, feedback!

September 15 2008

non è un segreto, sono test-infected. questo significa che prima di iniziare a scrivere del codice, il mio istinto (o malattia) mi porta a partire da un test automatico. ma non è solo questo: l’approcio infatti mi si rivela utile in ogni situazione in cui ci sia da scoprire come fare qualcosa di nuovo.

Test di esplorazione

questa settimana, ad esempio, ho esplorato una libreria di serializzazione/deserializzazione XML, partendo da un test unitario: dato un frammento XML, mi aspetto un oggetto deserializzato di un certo tipo e in certo stato, e viceversa. aiutato da qualche stampa a console di corredo, mi sono fatto guidare dalle barre verdi: si parte con un caso semplice, un oggetto vuoto, poi aggiungo una collezione di oggetti, infine decido un mapping custom tra attributi e classi. in due pomodori di pair-programming siamo riusciti a farci una chiara idea delle funzionalità offerte, e devo dire che anche la mia compagna di pair, nuova alla metodologia, è rimasta davvero soddisfatta del risultato ottenuto in così poco tempo.

nel tempo libero, ho anche iniziato studiare un nuovo linguaggio dinamico, per esplorare come rendere espressiva una DSL per test di accettazione che voglio scrivere. la prima cosa che ho cercato nella documentazione del linguaggio è come scrivere un test automatico. sono partito scrivendo qualche semplice asserzione sullo stato del sistema dopo aver eseguito un breve frammento di DSL. la prima implementazione poi si è occupata di far passare il test, senza usare nessuna feature del linguaggio: solo costruttori, chiamate a metodi e passaggio di parametri. dopo la prima barra verde, ho potuto iniziare a rifattorizzare il frammento introducendo blocchi e named-parameters. prossimo passo saranno le extensions e i builder, e magari poi imparerò qualcosa pure di meta-programming.

[ è lo stesso approcio che ho seguito qualche anno fa quando ho voluto imparare le nuove feature di Java, venendo da .NET: con una manciata di test unitari ho capito il funzionamento di generics, varargs e foreach. niente di così strano, ho seplicemente tradotto in asserzioni quello che, su ogni manuale di programmazione, viene tipicamente messo in una stampa a console dentro un main. in questo modo però ho reso ripetibili e deterministici gli esiti delle mie esplorazioni. ]

Piccoli test crescono

questo venerdì la retrospettiva di fine iterazione, nel progetto in cui sto lavorando sia come mentore che come sviluppatore, mi ha fatto riflettere e mi sono accorto di quanto incisivo, seppur nascosto, sia stato l’apporto che i miei colleghi ed io siamo riusciti a dare al team che stiamo seguendo: nell’arco di qualche mese siamo passati da “test automatici, questi sconosciuti” a una sana discussione sull’esigenza di introdurre, in aggiunta a test unitari e di integrazione, una nuova famiglia di test funzionali; a come accelerare l’esecuzione dell’intera suite di test durante la fase di build; a come automatizzare la creazione di una base di dati con dati di test reali; e così via.

in tutto questo, mi reso conto che uno dei contributi più validi che ho potuto dare al team è stato aiutare a trovare un modo per testare nuove parti del sistema. tipicamente, mi accade di affiancarmi a sviluppatori che sono un po’ scettici quando dico loro “partiamo scrivendo un test”. ma un po’ alla volta, i risultati sono arrivati.

uno dei primi task per il quale mi sono offerto è stato introdurre un modo per testare le view della webapp, scritte con un template engine che non conoscevo. sono partito con uno spike per capire la sintassi del linguaggio di markup dei template e come eseguire il rendering di una view. uno sguardo alla documentazione on-line, e via con il primo test: dato un file con “Hello, world!”, avvio l’engine, processo il file, e mi attendo come risultato la stringa con il canonico saluto a tutto il mondo. alla prima barra verde, certo non immediata, la strada era ormai avviata, e via quindi con bindind di variabili, espressioni condizionali, cicli e tutto il resto. abbiamo dovuto accettare qualche compromesso (come bypassare il motore di localizzazione), ma il risultato del task è stata una comoda BaseTestForTemplate. e così, dopo un paio di mesi, la codebase ora contiene una quarantina di preziosissime classi di test, una per ciascuna singola view, scritte da tutto il team.

il vantaggio più grosso che questo ha avuto, per me, è stata la tranquillità con cui, da allora, ho potuto mostrare ad alcuni sviluppatori come svuotare di logiche applicative i template delle viste, spostandole sugli oggetti di dominio e unit-testandole separatamente. il ciclo di feedback, per sapere se una certa fuzionalità fosse corretta è passato da decine di minuti – necessari per fare un nuovo deploy, inserire i dati necessari e navigare l’applicazione – a qualche minuto, giusto il tempo di aggiungere qualche setup e una nuova asserzione.

il passo successivo è stato provare a rimuovere del tutto la necessità di fare deploy e verifiche manuali del funzionamento dell’applicazione. un primo risultato c’è stato quando, grazie al supporto di opportune librerie, ho introdotto un test di integrazione HTTP in grado di caricare in memoria il contesto della webapp e verificare che tutto, dalla view all’accesso ai dati, fosse interconnesso correttamente. più volte infatti capitava che, involontariamente, venisse introdotto qualche errore nella configurazione XML dell’applicazione (in particolare, la parte realtiva al framework di IoC), e questo si rendeva visibile solo provando ad avviare l’applicazione in locale. non è stato facile, ma il risultato è stato soddisfacente e ora siamo in grado di accorgerci durante la build di eventuali errori di mapping o configurazione.

una cosa che noto spesso è che molti sviluppatori non riconoscono di essere loro stessi abituati a farsi guidare dal feedback (che è il valore che guida il TDD). in una sessione di pair-programming mi sono affiancato come mentore ad un ragazzo che doveva realizzare una stored procedure per selezionare i risultati di una ricerca. il suo approcio consisteva nello scrivere il codice SQL, compilare la stored-procedure, inserire alcuni dati di prova ed eseguire una ricerca, e verificare che i dati ottenuti fossero corretti. ovviamente, questa procedura ha lo svantaggio di essere lunga e ripetitiva, quindi soggetta a possibili errori (sopratutto quando ti ritrovi a fare continuamente le stesse operazioni e sei stressato). la mia prima domanda è stata “perchè non proviamo a scrivere un test?”.

ho scarsissima esperienza con le stored-procedure, e non conosco affatto la sintassi proprietaria SQL del DBMS che stiamo usando. mi serviva quindi “un punto fermo” su cui fare affidamento, e un test si prestava benissimo. così, con non troppa fatica, abbiamo scritto un test di integrazione che, dopo aver aperto una connessione al database, esegue una chiamata alla stored-procedure. barra rossa: la stored-procedure non esiste. bene! significa che ora ci possiamo dedicare a scrivere il codice SQL. dopo pochi minuti, arriva la prima barra verde. passo successivo è l’inserimento di alcuni dati di prova, con una coppia di INSERT/DELETE nel setup e teardown del test. nuova asserzione e nuova barra rossa. un po’ di lavoro con SQL ed ecco che la barra torna verde. e sopratutto inizio a vedere soddisfatto il mio compagno di pair.

qualche giorno dopo, insieme ad un altro sviluppatore, è arrivato l’ultimo tassello: l’introduzione di transazionalità. ci siamo arrivati in modo incrementale, anche perchè ha richiesto qualche modifica per permettere a test e applicazione di condividere la stessa transazione (e devo dire che in questo caso il framework di IoC usato è stato davvero utile).

se guardo indietro quindi, vedo come in questi primi mesi sul progetto il mio più grande contributo sia stato aiutare il team a scoprire come testare le parti di sistema più complicate. è per me una grossa soddisfazione veder crescere, di pari passo con l’applicazione, la suite di test automatici, a più livelli. oppure sentirmi chiedere “mi dai una mano a testare questa parte?”.

o ancora, sentire allo standup-meeting che uno sviluppatore ha creato una classe per testare, in modo automatico, equals e hashcode. sì, decisamente sono test-infected… e pure contagioso!

ah, e la validazione javascript? ok, questa la racconto un’altra volta!

no, non è un post in inglese. il titolo si riferisce alla sessione che io e il mio collega Tommaso abbiamo tenuto lo scorso giovedì per i ragazzi della ESSAP (European Summer School on Agile Programming) presso Villa Toeplitz a Varese. è stata un’esperienza stupenda, sia per il fatto che ci siamo tutti divertiti moltissimo, sia per l’interesse che i partecipanti (un po’ assonnati per il post pranzo!) hanno dimostrato verso i temi esposti.

putroppo, questa era la prima volta che la sessione prendeva corpo, e quindi sicuramente non siamo stati efficaci quanto speravamo: l’argomento è insidioso perchè offre il fianco a lunghe discussioni puramente tecniche, errore in cui siamo caduti anche noi. il pubblico, una ventina di ragazzi da tutta europa, era molto eterogeneo, chi vedeva per la prima volta le tematiche legate ai metodi Agili, accanto a chi invece già adotta alcuni principi e pratiche nel proprio lavoro ed era lì per affinarli o capire come farli meglio funzionare.

abbiamo scelto di dividere la sessione in due parti. prima un’introduzione al concetto di iterazione e test di accettazione scritti da/con il cliente, quali possibili forme usare per scriverli e quali tool esistono a supporto. abbiamo descritto in dettaglio il funzionamento di FIT e FitNesse e mostrato le principali fixtures usate, quelle di FIT e alcune di FitLibrary.

nella seconda parte della sessione invece abbiamo fatto un esercizio, partendo da un esempio scritto da noi (una variazione di quello che i ragazzi avevano già visto in altre sessioni): un semplice gioco di ruolo per il quale abbiamo realizzato una decina di user stories, corredandole di test unitari e test di accettazione. quindi abbiamo eletto a customer uno dei ragazzi nel pubblico, chiesto a lui di inventarsi la prossima user story e iniziato a descriverla in forma testuale su una lavagna. prendendo spunto da quanto già fatto per le altre storie, abbiamo poi scritto un test di accettazione, sempre su lavagna, e tradotto poi in forma tabellare.

il resto del pomeriggio (troppo breve!) i ragazzi hanno così lavorato in coppie cercando di implementare la storia richiesta, partendo dalla traduzione in FitNesse del test di accettazione, collezzionando una bella “barra rossa”, doverosa a inizio iterazione. hanno poi iniziato a decidere dove porre le responsabilità richieste, e mi pare che tutti abbiano deciso di assegnarle a oggetti già esistenti, iniziando così a scrivere i test unitari, a vederli fallire uno ad uno, per poi modificare il sistema e godersi il premio di una barra verde!

anche se l’esempio era molto semplice e le modifiche da aggiungere davvero limitate, ho notato la soddisfazione sopratutto dei ragazzi nuovi alle tematiche ad ogni esecuzione con successo dei test unitari. è quello che in eXtreme Programming viene detto il valore del feedback, assolutamente fondamentale.

prima di andare a casa, tutte le coppie sono riuscite a chiudere la micro-iterazione, verificando che il loro lavoro fosse corretto e concluso, vedendo passare con successo anche il test di accettazione. qualche coppia, avendo finito in anticipo, ha iniziato a lavorare su una seconda carta, inventata al momento. mi spiace solo che l’abbiano scelta loro invece di coinvolgere il “customer-per-un-giorno”, ma è comprensibile dato l’entusiasmo e la brama di giocare col la pratica e lo strumento.

a me non resta che ringraziare tutti: gli organizzatori (primo tra tutti il mio coach Matteo) per l’occasione concessa e i partecipanti per le ottime domande a cui abbiamo cercato di rispondere in modo conciso. da parte mia, è stata una giornata splendida, mi ha fatto crescere come “speaker”, ruolo per me nuovo, ho avuto anche l’occasione per conoscere di persona alcuni nomi “digitali” (come Luka), e si è conclusa con uno ottimo social-dinner!

il materiale della sessione sarà presto disponibile sul sito della ESSAP, nel frattempo è raggiungibile qui:

le nostre gesta sono anche state immortalate! più le rivedo e più sorrido. in ogni caso, sono qui, qui, qui e qui (peccato non si veda la scritta sul mio tesserino “Jacopo – xtreme guitarist“, nascosta dalla maglia rosso acceso!).

grazie ancora a tutti, spero la scuola possa farsi conoscere ancora di più, magari nelle prossime edizioni ci troveremo anche molti della comunità ugidotnet!

a presto.
-papo

segnalo questo annuncio di lavoro, che qualcuno avrà già letto sulla mailing list di extreme-programming italia.

il mio team vuole allargarsi!
siamo alla ricerca di giovani agilisti nella zona di milano, chiunque fosse interessato può contattare direttamente Matteo, che attualmente ricopre il ruolo di coach.

spero di poter incontrare presto qualcuno di voi!

se c’è una cosa che mi dispiace davvero è aver permesso che il mio blog rimanesse in silenzio per così tanto tempo. è passata una vita dal mio ultimo post, ma sopratutto tante sono le cose successe. occasione, che cerco oggi di cogliere, è un particolare anniversario che cade questa settimana: un anno da quando ho iniziato a lavorare come eXtreme Programmers, un anno che vivo da solo, un anno in una città come milano.

il 2008 si è aperto con una grossa novità, una grandissima occasione: si è conclusa la collaborazione che mi ha visto impegnato per gran parte dello scorso anno ed è iniziato il mio nuvo impiego, a tempo indeterminato, per una piccola ma attivissima realtà nel panorama Agile italiano. nello stesso tempo, mi sono impegnato a tempo pieno come membro dello XP User Group locale, organizzando alcuni incontri sia nella vecchia azienda che in quella nuova. con i ragazzi dello xpug abbiamo anche partecipato alla scorsa edizione dell’Agile Day, in cui ho avuto modo di dare un volto a mille dei nomi conosciuti in rete.

un anno, tempo di tirare le somme. mi vergogno quasi un po’ a dirlo, questo anno appena passato è stato per me davvero importante: ho imparato un mestiere, il mestiere che mi sono scelto e che mi appassione ogni giorno di più, affiancando dei veri professionisti e toccando con mano il valore dell’approcio Agile allo sviluppo del software. e sono cresciuto sopratutto come persona, imparando a vivere fuori casa, ad organizzarmi la vita.

la novità più grossa è che mi è stata offerta la possibilità di fare mentoring. da oltre due mesi infatti sto seguendo un team di una grossa banca italiana nel suo percorso di avviamento all’agilità. particolarmente interessante è la formula scelta: un team misto, in cui alterniamo attività di formazione ad altre di sviluppo puro. tutto questo è decisamente stimolante, passare in così poco tempo da apprendista stregone a sciamano! la portata della responsabilità è notevole, ma è altrettanto grande la soddisfazione nel sentirsi dire, da sviluppatori che fanno questo mestiere da anni, “grazie di avermi fatto scrivere tutti questi test”, o nel vedere riconosciuto il valore del customer on-site e della continua comunicazione.

questo è quanto, non posso che considerarmi soddisfatto dei mie miseri 27 anni. auguro a molti miei coetanei che vengano loro offerte le stesse opportunità che ho ricevuto io, e che sappiano farne buon uso!

dimenticavo l’ultima novità: sto scrivendo da un bellissimo MacBook Pro!

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.

passive-view

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:

  1. 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
  2. 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
  3. 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…