Extreme Programming http://blogs.ugidotnet.org/antonioganci/category/Extreme Programming.aspx Extreme Programming it-IT Antonio Ganci Subtext Version 2.6.0.0 Pensare ad oggetti http://blogs.ugidotnet.org/antonioganci/archive/2012/01/12/pensare-ad-oggetti.aspx <p> Ne avevo già parlato in un precedente <a href="http://blogs.ugidotnet.org/AntonioGanci/archive/2010/07/23/imparare-a-pensare-ad-oggetti.aspx">post</a>, ma provo ad illustrare altri aspetti che avevo ignorato. </p> <p> Una delle cose che viene data per scontato in XP è che si sappia pensare ad oggetti che è un prerequisito per il simple design. Ma cosa significa veramente? </p> <p> Nella programmazione tradizionale o formale un oggetto è dato dai suoi dati (attributi) e i metodi che agiscono su tali dati. Questo però porta ad un esplosione del numero di classi perché basta un solo dato diverso e devo creare una nuova classe. </p> <p> L'idea centrale del pensare ad oggetti sono i <b>comportamenti</b> cioè la decomposizione di un problema avviene individuando i comportamenti e assegnandoli agli oggetti. </p> <p> Ad esempio: prendiamo una tigre e un gatto nella programmazione formale ho una classe unica e due istanze diverse con i valori degli attributi diversi perché la tigre e il gatto hanno le stesse caratteristiche. Se pensiamo ad oggetti invece sono due classi diverse in quanto dalla tigre mi aspetto che mi aggredisca mentre un gatto è un animale domestico e quindi hanno diversi comportamenti. </p> <p> <b>Un modo utile per scoprire gli oggetti adatti a risolvere un problema è quello della metafora</b>, cioè cerco di capire se esiste un qualcosa di analogo nel mondo reale che si mappa con il mio problema. Bisogna tenere presente che la metafora è un modello del problema e quindi ci possono essere delle differenze. </p> <p> Ad esempio supponiamo di voler realizzare un sito per cercare un volo tra due destinazioni. Una metafora potrebbe essere quella dell'agenzia di viaggio a cui comunico dove voglio andare, in che data e mi viene fornito un catalogo con tutte le informazioni per poter scegliere il volo. </p> <p> Seguendo la metafora posso iniziare a disegnare l'oggetto agenzia di viaggio a cui mando il messaggio forniscimi il catalogo e gli passo una richiesta. A quel punto il risultato del messaggio puo' essere l'oggetto catalogo che contiene un elenco delle offerte e così via. </p> <p> Il punto cruciale è provare a fare una simulazione mentale o facendosi aiutare dai colleghi dell'interazione tra i vari oggetti per capire se il modello è adatto a risolvere la storia da realizzare. Quindi si ragiona nello spazio del problema o dominio e inizialmente si ignora la soluzione del problema, cioè la sua implementazione. </p> <p> Una volta individuati gli oggetti si può inziare l'implementazione utilizzando il TDD; ricordandosi che non sempre ad un oggetto di dominio corrisponde una classe, a volte puo' essere più di una a volte nessuna come nel caso in cui avessi creato, durante l'analisi, l'oggetto utente che fa la richiesta. </p> <p> Per approfondire l'argomento consiglio la lettura del libro <a href="http://www.amazon.com/Object-Thinking-DV-Microsoft-Professional-David/dp/0735619654">Object Thinking</a> di David West (ringrazio <a href="http://matteo.vaccari.name/blog/archives/675">Matteo</a> per la segnalazione). Mentre per gli effetti sulla produttività usando il TDD consiglio la lettura del post <a href="http://blog.8thlight.com/uncle-bob/2012/01/11/Flipping-the-Bit.html">Flipping the Bit</a> di Zio Bob. </p><img src="http://blogs.ugidotnet.org/antonioganci/aggbug/100696.aspx" width="1" height="1" /> Antonio Ganci http://blogs.ugidotnet.org/antonioganci/archive/2012/01/12/pensare-ad-oggetti.aspx Thu, 12 Jan 2012 20:08:46 GMT http://blogs.ugidotnet.org/antonioganci/archive/2012/01/12/pensare-ad-oggetti.aspx#feedback http://blogs.ugidotnet.org/antonioganci/comments/commentRss/100696.aspx http://blogs.ugidotnet.org/antonioganci/services/trackbacks/100696.aspx Le difficoltà nell'apprendere la pratica del TDD http://blogs.ugidotnet.org/antonioganci/archive/2011/12/20/le-difficolta-nellapprendere-la-pratica-del-tdd.aspx <p> Una delle pratiche più invasive di extreme programming oltre al pair programming è il TDD (Test Driven Development) ed è anche la più difficile da padroneggiare. In questo post cercherò di analizzare i motivi, fornendo alcuni spunti su come superare le difficoltà. </p> <p> Le cose più difficili da accettare soprattutto se si ha già una certa esperienza è il fare emergenere il design dai test. Questo implica di <b>non anticipare eventuali feature successive o test successivi e scrivere il codice minimo indispensabile per fare passare il test appena scritto</b>. Nella fase di refactoring poi si toglieranno tutti gli smell introdotti a partire dal più importante che è la duplicazione. </p> <p> Quindi non basta scrivere i test prima, magari solo per realizzare un'idea di design che ho già deciso, ma significa <i>sorprendersi</i> del risultato ottenuto. </p> <p> Una grossa difficoltà è capire quali test scrivere all'inizio e quindi occorre partire molto lentamente, facendo piccoli passi tra un test e il successivo in modo da familiarizzare con la tecnica. </p> <p> Spesso nell'affrontare il design in questa maniera ci si accorge di avere delle carenze nei concetti di OOP oppure nel riconoscere gli smell e quindi è importante studiare molto bene questi argomenti prima di iniziare. </p> <p> Bisogna accettare anche il fatto che nel percorso dell'apprendimento si possa sbagliare e il dover rifare la stessa cosa più volte fino ad arrivare ad un risultato soddisfacente. </p> <p> E' possibile che per ottenere una barra verde del test appena codificato si debba scrivere molto codice, questo è un segno che si è fatto un passo troppo lungo. Una buona soluzione potrebbe essere quella di revertare il codice e riflettere su come fare un passo più piccolo per arrivare al risultato. Ricordiamoci inoltre di integrare dopo ogni refactoring successivo ad una barra verde per rendere l'operazione più veloce ed indolore possibile. </p> <p> La disciplina è un alleato potente perché, soprattutto all'inizio, la tendenza ad abbandonare la pratica è molto forte, in quanto cosa molta fatica e si ha la sensazione di perdere tempo e di andare lentamente. </p> <p> Partire da una codebase con molto codice legacy introduce un'ulteriore difficoltà, quindi all'inizio conviene provare ad implementare una feature da zero limitando il più possibile l'uso del codice esistente. </p> <p> Ricordiamoci infine che il <b>nostro obiettivo è rilsolvere problemi</b>. Un codice di qualità è il mezzo e le feature sono il risultato del nostro lavoro. Su questo punto consiglio la visione di del video <a href="http://blip.tv/clojure/hammock-driven-development-4475586">Hammock-driven Development</a> </p><img src="http://blogs.ugidotnet.org/antonioganci/aggbug/100641.aspx" width="1" height="1" /> Antonio Ganci http://blogs.ugidotnet.org/antonioganci/archive/2011/12/20/le-difficolta-nellapprendere-la-pratica-del-tdd.aspx Tue, 20 Dec 2011 22:42:32 GMT http://blogs.ugidotnet.org/antonioganci/archive/2011/12/20/le-difficolta-nellapprendere-la-pratica-del-tdd.aspx#feedback 2 http://blogs.ugidotnet.org/antonioganci/comments/commentRss/100641.aspx http://blogs.ugidotnet.org/antonioganci/services/trackbacks/100641.aspx Mettere alla prova il design della propria codebase http://blogs.ugidotnet.org/antonioganci/archive/2011/11/23/mettere-alla-prova-il-design-della-propria-codebase.aspx <p> Il <a href="http://varvello.blogspot.com/">coach</a> del mio <a href="http://teamnautilus.wordpress.com/">team</a> xp di nome Nautilus ci ha proposto un'interessante esercizio per mettere alla prova la qualità della nostra codebase. </p> <p> Scrivere il test dello scenario che si vuole sviluppare come lo vorremmo, ignorando l'attuale architettura, misurando il tempo impiegato. </p> <p> Provare poi a scriverlo usando i nostri oggetti misurando nuovamente il tempo impiegato. </p> <p> Nel caso specifico la coppia, in quanto sviluppiamo in pair, ha impiegato 2 minuti a scrivere il test per il primo caso e tre <a href="http://www.pomodorotechnique.com/">pomodori</a> (circa un ora e mezza) nel secondo caso. </p> <p> La differenza tra i due tempi indica quanto la nostra codebase è lontana dalla qualità che vorremmo ottenere. </p> <p> Questa è l'essenza del TDD, cioè usare il test per comunicare come ci aspettiamo di utilizzare i nostri oggetti ed è anche un indicatore di quale sia il debito tecnico attualmente presente. </p> <p> Non solo: ci suggerisce anche come rifattorizzare il codice per migliorarne la comunicatività e chiarezza. </p><img src="http://blogs.ugidotnet.org/antonioganci/aggbug/100549.aspx" width="1" height="1" /> Antonio Ganci http://blogs.ugidotnet.org/antonioganci/archive/2011/11/23/mettere-alla-prova-il-design-della-propria-codebase.aspx Wed, 23 Nov 2011 19:42:03 GMT http://blogs.ugidotnet.org/antonioganci/archive/2011/11/23/mettere-alla-prova-il-design-della-propria-codebase.aspx#feedback 9 http://blogs.ugidotnet.org/antonioganci/comments/commentRss/100549.aspx http://blogs.ugidotnet.org/antonioganci/services/trackbacks/100549.aspx Studiare le basi della programmazione ad oggetti - seconda parte http://blogs.ugidotnet.org/antonioganci/archive/2010/11/23/studiare-le-basi-della-programmazione-ad-oggetti-seconda-parte.aspx <p> Continua l'elenco dal <a href="http://blogs.ugidotnet.org/AntonioGanci/archive/2010/11/11/studiare-le-basi-della-programmazione-ad-oggetti.aspx">post precedente</a> </p> <p><strong>Iterazione 7</strong></p> <p> Dal libro <a href="http://en.wikipedia.org/wiki/Design_Patterns">Design Patterns</a>: </p> <ul> <li>Preface to Book</li> <li>Introduction</li> <li>What is a Design Pattern?</li> <li>Design Patterns in Smalltalk MVC</li> <li>Describing Design Patterns</li> <li>Introduzione Creational patterns</li> <li>Factory Method (pag. 107)</li> </ul> <p> <a href="http://books.google.com/books?id=G8EL4H4vf7UC&amp;printsec=frontcover&amp;dq=extreme+programming+explained&amp;source=bl&amp;ots=j7BDwomXAk&amp;sig=LKzNHdze9dBVLlkzM8nXQb-rg2I&amp;hl=en&amp;ei=C73rTKbPAczrsgaw-LyVDw&amp;sa=X&amp;oi=book_result&amp;ct=result&amp;resnum=4&amp;ved=0CDoQ6AEwAw#v=onepage&amp;q&amp;f=false">Extreme programming explained: embrace change</a> - Beck Cap 5 e Cap 6 </p> <p> <a href="http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd">The Three Laws of TDD</a> - Bob Martin </p> <p> OCP sul libro <a href="http://www.amazon.com/Principles-Patterns-Practices-Robert-Martin/dp/0131857258">Agile Software Development, Principles, Patterns, and Practices</a> </p> <p><strong>Iterazione 8</strong></p> <p> Da libro <a href="http://martinfowler.com/books.html#refactoring">Refactoring</a> di Fowler: </p> <ul> <li>Introduzione ai Composing Methods (cap 6)</li> <li>Extract method (pag 110)</li> <li>Replace temp with query (pag 120)</li> <li>Replace method with method object (pag 135)</li> </ul> <p> Buon studio. </p><img src="http://blogs.ugidotnet.org/antonioganci/aggbug/99503.aspx" width="1" height="1" /> Antonio Ganci http://blogs.ugidotnet.org/antonioganci/archive/2010/11/23/studiare-le-basi-della-programmazione-ad-oggetti-seconda-parte.aspx Tue, 23 Nov 2010 15:30:30 GMT http://blogs.ugidotnet.org/antonioganci/archive/2010/11/23/studiare-le-basi-della-programmazione-ad-oggetti-seconda-parte.aspx#feedback http://blogs.ugidotnet.org/antonioganci/comments/commentRss/99503.aspx http://blogs.ugidotnet.org/antonioganci/services/trackbacks/99503.aspx Studiare le basi della programmazione ad oggetti http://blogs.ugidotnet.org/antonioganci/archive/2010/11/11/studiare-le-basi-della-programmazione-ad-oggetti.aspx <p> Vorrei condivere il percorso di studio del <a href="http://www.7pixel.it/ITA/Chi_Siamo__Gruppo_7Pixel.asp">team xp</a> per approfondire la conoscenza della programmazione ad oggetti e del ciclo di sviluppo software. Il percorso è utile sia per chi non conosce l'argomento e vuole apprendere le tecniche di sviluppo seguendo il paradigma OOP, sia per chi vuole ripassare concetti già noti. </p> <p><b>Iterazione 1</b></p> <p> <a href="http://csse.usc.edu/csse/TECHRPTS/1987/usccse87-502/usccse87-502.pdf">Improving Software Productivity</a> - Barry W. Boehm, TRW </p> <p> <a href="http://www.objectmentor.com/resources/articles/IIDI.pdf">Iterative and Incremental Development</a> - Robert C. Martin (Engineering Notebook C++ Report, Feb, 1999) </p> <p> <a href="http://www.objectmentor.com/resources/articles/IIDII.pdf">Iterative and Incremental Development (IID)</a> - Robert C. Martin Engineering (Notebook Column April, 1999, C++ Report.) </p> <p><b>Iterazione 2</b></p> <p> <a href="http://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062/ref=sr_1_1?ie=UTF8&amp;qid=1289486573&amp;sr=8-1">Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition)</a> Cap 1. - Pag 3-14 </p> <p> <a href="http://www.objectmentor.com/resources/articles/umlCollaborationDiagrams.pdf">UML Tutorial: Collaboration Diagrams</a> - Robert C. Martin Engineering Notebook Column Nov/Dec, 97 </p> <p><b>Iterazione 3</b></p> <p> <a href="http://agileotter.blogspot.com/2009/03/simple-act-of-using-better-name-instead.html">Power Of Naming</a> </p> <p> <a href="http://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062/ref=sr_1_1?ie=UTF8&amp;qid=1289486573&amp;sr=8-1">Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition)</a> Cap. 17.8, 17.9, 17.10, 17.11 </p> <p><b>Iterazione 4</b></p> <p> <a href="http://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062/ref=sr_1_1?ie=UTF8&amp;qid=1289486573&amp;sr=8-1">Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition)</a> capitoli 17.12 e 17.14 Low Coupling e High Cohesion </p> <p> <a href="http://martinfowler.com/books.html#refactoring">Refactoring: Improving the Design of Existing Code</a> Fowler cap 1. Come esercizio riprendere il codice e farlo in javascript </p> <p> <a href="http://www.objectmentor.com/resources/articles/umlClassDiagrams.pdf">UML Tutorial: Part 1</a> -- Class Diagrams. Robert C. Martin </p> <p><b>Iterazione 5</b></p> <p> <a href="http://martinfowler.com/books.html#refactoring">Refactoring: Improving the Design of Existing Code</a> Fowler cap 2. </p> <p> <a href="http://books.google.com/books?id=G8EL4H4vf7UC&amp;printsec=frontcover&amp;dq=extreme+programming+explained&amp;source=bl&amp;ots=j7BDwomXAk&amp;sig=LKzNHdze9dBVLlkzM8nXQb-rg2I&amp;hl=en&amp;ei=C73rTKbPAczrsgaw-LyVDw&amp;sa=X&amp;oi=book_result&amp;ct=result&amp;resnum=4&amp;ved=0CDoQ6AEwAw#v=onepage&amp;q&amp;f=false">Extreme programming explained: embrace change</a> Kent Beck - Fino al capitolo 3 incluso. </p> <p><b>Iterazione 6</b></p> <p> <a href="http://martinfowler.com/books.html#refactoring">Refactoring: Improving the Design of Existing Code</a> Fowler cap 3. </p> <p> <a href="http://www.objectmentor.com/resources/articles/ocp.pdf">The Open-Closed Principle</a> </p> <p> <a href="http://books.google.com/books?id=G8EL4H4vf7UC&amp;printsec=frontcover&amp;dq=extreme+programming+explained&amp;source=bl&amp;ots=j7BDwomXAk&amp;sig=LKzNHdze9dBVLlkzM8nXQb-rg2I&amp;hl=en&amp;ei=C73rTKbPAczrsgaw-LyVDw&amp;sa=X&amp;oi=book_result&amp;ct=result&amp;resnum=4&amp;ved=0CDoQ6AEwAw#v=onepage&amp;q&amp;f=false">Extreme programming explained: embrace change</a> Kent Beck - Capitolo 4. </p> <p> Continua... </p> <img src="http://blogs.ugidotnet.org/antonioganci/aggbug/99474.aspx" width="1" height="1" /> Antonio Ganci http://blogs.ugidotnet.org/antonioganci/archive/2010/11/11/studiare-le-basi-della-programmazione-ad-oggetti.aspx Thu, 11 Nov 2010 17:53:28 GMT http://blogs.ugidotnet.org/antonioganci/archive/2010/11/11/studiare-le-basi-della-programmazione-ad-oggetti.aspx#feedback 10 http://blogs.ugidotnet.org/antonioganci/comments/commentRss/99474.aspx http://blogs.ugidotnet.org/antonioganci/services/trackbacks/99474.aspx Un tecnica per testare l'interazione tra oggetti http://blogs.ugidotnet.org/antonioganci/archive/2010/09/06/un-tecnica-per-testare-linterazione-tra-oggetti.aspx <p> Ogni tanto, nello sviluppo software, emerge qualche <i>meme</i> come ad esempio: tutte le dipendenze devono essere disaccoppiate tramite un interface, tutte gli oggetti devono essere creati tramite factory, l'accesso ad un database deve avvenire tramite un ORM, il TDD genera un buon design ecc. </p> <p> Cosa hanno in comune tutte le frasi precedenti? Semplice: <b>creano scorciatoie per evitare di pensare</b>. Sarebbe bello se potessimo scrivere codice seguendo alla lettera un manuale, ma sarebbe anche terribilmente noioso e probabilmente verremmo sostituiti da qualche tipo di bot. </p> <p> Prendiamo la prima affermazione: <i>tutte le dipendenze devono essere disaccoppiate tramite un interface</i> e cerchiamo di capire da dove nasce questa esigenza. Il vantaggio di avere le dipendenze solo tramite interfacce <i>dovrebbe</i> essere quello di rendere più testabile le nostre classi. Ma è l'unico modo? Ed è il più semplice? </p> <p> Proviamo a fare un esempio. Supponiamo di voler testare il metodo SayHello: </p> <pre style="color:#000000;background:#ffffff;">var display = <span style="color:#000084; font-weight:bold; ">new</span> Display(); var greeting = <span style="color:#000084; font-weight:bold; ">new</span> Greeting(display); greeting.SayHello(); </pre> <p> L'implementazione di Greeting è la seguente: </p> <pre style="color:#000000;background:#ffffff;"><span style="color:#000084; font-weight:bold; ">public</span> <span style="color:#000084; font-weight:bold; ">class</span> Greeting { <span style="color:#000084; font-weight:bold; ">private</span> <span style="color:#000084; font-weight:bold; ">readonly</span> Display _display; <span style="color:#000084; font-weight:bold; ">public</span> Greeting(Display display) { _display = display; } <span style="color:#000084; font-weight:bold; ">public</span> <span style="color:#000084; font-weight:bold; ">void</span> SayHello() { _display.Show(<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">Hello!</span><span style="color:#0000ff; ">"</span>); } } </pre> <p> Mentre l'implementazione di display è la seguente: </p> <pre style="color:#000000;background:#ffffff;"><span style="color:#000084; font-weight:bold; ">public</span> <span style="color:#000084; font-weight:bold; ">class</span> Display { <span style="color:#000084; font-weight:bold; ">public</span> <span style="color:#000084; font-weight:bold; ">void</span> Show(<span style="color:#000084; font-weight:bold; ">string</span> text) { Console.WriteLine(text); } } </pre> <p> Sembra proprio il tipico esempio da manuale in cui si estrae l'interfaccia IDisplay e tramite la libreria di mocking preferita testo le interazioni di Greeting con Display. Esiste un'alternativa? </p> <p> La classe Console eredita da TextWriter, anche la classe StringWriter eredita da TextWriter. Proviamo quindi a passare la Console in costruzione a Display: </p> <pre style="color:#000000;background:#ffffff;"><span style="color:#000084; font-weight:bold; ">public</span> <span style="color:#000084; font-weight:bold; ">class</span> Display { <span style="color:#000084; font-weight:bold; ">private</span> <span style="color:#000084; font-weight:bold; ">readonly</span> TextWriter _textWriter; <span style="color:#000084; font-weight:bold; ">public</span> Display(TextWriter textWriter) { _textWriter = textWriter; } <span style="color:#000084; font-weight:bold; ">public</span> <span style="color:#000084; font-weight:bold; ">void</span> Show(<span style="color:#000084; font-weight:bold; ">string</span> text) { _textWriter.WriteLine(text); } } </pre> <p> Ora modfichiamo il main: </p> <pre style="color:#000000;background:#ffffff;">var display = <span style="color:#000084; font-weight:bold; ">new</span> Display(Console.Out); var greeting = <span style="color:#000084; font-weight:bold; ">new</span> Greeting(display); greeting.SayHello(); </pre> <p> A questo punto possiamo scrivere il test: </p> <pre style="color:#000000;background:#ffffff;">var stringWriter = <span style="color:#000084; font-weight:bold; ">new</span> StringWriter(); var greeting = <span style="color:#000084; font-weight:bold; ">new</span> Greeting(<span style="color:#000084; font-weight:bold; ">new</span> Display(stringWriter)); greeting.SayHello(); Assert.That(stringWriter.ToString(), Is.EqualTo(<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">Hello!</span><span style="color:#0000ff; ">"</span>)); </pre> <p> In questo modo abbiamo fatto <b>un test più solido rispetto a testare l'interazione con un interfaccia</b> ed il codice è più semplice. </p> <img src="http://blogs.ugidotnet.org/antonioganci/aggbug/99157.aspx" width="1" height="1" /> Antonio Ganci http://blogs.ugidotnet.org/antonioganci/archive/2010/09/06/un-tecnica-per-testare-linterazione-tra-oggetti.aspx Mon, 06 Sep 2010 09:54:57 GMT http://blogs.ugidotnet.org/antonioganci/archive/2010/09/06/un-tecnica-per-testare-linterazione-tra-oggetti.aspx#feedback 4 http://blogs.ugidotnet.org/antonioganci/comments/commentRss/99157.aspx http://blogs.ugidotnet.org/antonioganci/services/trackbacks/99157.aspx Scrivere Acceptance Test per una applicazione Wpf - Seconda parte http://blogs.ugidotnet.org/antonioganci/archive/2010/08/25/scrivere-acceptance-test-per-una-applicazione-wpf-seconda-parte.aspx <p> Se avete seguito i passi del <a href="http://blogs.ugidotnet.org/AntonioGanci/archive/2010/08/19/scrivere-acceptance-test-per-una-applicazione-wpf.aspx">post</a> precedente e provate a lanciare il test dovrebbe aprirsi una finestra che si chiude quasi istantaneamente. </p> <p> Proviamo ora a simulare il click ad un pulsante. Per prima cosa aggiungiamo il controllo alla main window <b>ricordandoci di dargli un nome</b> (nel nostro caso buttonControl). Lo xaml dovrebbe essere qualcosa di analogo: </p> <pre style="color:#000000;background:#ffffff;"><span style="color:#7f0055; ">&lt;</span><span style="color:#7f0055; ">Window</span> x:Class=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">WPFAndNUnit.MainWindow</span><span style="color:#0000ff; ">"</span> xmlns=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">http</span><span style="color:#0000ff; ">:</span><span style="color:#000084; font-weight:bold; ">//</span><span style="color:#3f3fbf; ">schemas.microsoft.com</span><span style="color:#3f3fbf; ">/winfx/2006/xaml/presentation</span><span style="color:#0000ff; ">"</span> xmlns:x=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">http</span><span style="color:#0000ff; ">:</span><span style="color:#000084; font-weight:bold; ">//</span><span style="color:#3f3fbf; ">schemas.microsoft.com</span><span style="color:#3f3fbf; ">/winfx/2006/xaml</span><span style="color:#0000ff; ">"</span> Title=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">MainWindow</span><span style="color:#0000ff; ">"</span> Height=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">350</span><span style="color:#0000ff; ">"</span> Width=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">525</span><span style="color:#0000ff; ">"</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;</span><span style="color:#7f0055; ">Canvas</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;</span><span style="color:#7f0055; ">Button</span> Name=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">buttonControl</span><span style="color:#0000ff; ">"</span> <span style="color:#7f0055; ">&gt;</span>A button<span style="color:#7f0055; ">&lt;/</span><span style="color:#7f0055; ">Button</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;/</span><span style="color:#7f0055; ">Canvas</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;/</span><span style="color:#7f0055; ">Window</span><span style="color:#7f0055; ">&gt;</span> </pre> <p> </p> <p> Ora possiamo usare il metodo FindName per trovare il nostro button e quindi modifichiamo il test come segue: </p> <pre style="color:#000000;background:#ffffff;">[Test] <span style="color:#000084; font-weight:bold; ">public</span> <span style="color:#000084; font-weight:bold; ">void</span> ShowTheMainWindow() { var window = <span style="color:#000084; font-weight:bold; ">new</span> MainWindow(); window.Show(); var button = (Button) window.FindName(<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">buttonControl</span><span style="color:#0000ff; ">"</span>); Assert.That(button, Is.Not.Null); } </pre> <p> </p> <p> Se eseguiamo il test dovrebbe passare altrimenti ricontrollate i passi precedenti. </p> <p> Per simulare il click al pulsante usiamo il metodo RaiseEvent come segue: </p> <pre style="color:#000000;background:#ffffff;">button.RaiseEvent(<span style="color:#000084; font-weight:bold; ">new</span> RoutedEventArgs(Button.ClickEvent)); </pre> <p> </p> <p> Se proviamo ad aggiungere un comportamento all'evento click del pulsante verifichiamo che venga eseguito correttamente. </p> <p> In sinstesi la tecnica consiste in: dare un nome ai controlli con cui vogliamo interagire nel test e usare il metodo RaiseEvent per simulare le azioni dell'utente. </p> <img src="http://blogs.ugidotnet.org/antonioganci/aggbug/99113.aspx" width="1" height="1" /> Antonio Ganci http://blogs.ugidotnet.org/antonioganci/archive/2010/08/25/scrivere-acceptance-test-per-una-applicazione-wpf-seconda-parte.aspx Wed, 25 Aug 2010 13:34:06 GMT http://blogs.ugidotnet.org/antonioganci/archive/2010/08/25/scrivere-acceptance-test-per-una-applicazione-wpf-seconda-parte.aspx#feedback http://blogs.ugidotnet.org/antonioganci/comments/commentRss/99113.aspx http://blogs.ugidotnet.org/antonioganci/services/trackbacks/99113.aspx Scrivere Acceptance Test per una applicazione Wpf http://blogs.ugidotnet.org/antonioganci/archive/2010/08/19/scrivere-acceptance-test-per-una-applicazione-wpf.aspx <p> Gli <a href="http://c2.com/cgi/wiki?AcceptanceTest">acceptance test</a> servono a verificare che una user story sia stata realizzata correttamente, quindi sono test definiti insieme al cliente o addirittura scritti dal cliente. </p> <p> L'applicazione che stiamo scrivendo utilizza wpf, quindi la nostra necessità è quella di poter aprire finestre, cliccare sui pulsanti, ecc. all'interno di un test automatico. </p> <p> Esistono approcci alternativi a quello che propongo in questo post, come ad esempio le <a href="http://testapi.codeplex.com/">TestApi</a>, le quali utilizzano le <a href="http://msdn.microsoft.com/en-us/library/ms747327.aspx">automation api</a> mentre per l'input del mouse e della tastiera utilizzano l'API <a href="http://msdn.microsoft.com/en-us/library/ms646310(VS.85).aspx">SendInput</a>. Le TestApi fanno molto di più di quello che a noi serve e quindi ho cercato un approccio più adatto al nostro caso. </p> <p> Per prima cosa creiamo un progetto di Test che referenzia l'assembly con la finestra sotto test e scriviamo il seguente codice: </p> <pre style="color:#000000;background:#ffffff;">[TestFixture] <span style="color:#000084; font-weight:bold; ">public</span> <span style="color:#000084; font-weight:bold; ">class</span> MainWindowTest { [Test] <span style="color:#000084; font-weight:bold; ">public</span> <span style="color:#000084; font-weight:bold; ">void</span> ShowTheMainWindow() { var window = <span style="color:#000084; font-weight:bold; ">new</span> MainWindow(); window.Show(); } } </pre> <p> Se proviamo ad eseguirlo ottienamo il seguente errore: </p> <p> System.InvalidOperationException : <b>The calling thread must be STA, because many UI components require this</b>. </p> <p> Il motivo dell'errore è che il default <a href="http://msdn.microsoft.com/en-us/library/system.threading.thread.setapartmentstate.aspx">apartment state</a> è MTA, normalmente lo si imposta come attributo del metodo Main, purtroppo in questo caso il main si trova nel test runner. </p> <p> Per risolvere il problema dobbiamo aggiungere al progetto l'Application Configuration File (App.config) ed inserire la seguente configurazione: </p> <pre style="color:#000000;background:#ffffff;"><span style="color:#000084; ">&lt;?</span><span style="color:#000084; ">xml</span> <span style="color:#000084; ">version</span>="1.0" <span style="color:#000084; ">encoding</span>=<span style="color:#0000ff; ">"utf-8"</span> <span style="color:#000084; ">?&gt;</span> <span style="color:#7f0055; ">&lt;</span><span style="color:#7f0055; ">configuration</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;</span><span style="color:#7f0055; ">configSections</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;</span><span style="color:#7f0055; ">sectionGroup</span> name=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">NUnit</span><span style="color:#0000ff; ">"</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;</span><span style="color:#7f0055; ">section</span> name=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">TestRunner</span><span style="color:#0000ff; ">"</span> type=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">System.Configuration.NameValueSectionHandler</span><span style="color:#0000ff; ">"</span><span style="color:#7f0055; ">/&gt;</span> <span style="color:#7f0055; ">&lt;/</span><span style="color:#7f0055; ">sectionGroup</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;/</span><span style="color:#7f0055; ">configSections</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;</span><span style="color:#7f0055; ">NUnit</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;</span><span style="color:#7f0055; ">TestRunner</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;</span><span style="color:#7f0055; ">add</span> key=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">ApartmentState</span><span style="color:#0000ff; ">"</span> value=<span style="color:#0000ff; ">"</span><span style="color:#0000ff; ">STA</span><span style="color:#0000ff; ">"</span> <span style="color:#7f0055; ">/&gt;</span> <span style="color:#7f0055; ">&lt;/</span><span style="color:#7f0055; ">TestRunner</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;/</span><span style="color:#7f0055; ">NUnit</span><span style="color:#7f0055; ">&gt;</span> <span style="color:#7f0055; ">&lt;/</span><span style="color:#7f0055; ">configuration</span><span style="color:#7f0055; ">&gt;</span> </pre> <p> Se proviamo a lanciare il test ora passa senza problemi; come test runner uso quello di Resharper per cui non so se con altri test runner la soluzione proposta funzioni correttamente. </p> <p> Vedremo una tecnica per mandare gli eventi ai controlli nel prossimo post. </p> <img src="http://blogs.ugidotnet.org/antonioganci/aggbug/99087.aspx" width="1" height="1" /> Antonio Ganci http://blogs.ugidotnet.org/antonioganci/archive/2010/08/19/scrivere-acceptance-test-per-una-applicazione-wpf.aspx Thu, 19 Aug 2010 11:55:57 GMT http://blogs.ugidotnet.org/antonioganci/archive/2010/08/19/scrivere-acceptance-test-per-una-applicazione-wpf.aspx#feedback 2 http://blogs.ugidotnet.org/antonioganci/comments/commentRss/99087.aspx http://blogs.ugidotnet.org/antonioganci/services/trackbacks/99087.aspx L'importanza degli spike http://blogs.ugidotnet.org/antonioganci/archive/2010/07/13/limportanza-degli-spike.aspx <p> Per stimare o sviluppare una user story a volte è necessario documentarsi su aspetti tecnici che non padroneggiamo. Nel mondo agile questa pratica viene chiamata <a href="http://www.extremeprogramming.org/rules/spike.html">spike</a> </p> <p> Uno degli aspetti che si sottovalutano degli spike è che con il tempo costituiscono una knowledge base molto utile per lo sviluppatore. <strong>Un altro aspetto importante è che non vengono fatti esperimenti sul codice di produzione</strong>. </p> <p> Personalmente gli spike li committo in un repository chiamato Spikes cercando di dare dei nomi significativi alle varie solution in modo da poterli ritrovare facilmente in seguito es: HowToCenterTextVerticallyWithWpf.sln. Inoltre cerco di scrivere, se possibile, tutto il codice in un unico metodo per ritrovarlo facilmente. Lo scopo dello spike non è codice object oriented o con un'architettura malleabile, ma semplicemente di rispondere ad una domanda tecnica ben precisa. </p> <p> Gli svantaggi nello scrivere gli spike nel codice di produzione sono: difficoltà nel ritrovarli in futuro; qualità del codice compromessa in quanto non sapendo esattamente cosa fare si rischia di scrivere molto più codice del necessario. </p> <p> Un altro utilizzo molto utile dello spike è quello di <span style="font-weight: bold;">cercare diverse soluzioni per lo stesso problema in modo da scegliere la più semplice</span>. In questo caso trovo utile decidere prima un timebox fisso (tipo mezza giornata) per non rischiare di perdere troppo tempo. A volte il timebox è meno importante perchè non si conosce alcuna soluzione al problema e quindi è necessario andare avanti finchè non si trova oppure si rinuncia alla feature. </p><img src="http://blogs.ugidotnet.org/antonioganci/aggbug/98938.aspx" width="1" height="1" /> Antonio Ganci http://blogs.ugidotnet.org/antonioganci/archive/2010/07/13/limportanza-degli-spike.aspx Tue, 13 Jul 2010 19:29:40 GMT http://blogs.ugidotnet.org/antonioganci/archive/2010/07/13/limportanza-degli-spike.aspx#feedback 1 http://blogs.ugidotnet.org/antonioganci/comments/commentRss/98938.aspx http://blogs.ugidotnet.org/antonioganci/services/trackbacks/98938.aspx Alcune riflessioni sui metodi agili http://blogs.ugidotnet.org/antonioganci/archive/2010/05/11/alcune-riflessioni-sui-metodi-agili.aspx <p> il <a href="http://riccardo.marotti.name/post/573406958/fr-agile">post</a> di Riccardo mi ha dato l'occasione per riflettere su un disagio che sento presso le aziende che intendono iniziare o già utilizzano i metodi agili. </p> <p> Credo che la questione sia dovuta alla differenza della situazione delle aziende italiane, formate soprattutto da PMI, rispetto a quelle anglosassoni. </p> <p> In generale ho visto l'interesse ad utilizzare alcune pratiche agili (soprattutto l'introduzione dei test e la continuous integration) in situazioni dove è presente quello che io chiamo il <em>cowboy programming</em>. </p> <p> Sostanzialmente una situazione di quasi totale anarchia dove la pratica più utilizzata è il code and fix. In queste realtà le pratiche agili vengono viste come una <strong>burocratizzazione</strong> del processo e non uno snellimento. </p> <p> Molti articoli che ho visto in rete invece mostrano i vantaggi dei metodi agili rispetto al waterfall. Il waterfall è l'esatto opposto del <em>cowboy programming</em> e quindi il metodo agile, in questo caso, viene visto come una sburocratizzazione del processo. </p> <p> La parola burocrazia ha un'accezione negativa in Italia per i motivi che tutti conosciamo, ma è fondamentale per il funzionamento di qualunque organizzazione compresa un'azienda di sviluppo software. </p> <p> Schematizzando con un grafico questi concetti potrei ipotizzare che nessuna burocrazia sia un danno e quindi un beneficio negativo, analogalmente a troppa burocrazia. </p> <p> <img alt="Grafico burocrazia" src="http://blogs.ugidotnet.org/images/blogs_ugidotnet_org/AntonioGanci/1890/o_Burocrazia.png" /> </p> <p> Un altro luogo comune è quello di considerare le pratiche agili come un silver bullet: cioè necessarie e sufficienti a portare a compimento con successo un progetto. Mi spiace, ma si possono seguire <strong>tutte le pratiche agili</strong> e fallire. </p> <p> Il motivo è dovuto alle precondizioni affinchè un progetto abbia successo come ad esempio le competenze degli sviluppatori, ecc. Analogamente un progetto software puo' avere successo anche senza usare nessuna pratica agile. </p><img src="http://blogs.ugidotnet.org/antonioganci/aggbug/98546.aspx" width="1" height="1" /> Antonio Ganci http://blogs.ugidotnet.org/antonioganci/archive/2010/05/11/alcune-riflessioni-sui-metodi-agili.aspx Tue, 11 May 2010 22:53:11 GMT http://blogs.ugidotnet.org/antonioganci/archive/2010/05/11/alcune-riflessioni-sui-metodi-agili.aspx#feedback 7 http://blogs.ugidotnet.org/antonioganci/comments/commentRss/98546.aspx http://blogs.ugidotnet.org/antonioganci/services/trackbacks/98546.aspx