<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2819327489527180569</id><updated>2011-12-08T18:55:54.976+01:00</updated><category term='giuliani'/><category term='presidential'/><category term='lean'/><category term='obama'/><category term='scrum'/><category term='subclass'/><category term='agile'/><category term='data types'/><category term='java'/><category term='abstraction'/><category term='tit for tat'/><category term='tdd testing'/><category term='kanban'/><category term='annotations'/><category term='open closed'/><category term='fun'/><category term='depdency inversion'/><category term='xp'/><category term='prisoner dilemma'/><title type='text'>tonyx</title><subtitle type='html'>agile, scrum, tdd, software craftsmanship</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>44</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-4528461436425731512</id><published>2011-12-08T14:52:00.007+01:00</published><updated>2011-12-08T18:55:54.983+01:00</updated><title type='text'>Global Day of Coderetreat in Milan</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;3th of December  was a wonderful day, with around 25 enthusiast people joining the Global Day of Coderetreat.&lt;/p&gt; &lt;p lang="en-US" style="margin-bottom: 0cm"&gt;  &lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;The organizer of the event were me, Gabriele Lana, Giordano Scalzo and  Sergio Berisso.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;We decided to organize the event at the very last moment. The fact that I met Corey Haines, Peter Lind, and other guys in a pub in Stockholm two weeks before, talking also about this global event in motivated me.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;It came in my mind about Lorenzo Sicilia and his &lt;a href="http://www.fractalgarden.com/"&gt;FractalGarden&lt;/a&gt; location that I expected beeing available, so I thought that we could organize, and we did.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;When back in Milan... after a rapid mail exchange with Giordano, Gabriele, Sergio and Lorenzo we had the confirmation from the location and... we made it!&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;The final announce was sent with a short notice, only one week before, but it went sold out in just one morning! Awesome!&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;We “self-sponsored” the food offering the &lt;a href="https://picasaweb.google.com/lh/photo/2i2WxW3CXPq8iZEwPlFJadMTjNZETYmyPJy0liipFm0?feat=directlink"&gt;breakfast&lt;/a&gt; and snacks for all day. We also get some Japanese food during the day. And of course we had some &lt;a href="http://twitter.com/#!/giordanoscalzo/status/142962180663410688/photo/1"&gt;beer&lt;/a&gt; :D&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;Let's go to the day than: after a quick welcome, Gabriele Lana &lt;a href="http://www.slideshare.net/gabriele.lana/coderetreat"&gt;presented&lt;/a&gt; the format of the day and explained the value of the practices like coding dojo and kata.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;Then we started.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;The first two iterations were essentially free of rules, just to be confident about the problem, and comfortable doing programming, setting up the environment and so on.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;I used an &lt;a href="http://yfrog.com/nnz1vz"&gt;irish flute&lt;/a&gt; to signal the end of the iterations :)&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;Then in the following iterations we started suggesting some constraints like ping poing, primitive obsessions, and using immutable objects.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;At the beginning we found some pairs needing  help like when got stuck, and helped them and moreover tried to set up for the next iterations  pairs in a way to prevent blocks.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;During the 10 minutes retrospective between iterations, we encouraged attendees to share about their learning.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;We closed the day with a &lt;a href="http://twitter.com/#!/piccoloaiutante/status/143001599290261506/photo/1"&gt;final retrospective&lt;/a&gt;, and closing the circle.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;Of course, we &lt;a href="https://picasaweb.google.com/lh/photo/H8TSHFuB60EH6ySylhkjCdMTjNZETYmyPJy0liipFm0?feat=directlink"&gt;cleaned&lt;/a&gt; up at the end. &lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;It was a fantastic day. And we are surely going to do it again soon.&lt;/p&gt; &lt;p lang="en-US" style="text-align: left;margin-bottom: 0cm; "&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-4528461436425731512?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/4528461436425731512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=4528461436425731512' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/4528461436425731512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/4528461436425731512'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2011/12/global-day-of-coderetreat-in-milan.html' title='Global Day of Coderetreat in Milan'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-5704876841875007605</id><published>2011-09-11T18:30:00.015+02:00</published><updated>2011-10-25T00:11:20.055+02:00</updated><title type='text'>Stop doing estimates? Yes you can!</title><content type='html'>&lt;div&gt;&lt;p style="margin-bottom: 0cm; font-style: normal;" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;An interesting session of the &lt;a href="http://ale2011.eu/"&gt;Ale2011&lt;/a&gt; is from &lt;a href="http://twitter.com/#%21/angel_m"&gt;Angel Medinilla&lt;/a&gt;, about &lt;a href="http://www.slideshare.net/proyectalis/the-easy-way-to-stop-estimating"&gt;the easy way to stop estimating&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0cm; font-style: normal;" lang="en-US"&gt;Here are my thoughts after attending the session.&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;The topic originates from a quite simple concept: doing estimates needs time, which is a costs. If they are not needed, they should be considered a waste, to be eliminated, as David J. Anderson stated as well, some times ago.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;His finding is that the estimates are actually not needed and he explained why.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;This is my short way to come to that conclusion (not necessarily the same as was presented in the session by Angel).&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;Estimates are, normally, considered useful because they let us "forecast" how much can be delivered within a certain, generally short, period of time.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;Well, that's not what a Product Owner really want. What is needed, actually, is not just a short term "&lt;i&gt;forecast&lt;/i&gt;", but rather a long term "&lt;i&gt;projection&lt;/i&gt;": a reliable release plan. And that plan can be obtained by the teams who know their velocity (usually in term of number of story points per sprint).&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;But, wait a moment. What if we try to get this projection just counting the features instead of the sum of their estimated size (story points)? It would be like just giving to all the stories one story point.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;The fact that the story &lt;i&gt;sizes&lt;/i&gt; may be of different sizes doesn't matter so much. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;I guess that a statistician would say something like: let's just count the stories released in the past sprints, and we have an &lt;i&gt;&lt;a href="http://en.wikipedia.org/wiki/Bias_of_an_estimator"&gt;unbiased estimator&lt;/a&gt;&lt;/i&gt; of the velocity of the future sprints. It's true if the sprints are “regular” enough (i.e. the story sizes are equally distributed over the sprints) and the average of the velocities doesn't change over the sprints.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;However, beside the above long-winded statement, we may just consider that it is ok also for another reason. The stories are actually small, so though counting stories (instead of summing their estimated size) will introduce a bias, that bias would be small as well.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;So I am almost convinced but... wait a moment!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;What about the other outcomes from the estimation activity? The conversation on the scope that you have while estimating, say, playing poker planning game?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;A "mainstream" opinion is that estimation permits a conversation about the scope, giving the Product Owner important feedback about the possibility of splitting stories,  clarify their scope, or modify their priority.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;However stopping doing estimates could be still reasonable. Sometimes there is no need to discuss  so much and so on... because may be they are perfectly clear to everybody, (and there is still room for a conversation when splitting in sub-tasks)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;That could work, at least for a while, but something can change: perhaps there will be new team members, or the product may change as well, or even the customer needs may change. So in all this case, estimation can be a good exercise to let the team gel, and let emerge critical issues.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;Anyway, this is just my idea about the session, and I can't remember everything from it, so if I misinterpreted the meaning, or skipped some important parts, I apologize.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;Back on topic...  nothing is forever. Every context is different from another, so what is good sometimes, sometimes it is not.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt; &lt;span&gt;&lt;span&gt;&lt;span&gt;If during a retrospective the team suggest skipping estimation, we know that it could be perfectly reasonable and consistent even for the Product Owner, so we can give it a try... and then check.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2;" align="LEFT" lang="en-US"&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-5704876841875007605?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/5704876841875007605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=5704876841875007605' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5704876841875007605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5704876841875007605'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2011/09/stop-doing-estimates-yes-you-can.html' title='Stop doing estimates? Yes you can!'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-3163712104926642626</id><published>2011-09-10T20:25:00.011+02:00</published><updated>2011-10-25T00:10:05.684+02:00</updated><title type='text'>Smettere di stimare</title><content type='html'>Una presentazione interessante dell'ale2011 è stata quella di &lt;a href="http://twitter.com/#%21/angel_m"&gt;Angel Medinilla&lt;/a&gt;, sul &lt;a href="http://www.slideshare.net/proyectalis/the-easy-way-to-stop-estimating"&gt;modo piu' semplice per smettere di fare le stime&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;L'argomento parte da un concetto semplice: fare delle stime è una attività complessa che occupa del tempo, e quindi, se non è necessaria è un waste da eliminare, come ebbe a suo tempo modo di dire anche David Anderson.&lt;br /&gt;&lt;br /&gt;La tesi è appunto che le stime non sono necessarie.&lt;br /&gt;&lt;br /&gt;Come fare a stabilire che non lo sono?&lt;br /&gt;Una interpretazione che si da all'utilità delle stime è che queste consentirebbero di avere una "previsione" su cosa si riesce a rilasciare in un certo periodo.&lt;div&gt;In realtà più che un previsione quello che serve è una "proiezione": un piano di rilascio affidabile che possono per esempio dare i team che conoscono la velocità (come numero di story points per sprint).&lt;br /&gt;&lt;div&gt;Ma questa proiezione la si può ottenere anche senza fare le stime. Basta assumere che anziché misurare gli story point, si misurano le user story stesse rilasciate, come se avessero tutte peso unitario.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Non importa che le storie possono avere delle grandezze differenti. Lo statistico che è in me (ma vorrei avere una conferma più autorevole) su questo punto direbbe: il conteggio delle storie negli sprint passati è uno &lt;i&gt;&lt;a href="http://it.wikipedia.org/wiki/Bias_(statistica)"&gt;stimatore corretto&lt;/a&gt;&lt;/i&gt; (unbiased) della velocità degli sprint futuri, se la grandezza delle storie è distribuita allo stesso modo in tutti gli sprint e la velocità media è costante, rispetto agli sprint.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Poi, a livello pratico, diciamo che le storie già di per sé &lt;i&gt;devono&lt;/i&gt; essere piccole, quindi, anche se fosse rilevante, l'errore potenziale tra una stima virtualmente costante (peso unitario) ed un valore (size) che è sempre piccolo, è comunque limitato.&lt;br /&gt;&lt;br /&gt;Sotto questo aspetto, la tesi dello smettere di stimare è convincente, anche se...&lt;/div&gt;&lt;div&gt;che cosa diciamo del beneficio che si ha dalla conversazione che si fa stimando, per esempio attraverso "cerimonie" come il planning poker game?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Secondo il pensiero mainstream infatti tra i vantaggi dello stimare le storie c'è il fatto che risulta possibile ingaggiare una discussione proficua che riguarda lo scope,  che può aiutare il Product Owner a chiarirle, modificarle, dividerle in più storie, o cambiarne la priorità.&lt;br /&gt;&lt;br /&gt;Può darsi invece il rinunciare a fare delle stime sia effettivamente un'ottima cosa, per esempio per team ben rodati che lavorano su un prodotto già noto, ma qui è come se ci stessimo spostando su un qualcosa di più &lt;i&gt;definito, &lt;/i&gt;dove la generare molte informazioni non è più necessario.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ma le cose poi cominciano a cambiare: i componenti del team cambiano, cambiar il tipo di prodotto, e per questo potrebbe essere utile una discussione che coinvolga anche la grandezza delle storie, almeno come &lt;i&gt;espediente&lt;/i&gt; per parlare anche del loro vero scope. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Comunque, niente si può dare per scontato. Ogni contesto è diverso, e quindi quello che va bene per uno magari non va bene per l'altro.&lt;/div&gt;&lt;div&gt;Quindi l'unica cosa è provare e... verificare.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-3163712104926642626?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/3163712104926642626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=3163712104926642626' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3163712104926642626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3163712104926642626'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2011/09/smettere-di-stimare.html' title='Smettere di stimare'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-8403859098045970863</id><published>2011-09-03T16:45:00.008+02:00</published><updated>2011-09-18T20:34:58.442+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>Unplanned items, velocity and prisoner check-mark tecnique</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: center; "&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"&gt;&lt;p style="font-style: italic; "&gt;&lt;/p&gt;&lt;p style="font-style: italic; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;a href="http://1.bp.blogspot.com/-bKTmn1dS8io/TlnV1QuwZUI/AAAAAAAAAgM/eHXcDLS5WDM/s1600/Unplanneditemschartstartday10-2.png" style="font-style: normal; " onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://1.bp.blogspot.com/-bKTmn1dS8io/TlnV1QuwZUI/AAAAAAAAAgM/eHXcDLS5WDM/s400/Unplanneditemschartstartday10-2.png" alt="" id="BLOGGER_PHOTO_ID_5645778718886487362" border="0" style="text-align: left; display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; cursor: pointer; width: 400px; height: 300px; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;/span&gt;&lt;/i&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;(note added: I'm going to write a short version of this post later. No need to read all of it now then)&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;This post is about a way to give visibility on what is happening during the sprint, including the "unplanned items", using an unplanned items burn up, measuiring the actual time by "prisoner metrics" check-marks, and having not just the velocity in term of total item of the sprint, but also the the "net velocity", calculated considering the time actually available during the sprint.&lt;/span&gt;&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Rearranging the items for the gap between actual average velocity, and estimated, the team can effectively answer to the question "what went wrong". &lt;/span&gt;&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;We will able to see:&lt;/span&gt;&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;- actual time spent in working on the item.&lt;/span&gt;&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;- actual time spent on unplanned items.&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;- the actual velocity of the sprint, and a projection of what that velocity could have been if we didn't have unplanned items. This is using the "net velocity".&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;- at the end of the sprint we may have also visibility of what are the tech area we were late, and some guesses of why, particularly using information from the  &lt;/span&gt;&lt;a href="http://blog.crisp.se/henrikkniberg/2009/02/27/1235769840000.html"&gt;skill matrix&lt;/a&gt;&lt;span class="Apple-style-span"&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;The team is not supposed to add anything to the sprint, &lt;i&gt;but&lt;/i&gt; that happens anyway: fixing bugs coming from the previous sprint, attending important meetings, or having some slack time. That actually modifies the &lt;i&gt;container&lt;/i&gt;.&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;If we can't get rid of unplanned items, at least let's have visibility about.&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Instead of aborting sprints, or, worst, tending to hide what's really happening, or (better) using focus factor tecquique, I'd suggest an alternative that consist in making visible:&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;- the actual time spent in any item&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;- the burn up of the time spent in unplanned items.&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;At the end of the sprint it can be showed where there is the need of improve, distributing the item colored with their technology area, with the rank of the skill of who worked on what items. &lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;br /&gt;&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;Here we can see a simulation of  sprint: &lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;We have a 10 days sprint of a "team" of two member (just for simplicity), and an estimated velocity of 10 story point (i.e. 0.5 story point for man/day)&lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;(Please, note that I am not dealing so much about tasks and user stories. In the first part of the post the items we could consider them much more as they were user stories) &lt;/p&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;Here is the taskboard at the day 0:&lt;/p&gt;&lt;div style="text-align: center; "&gt;&lt;p style="font-style: normal; "&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5644819774683781842"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-SGgQUkEVvRE/TlZtrXMgmtI/AAAAAAAAAdU/KkvsK1uW8DY/s1600/unplanneditemschart.png"&gt;&lt;img src="http://2.bp.blogspot.com/-SGgQUkEVvRE/TlZtrXMgmtI/AAAAAAAAAdU/KkvsK1uW8DY/s400/unplanneditemschart.png" name="immagini1" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;The A and B item are selected for "doing":&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;a name="BLOGGER_PHOTO_ID_5644823885920059234"&gt;&lt;/a&gt;&lt;/u&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://2.bp.blogspot.com/-sA-AnzW2LcA/TlZxaqvnv2I/AAAAAAAAAdc/Sv7tA_Wa6Eo/s1600/UNPLANNEDCHARTSTARTDAY1.png"&gt;&lt;img src="http://2.bp.blogspot.com/-sA-AnzW2LcA/TlZxaqvnv2I/AAAAAAAAAdc/Sv7tA_Wa6Eo/s400/UNPLANNEDCHARTSTARTDAY1.png" name="immagini2" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;After one day, we use the "prisoner metrics", that simply means using check mark to visualize the time spent on any item:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5644825225670005042"&gt;&lt;/a&gt;&lt;span&gt;&lt;img src="http://4.bp.blogspot.com/-GZvAG-Vf_t0/TlZyops5kTI/AAAAAAAAAdk/QGN1woSc74g/s400/UNPLANNEDCHARTSTARTDAY2.png" name="immagini3" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;After one day, nothing changes, except that we add another checkmark to both the items:&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;a name="BLOGGER_PHOTO_ID_5645101709653434386"&gt;&lt;/a&gt;&lt;/u&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://1.bp.blogspot.com/-HaMrmbzlFxo/TlduGIzX4BI/AAAAAAAAAds/DXrPsjalPpM/s1600/Unplanneditemschartstartday3.png"&gt;&lt;img src="http://1.bp.blogspot.com/-HaMrmbzlFxo/TlduGIzX4BI/AAAAAAAAAds/DXrPsjalPpM/s400/Unplanneditemschartstartday3.png" name="immagini4" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;At the beginning of the fourth day, item A is done, another mark is put on it (so the information about how much days was taken is consistent).&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://4.bp.blogspot.com/-Lkke5roiuHE/TldxXJEao5I/AAAAAAAAAd0/co78WVAiHMg/s1600/Unplanneditemschartstartday4-1.png"&gt;&lt;img src="http://4.bp.blogspot.com/-Lkke5roiuHE/TldxXJEao5I/AAAAAAAAAd0/co78WVAiHMg/s400/Unplanneditemschartstartday4-1.png" name="immagini5" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;...the item C is in doing now:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;a name="BLOGGER_PHOTO_ID_5645107009409763346"&gt;&lt;/a&gt;&lt;/u&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://3.bp.blogspot.com/-7LD-VKV5qdA/Tldy6n7vyBI/AAAAAAAAAd8/hTqKC6KWO_Q/s1600/Unplanneditemschartstartday4.png"&gt;&lt;img src="http://3.bp.blogspot.com/-7LD-VKV5qdA/Tldy6n7vyBI/AAAAAAAAAd8/hTqKC6KWO_Q/s400/Unplanneditemschartstartday4.png" name="immagini6" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Another day passes. And item C is check-marked appropriately:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;a name="BLOGGER_PHOTO_ID_5645107695426015378"&gt;&lt;/a&gt;&lt;/u&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://1.bp.blogspot.com/-v6JIVRWMxdo/TldzijixEJI/AAAAAAAAAeE/Mn7vsLF9MsQ/s1600/Unplanneditemschartstartday5.png"&gt;&lt;img src="http://1.bp.blogspot.com/-v6JIVRWMxdo/TldzijixEJI/AAAAAAAAAeE/Mn7vsLF9MsQ/s400/Unplanneditemschartstartday5.png" name="immagini7" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Day 6: B is finished, it has another mark (and a cross mark as well, a big cross mark has to be put each 5 working days), and the item D is checked out.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645111472868463538"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://1.bp.blogspot.com/-XpOyayrSAq4/Tld2-bnOk7I/AAAAAAAAAeM/63zs9dZykSs/s1600/Unplanneditemschartstartday6.png"&gt;&lt;img src="http://1.bp.blogspot.com/-XpOyayrSAq4/Tld2-bnOk7I/AAAAAAAAAeM/63zs9dZykSs/s400/Unplanneditemschartstartday6.png" name="immagini8" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Unfortunately, during the day an unplanned item is added and the C activity is interrupted. We track it putting that activity over C, in the following way:&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;a name="BLOGGER_PHOTO_ID_5645112745815831474"&gt;&lt;/a&gt;&lt;/u&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://1.bp.blogspot.com/-_6K3lmqUejc/Tld4Ihth87I/AAAAAAAAAeU/Wmpd4nOmOmo/s1600/Unplanneditemschartstartday6-middle.png"&gt;&lt;img src="http://1.bp.blogspot.com/-_6K3lmqUejc/Tld4Ihth87I/AAAAAAAAAeU/Wmpd4nOmOmo/s400/Unplanneditemschartstartday6-middle.png" name="immagini9" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;The question now is what about the burn down and the unplanned item.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;The burn down will probably be flatter, but we may not know the reason, then a new "burn up" chart will be useful to show how much time is being subtracted from the sprint. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;In this new graph the Y axis value are based on time, and not in story points. In fact we are not estimating the new items. There is no need for this.&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;Another day passes, and we mark the unplanned item with a checkmark as well, and what we do with the C that is still there, unfinished, though one day passed anyway? We decide to checkmark it anyway with a different color (red). And the burn up tracks the time:&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; display: inline !important; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-nK9rRtgz6yc/TleIaePDaeI/AAAAAAAAAek/P0kte7o2xN4/s1600/Unplanneditemschartstartday7.png"&gt;&lt;img src="http://2.bp.blogspot.com/-nK9rRtgz6yc/TleIaePDaeI/AAAAAAAAAek/P0kte7o2xN4/s400/Unplanneditemschartstartday7.png" name="immagini11" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Day 8. Same song:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645131003908836690"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-jKCoRAy320Q/TleIvSaHzVI/AAAAAAAAAes/G-XoSP34HqA/s1600/Unplanneditemschartstartday8.png"&gt;&lt;img src="http://2.bp.blogspot.com/-jKCoRAy320Q/TleIvSaHzVI/AAAAAAAAAes/G-XoSP34HqA/s400/Unplanneditemschartstartday8.png" name="immagini12" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Day 9: we realize that D is finished.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; display: inline !important; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span&gt;&lt;a href="http://3.bp.blogspot.com/-5LxWcCTRHrY/TleJjAl94zI/AAAAAAAAAe0/KgCf2qZhOVg/s1600/Unplanneditemschartstartday9.png"&gt;&lt;img src="http://3.bp.blogspot.com/-5LxWcCTRHrY/TleJjAl94zI/AAAAAAAAAe0/KgCf2qZhOVg/s400/Unplanneditemschartstartday9.png" name="immagini13" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;... so the activities can be parallelized:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645134244791526690"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-tFfazPMnrpw/TleLr7oxJSI/AAAAAAAAAe8/c_vHXY7pmNI/s1600/Unplanneditemschartstartday9-2.png"&gt;&lt;img src="http://2.bp.blogspot.com/-tFfazPMnrpw/TleLr7oxJSI/AAAAAAAAAe8/c_vHXY7pmNI/s400/Unplanneditemschartstartday9-2.png" name="immagini14" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Day 10: the unplanned activity is done:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645134928025292578"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://1.bp.blogspot.com/-Ed125Q_DBl0/TleMTs4ZDyI/AAAAAAAAAfE/vNSZ1v4owjI/s1600/Unplanneditemschartstartday10.png"&gt;&lt;img src="http://1.bp.blogspot.com/-Ed125Q_DBl0/TleMTs4ZDyI/AAAAAAAAAfE/vNSZ1v4owjI/s400/Unplanneditemschartstartday10.png" name="immagini15" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;One of the two guys is free, and to is (legitimately) taking a slack. We make evident this as well, so we will be able to consistently count all the checkmarks at the end of the sprint (for example about counting the actual man day available in the sprint).&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645136265067737394"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://1.bp.blogspot.com/-a1bNTxu57qE/TleNhhwJsTI/AAAAAAAAAfM/H0D6r1hGrYE/s1600/Unplanneditemschartstartday10-2.png"&gt;&lt;img src="http://1.bp.blogspot.com/-a1bNTxu57qE/TleNhhwJsTI/AAAAAAAAAfM/H0D6r1hGrYE/s400/Unplanneditemschartstartday10-2.png" name="immagini16" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Day 11. All is done, and the Sprint is at the end:&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645137505083084706"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-qWMAMEvql3E/TleOptK2T6I/AAAAAAAAAfU/NSmF0dVh0bA/s1600/Unplanneditemschartstartday11.png"&gt;&lt;img src="http://2.bp.blogspot.com/-qWMAMEvql3E/TleOptK2T6I/AAAAAAAAAfU/NSmF0dVh0bA/s400/Unplanneditemschartstartday11.png" name="immagini17" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;What we can see here:&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;- the amount of the black checkmarks is the total of the man days that were available during the sprint&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;- the amount of the black checkmarks on the planned items is the numbers of man days spent on what was decided during the sprint plan.&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;- the amount of the red checkmarks shows how much time some activities have been spent in blocked state because of urgent unplanned items.&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;- the burn up chart,  and the total of the black checkmark on the unplanned items and the slacks, they both show how much time is subtracted form the planned items.&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;- the burn down works is showing the remaining to work story points, as usual.&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;About the sprint velocity:&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;the velocity here is 10 story points. However what if the unplanned items and the slack were "invisible"?&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;1) we could have reported that in "ten man days" we have been able to work on twenty story points, so that the day man velocity is 0.5 story point.&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;2) we may have given the false perception that it is OK adding unplanned items during the sprint.&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;3) we forget to consider those data, and so we are not able to see them retrospectively in order to set some improvement direction during the retrospective meeting.&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;In this way we could know the Expected Value of the velocity of the Sprint if there were no interruptions.&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;To calculate it we  just have to multiply the story points with the ratio between the available man days and the man days spent on actual planned items:&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;10 * 20 / 15 = 13.33&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;We can easily find, dividing this value with 20 (man days available on the sprint), that the average story point for man day is approx 0.66 (not 0.5). &lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;Thus we can have a better projection on the "actual" velocity, and we can understand what would happen if we remove the interruption (as should be) on the next sprint.&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;We may also discuss about what really will make us slower, just in case (external interruption or bad code quality?). For example, according the the "quality of non declining velocity model" if the problem is low code base quality, the effect will be the net velocity, and of course if the problem is interruption, the effect is the total velocity.&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;May be we have also both, so then it is much difficult to decide what to do.&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;Here we can see how to reason about those data, for example when we have a retrospective.&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;We know how much is the gap between the average velocity and the actual velocity for any item.&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;For example. The A item, had an estimate of 3 story point, and toke 3 man days. According to the actual "net velocity" the expectation of story points done in three days is 0.66 * 2 = 2. So this story has a +1 respect of the estimation.&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;Let's make some calculations about all these actual vs estimated &lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;(p.s. and note that thought the comparison uses time, there are no actual time based estimates).&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;a href="http://3.bp.blogspot.com/-R5zRGqFXAQA/Tmjxwbef4nI/AAAAAAAAAgs/jzxrhGSuFvk/s1600/Unplanneditemsmetricscorr.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://3.bp.blogspot.com/-R5zRGqFXAQA/Tmjxwbef4nI/AAAAAAAAAgs/jzxrhGSuFvk/s400/Unplanneditemsmetricscorr.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5650031546847978098" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 800px; height: 600px; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;In interesting game is setting out the items up on a X,Y axis (X is the timeline, and Y is the distribution of the gab between the actual and expected time, according to the net velocity):&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; display: inline !important; "&gt;&lt;span&gt;&lt;img src="http://1.bp.blogspot.com/-WTlNKtwknWM/TlizC6JXbvI/AAAAAAAAAf8/bPE1ydoOjIE/s400/CopyofCopyofUnplanneditemsmetrics.png" name="immagini19" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="font-style: normal; "&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;(We don't care about the Y of slacks or unplanned items because are not estimated and shouldn't)&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;Moreover, if the item are proper tasks (instead of generic items) we can introduce more dimentions to this diagram, using color for tech areas, and symbols from the skill matrix.&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;(task are not supposed to have story points, but that does not matter so much.  We can still distribute story points of a story to it's tasks, for instance)&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;So now, dividing the items per tech area (that makes perfectly sense), we can see something like:&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="text-decoration: underline; -webkit-text-decorations-in-effect: none; "&gt;&lt;a href="http://1.bp.blogspot.com/-3E4I7-16erY/Tl5Xvgv2PMI/AAAAAAAAAgU/gPvNuvT_zR0/s1600/CopyofTaskTimeLine.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://1.bp.blogspot.com/-3E4I7-16erY/Tl5Xvgv2PMI/AAAAAAAAAgU/gPvNuvT_zR0/s400/CopyofTaskTimeLine.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5647047456525270210" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 800px; height: 600px; " /&gt;&lt;/a&gt;&lt;/span&gt;In blue items we performed better than the others. &lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;One of the reason could be that the people that worked on them were not so much skilled in that area. To make it evident we could have added the values taken from the &lt;a href="http://blog.crisp.se/henrikkniberg/2009/02/27/1235769840000.html"&gt;skill matrix&lt;/a&gt; when working on that item.&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;Tipically each entry in the skill matrix is empty, has a dot, or a star.&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;Wen we rearrange the item at the end of the sprint we could have something like follows (I replaced the dot with a 'x'):&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;a href="http://4.bp.blogspot.com/-pGxIFZ9yQEA/Tl5dacK-WuI/AAAAAAAAAgc/NTNviuXiwyU/s1600/TaskTimeLine%2B%25282%2529.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;span class="Apple-style-span"&gt;&lt;img src="http://4.bp.blogspot.com/-pGxIFZ9yQEA/Tl5dacK-WuI/AAAAAAAAAgc/NTNviuXiwyU/s400/TaskTimeLine%2B%25282%2529.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5647053691589384930" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 800px; height: 600px; " /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="text-align: justify;"&gt;It's perfectly clear that the guys that worked on the area that performed well, are skilled in there, and that may be the most likely reason for the performance, so we don't worry too much about, except that we may have some new challenge, as improve some skill in some area where we are weaker. &lt;/div&gt;&lt;div style="text-align: justify;"&gt;In other cases, for example when the skill matrix data are randomly distributed on the Y axis, our finding can be different (for example that the skill matrix need to be updated realizing that our team became more cross functional).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Some actions that can be taken about the relevance of some weakest area, is the re-estimation of components that are more closer to some area where we realized are weaker than expected.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Or we may adjust the skill matrix in a more realistic way, and so on...&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-style: italic; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-style: italic; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-style: italic; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt; &lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-8403859098045970863?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/8403859098045970863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=8403859098045970863' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8403859098045970863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8403859098045970863'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2011/09/measurment-is-quantitatively-expressed.html' title='Unplanned items, velocity and prisoner check-mark tecnique'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-bKTmn1dS8io/TlnV1QuwZUI/AAAAAAAAAgM/eHXcDLS5WDM/s72-c/Unplanneditemschartstartday10-2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-5609606672161554030</id><published>2011-08-25T14:45:00.073+02:00</published><updated>2011-09-18T07:55:56.364+02:00</updated><title type='text'>Non era nello Sprint Backlog: item non pianificati, e tecniche del prigioniero</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;i&gt;&lt;p style="font-style: italic; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; display: inline !important; "&gt;&lt;i&gt;&lt;span class="Apple-style-span"&gt;-&lt;a href="http://members.thebusinesssource.com/membersanew/archivedispbook.php?pass=howtomeasureanything&amp;amp;mx=201010HRMAM5&amp;amp;prm=TEPALL&amp;amp;month=201108&amp;amp;book1=talktoanyonenonresponder&amp;amp;book2=teamgamesstackup&amp;amp;tip1=&amp;amp;tip2="&gt;Una misura è una riduzione di incertezza espressa quantitativamente sulla base di una o più osservazioni&lt;/a&gt;. - (Douglas W. Hubbard - How to Measure Anything)&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;i&gt;&lt;p style="font-style: italic; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; display: inline !important; "&gt;&lt;i&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;i&gt;&lt;p style="font-style: italic; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; display: inline !important; "&gt;&lt;i&gt;&lt;span class="Apple-style-span"&gt;- &lt;a href="http://en.wikipedia.org/wiki/Good_Regulator"&gt;Ogni Buon Regolatore di un sistema deve essere un modello di quel sistema&lt;/a&gt; (R.G. Conant, W.R. Ashby)&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: center; "&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"&gt;&lt;p style="font-style: italic; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;/p&gt;&lt;p align="LEFT" style="text-align: left;font-style: italic; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/p&gt;&lt;p style="font-style: italic; "&gt;&lt;/p&gt;&lt;p style="font-style: italic; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;a href="http://1.bp.blogspot.com/-bKTmn1dS8io/TlnV1QuwZUI/AAAAAAAAAgM/eHXcDLS5WDM/s1600/Unplanneditemschartstartday10-2.png" style="font-style: normal; " onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://1.bp.blogspot.com/-bKTmn1dS8io/TlnV1QuwZUI/AAAAAAAAAgM/eHXcDLS5WDM/s400/Unplanneditemschartstartday10-2.png" alt="" id="BLOGGER_PHOTO_ID_5645778718886487362" border="0" style="text-align: left; display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; cursor: pointer; width: 400px; height: 300px; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;/span&gt;&lt;/i&gt;&lt;p align="LEFT" style="margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Vediamo qualche modo per visualizzare informazioni "non standard" sulla taskboard.&lt;/span&gt;&lt;/p&gt;&lt;div style="text-align: center; "&gt;&lt;p align="LEFT" style="font-style: normal; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Ciò che non è stato deciso in fase di Sprint Planning Meeting, proposto dal P.O. e stimato dal team, non dovrebbe esistere.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Tuttavia a volte garantirlo è difficile, c'è il "firefighting", emergenze non rimandabili che sopraggiungono. Come si può fare a mantenere comunque consistenti le informazioni degli information radiator e le relative misure?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Mettiamo di avere nello sprint backlog quattro items per un totale di 10 story point.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Diciamo che il team è composto da due persone (poche rispetto allo standard, ma è per semplificare) e che lavora su generici "item" dotati di stima in story point.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Giorno 0. Nello sprint backlog ci sono quattro item:&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; "&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5644819774683781842"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-SGgQUkEVvRE/TlZtrXMgmtI/AAAAAAAAAdU/KkvsK1uW8DY/s1600/unplanneditemschart.png"&gt;&lt;img src="http://2.bp.blogspot.com/-SGgQUkEVvRE/TlZtrXMgmtI/AAAAAAAAAdU/KkvsK1uW8DY/s400/unplanneditemschart.png" name="immagini1" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Al primo giorno vengono selezionati e spostati in "doing" gli item A e B:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;a name="BLOGGER_PHOTO_ID_5644823885920059234"&gt;&lt;/a&gt;&lt;/u&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://2.bp.blogspot.com/-sA-AnzW2LcA/TlZxaqvnv2I/AAAAAAAAAdc/Sv7tA_Wa6Eo/s1600/UNPLANNEDCHARTSTARTDAY1.png"&gt;&lt;img src="http://2.bp.blogspot.com/-sA-AnzW2LcA/TlZxaqvnv2I/AAAAAAAAAdc/Sv7tA_Wa6Eo/s400/UNPLANNEDCHARTSTARTDAY1.png" name="immagini2" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Passa un giorno. La taskboard si presenta come segue:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5644825225670005042"&gt;&lt;/a&gt;&lt;span&gt;&lt;img src="http://4.bp.blogspot.com/-GZvAG-Vf_t0/TlZyops5kTI/AAAAAAAAAdk/QGN1woSc74g/s400/UNPLANNEDCHARTSTARTDAY2.png" name="immagini3" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Gli item che si trovano in doing sono stati marcati con una barretta per indicare che è passato un giorno, un po' come farebbe un prigioniero in una cella.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Nel giorno successivo le cose restano invariate, e viene aggiunta un'altra barretta ad entrambi gli item, mentre il burn down resta piatto.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;a name="BLOGGER_PHOTO_ID_5645101709653434386"&gt;&lt;/a&gt;&lt;/u&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://1.bp.blogspot.com/-HaMrmbzlFxo/TlduGIzX4BI/AAAAAAAAAds/DXrPsjalPpM/s1600/Unplanneditemschartstartday3.png"&gt;&lt;img src="http://1.bp.blogspot.com/-HaMrmbzlFxo/TlduGIzX4BI/AAAAAAAAAds/DXrPsjalPpM/s400/Unplanneditemschartstartday3.png" name="immagini4" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;All'inizio del quarto giorno risulta che l'item A è terminato, vengono sempre aggiunte le barrette per il tempo passato in "doing", il burndown si abbassa di tre punti...&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://4.bp.blogspot.com/-Lkke5roiuHE/TldxXJEao5I/AAAAAAAAAd0/co78WVAiHMg/s1600/Unplanneditemschartstartday4-1.png"&gt;&lt;img src="http://4.bp.blogspot.com/-Lkke5roiuHE/TldxXJEao5I/AAAAAAAAAd0/co78WVAiHMg/s400/Unplanneditemschartstartday4-1.png" name="immagini5" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;...e si  mette l'item C in doing:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;a name="BLOGGER_PHOTO_ID_5645107009409763346"&gt;&lt;/a&gt;&lt;/u&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://3.bp.blogspot.com/-7LD-VKV5qdA/Tldy6n7vyBI/AAAAAAAAAd8/hTqKC6KWO_Q/s1600/Unplanneditemschartstartday4.png"&gt;&lt;img src="http://3.bp.blogspot.com/-7LD-VKV5qdA/Tldy6n7vyBI/AAAAAAAAAd8/hTqKC6KWO_Q/s400/Unplanneditemschartstartday4.png" name="immagini6" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Passa un altro giorno, vengono aggiunte le barrette agli item che sono in "doing":&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;a name="BLOGGER_PHOTO_ID_5645107695426015378"&gt;&lt;/a&gt;&lt;/u&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://1.bp.blogspot.com/-v6JIVRWMxdo/TldzijixEJI/AAAAAAAAAeE/Mn7vsLF9MsQ/s1600/Unplanneditemschartstartday5.png"&gt;&lt;img src="http://1.bp.blogspot.com/-v6JIVRWMxdo/TldzijixEJI/AAAAAAAAAeE/Mn7vsLF9MsQ/s400/Unplanneditemschartstartday5.png" name="immagini7" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Il giorno 6 risulta terminato l'item B, e quindi viene preso in carico D:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645111472868463538"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://1.bp.blogspot.com/-XpOyayrSAq4/Tld2-bnOk7I/AAAAAAAAAeM/63zs9dZykSs/s1600/Unplanneditemschartstartday6.png"&gt;&lt;img src="http://1.bp.blogspot.com/-XpOyayrSAq4/Tld2-bnOk7I/AAAAAAAAAeM/63zs9dZykSs/s400/Unplanneditemschartstartday6.png" name="immagini8" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Durante la giornata C viene interrotto per far posto ad una attività imprevista (Unplan):&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;&lt;a name="BLOGGER_PHOTO_ID_5645112745815831474"&gt;&lt;/a&gt;&lt;/u&gt;&lt;span style="text-decoration: underline; "&gt;&lt;a href="http://1.bp.blogspot.com/-_6K3lmqUejc/Tld4Ihth87I/AAAAAAAAAeU/Wmpd4nOmOmo/s1600/Unplanneditemschartstartday6-middle.png"&gt;&lt;img src="http://1.bp.blogspot.com/-_6K3lmqUejc/Tld4Ihth87I/AAAAAAAAAeU/Wmpd4nOmOmo/s400/Unplanneditemschartstartday6-middle.png" name="immagini9" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Mediante un nuovo grafico "burn up" verrà tracciato &lt;/span&gt;il tempo che si spenderà in queste attività "unplanned":&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645113772597004082"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-FVKtFQR8dAY/Tld5ESxPRzI/AAAAAAAAAec/oCsmJkMMFuA/s1600/Unplanneditemsmiddleday6-2.png"&gt;&lt;img src="http://2.bp.blogspot.com/-FVKtFQR8dAY/Tld5ESxPRzI/AAAAAAAAAec/oCsmJkMMFuA/s400/Unplanneditemsmiddleday6-2.png" name="immagini10" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;A differenza del burndown, in questo grafico i valori dell'asse Y sono espressi in unità di tipo tempo-uomo, e non in story point.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;All'item C, che è rimasto in sospeso perché interrotto, viene aggiunta comunque una nuova barra, questa volta rossa, per mettere in evidenza la quantità di tempo in cui l'item è rimasto bloccato.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645130646306384354"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-nK9rRtgz6yc/TleIaePDaeI/AAAAAAAAAek/P0kte7o2xN4/s1600/Unplanneditemschartstartday7.png"&gt;&lt;img src="http://2.bp.blogspot.com/-nK9rRtgz6yc/TleIaePDaeI/AAAAAAAAAek/P0kte7o2xN4/s400/Unplanneditemschartstartday7.png" name="immagini11" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Sì continua allo stesso modo al giorno 8:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645131003908836690"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-jKCoRAy320Q/TleIvSaHzVI/AAAAAAAAAes/G-XoSP34HqA/s1600/Unplanneditemschartstartday8.png"&gt;&lt;img src="http://2.bp.blogspot.com/-jKCoRAy320Q/TleIvSaHzVI/AAAAAAAAAes/G-XoSP34HqA/s400/Unplanneditemschartstartday8.png" name="immagini12" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Nel giorno 9 l'attività D è terminata...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645131892479877938"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://3.bp.blogspot.com/-5LxWcCTRHrY/TleJjAl94zI/AAAAAAAAAe0/KgCf2qZhOVg/s1600/Unplanneditemschartstartday9.png"&gt;&lt;img src="http://3.bp.blogspot.com/-5LxWcCTRHrY/TleJjAl94zI/AAAAAAAAAe0/KgCf2qZhOVg/s400/Unplanneditemschartstartday9.png" name="immagini13" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;... quindi le attività in corso posso essere parallelizzate:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645134244791526690"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-tFfazPMnrpw/TleLr7oxJSI/AAAAAAAAAe8/c_vHXY7pmNI/s1600/Unplanneditemschartstartday9-2.png"&gt;&lt;img src="http://2.bp.blogspot.com/-tFfazPMnrpw/TleLr7oxJSI/AAAAAAAAAe8/c_vHXY7pmNI/s400/Unplanneditemschartstartday9-2.png" name="immagini14" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Al giorno 10 l'attività unplanned è terminata:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645134928025292578"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://1.bp.blogspot.com/-Ed125Q_DBl0/TleMTs4ZDyI/AAAAAAAAAfE/vNSZ1v4owjI/s1600/Unplanneditemschartstartday10.png"&gt;&lt;img src="http://1.bp.blogspot.com/-Ed125Q_DBl0/TleMTs4ZDyI/AAAAAAAAAfE/vNSZ1v4owjI/s400/Unplanneditemschartstartday10.png" name="immagini15" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Uno dei due membri del team è libero, e potrebbe aiutare l'altro componente del team o approfondire qualche argomento. Per "quadrare" i conti, si introduce un item fittizio "slack".&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645136265067737394"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://1.bp.blogspot.com/-a1bNTxu57qE/TleNhhwJsTI/AAAAAAAAAfM/H0D6r1hGrYE/s1600/Unplanneditemschartstartday10-2.png"&gt;&lt;img src="http://1.bp.blogspot.com/-a1bNTxu57qE/TleNhhwJsTI/AAAAAAAAAfM/H0D6r1hGrYE/s400/Unplanneditemschartstartday10-2.png" name="immagini16" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Il giorno 11 finisce lo sprint, e le attività sono tutte concluse:&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;a name="BLOGGER_PHOTO_ID_5645137505083084706"&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="http://2.bp.blogspot.com/-qWMAMEvql3E/TleOptK2T6I/AAAAAAAAAfU/NSmF0dVh0bA/s1600/Unplanneditemschartstartday11.png"&gt;&lt;img src="http://2.bp.blogspot.com/-qWMAMEvql3E/TleOptK2T6I/AAAAAAAAAfU/NSmF0dVh0bA/s400/Unplanneditemschartstartday11.png" name="immagini17" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;In sintesi:&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;- il totale delle barre nere è il numero di giorni/uomo che abbiamo avuto a disposizione durante lo sprint&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;- il totale delle barre nere degli item pianificati è il numero di giorni uomo spesi per quanto deciso durante lo Sprint Planning.&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;- le barre rosse rappresentano il tempo in cui certe attività sono rimaste "bloccate".&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;- il burn up chart,  oppure il totale delle barrette nere degli item non pianificati e degli slack, mostrano il tempo uomo speso in attività non pianificate.&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;- il burn down funziona al solito modo.&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Sulla velocità:&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;se gli item non pianificati e lo slack fossero rimasti "invisibili", avremmo detto che la velocità del team è stata di 10 story point, ma in realtà dei 20 giorni uomo a disposizione nello sprint, solo 15 sono stati utilizzati per gli item pianificati, altri 4 per un item non pianificato, e uno per lo "slack time".&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Possiamo ricavare la "velocità netta". &lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Perché dovremmo farlo?&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: italic; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="font-style: normal; "&gt;La velocità &lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;netta permette di conoscere il valore atteso di quella che sarebbe stata la velocità totale se lo Sprint non fosse stato "inquinato", e quindi rende confrontabili le velocità di sprint diversi.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Un modo rapido per calcolarla è moltiplicare il numero di story point portati a termine per il numero di giorni uomo dello sprint diviso il numero di giorni uomo effettivamente utilizzati per i planned items: 10 * 20 / 15 = 13.33&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Il numero medio di story point per giornata è 1.33. Siccome il team è di due sole persone, dividiamo per due per ottenere il numero medio di story point per giorno uomo: 0.66.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Oltre ad avere proiezioni sulla velocità "reale", si possono incrociare queste informazioni in altri modi, per esempio per discuterne in una retrospettiva.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Per ogni item sappiamo di quanto si è discostata la velocità rispetto alla media.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Per esempio per l'item A, stimato in 3 story point, la velocità effettiva è stata di 3 giorni uomo. La media degli story point in tre giorni è 0.66 * 3 = 2. Quindi per quella storia un "bilancio positivo" di 1 story point.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Questi valori possono essere aggiunti in rosso nelle user story.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Da notare che si compensano a vicenda e dunque la loro somma deve fare zero.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;a href="http://3.bp.blogspot.com/-R5zRGqFXAQA/Tmjxwbef4nI/AAAAAAAAAgs/jzxrhGSuFvk/s1600/Unplanneditemsmetricscorr.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://3.bp.blogspot.com/-R5zRGqFXAQA/Tmjxwbef4nI/AAAAAAAAAgs/jzxrhGSuFvk/s400/Unplanneditemsmetricscorr.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5650031546847978098" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 800px; height: 600px; " /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Si possono poi ordinare su una"timeline", sull'asse X rispetto al tempo, e sull'asse Y rispetto allo scostamento dalla media, per avere una visione di come sono distribuiti nell'arco dello sprint.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-decoration: underline; margin-bottom: 0cm; widows: 2; orphans: 2; display: inline !important; "&gt;&lt;span&gt;&lt;img src="http://1.bp.blogspot.com/-WTlNKtwknWM/TlizC6JXbvI/AAAAAAAAAf8/bPE1ydoOjIE/s400/CopyofCopyofUnplanneditemsmetrics.png" name="immagini19" vspace="5" width="800" align="BOTTOM" border="0" height="600" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; "&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;(La collocazione degli item di tipo unplan e slack è arbitraria rispetto all'asse Y.)&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Con la colorazione rispetto alle aree tecnologiche, possiamo anche vedere la correlazione di tali valori rispetto alle aree tecnologiche stesse.&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Per questo tipo di analisi anziché di item di tipo user story, parliamo di task.&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;I task sono legati alle componenti tecniche. In teoria non sarebbero da stimare in story point, ma possiamo assumere che "ereditano" il numero di story point attribuito dalla user story a cui appartenevano.&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Dalla distribuzione dei colori rispetto all'asse Y si può avere una visione di insieme su alcune criticità dello sprint:&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal; text-align: justify; margin-bottom: 0cm; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="text-decoration: underline; -webkit-text-decorations-in-effect: none; "&gt;&lt;a href="http://1.bp.blogspot.com/-3E4I7-16erY/Tl5Xvgv2PMI/AAAAAAAAAgU/gPvNuvT_zR0/s1600/CopyofTaskTimeLine.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://1.bp.blogspot.com/-3E4I7-16erY/Tl5Xvgv2PMI/AAAAAAAAAgU/gPvNuvT_zR0/s400/CopyofTaskTimeLine.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5647047456525270210" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 800px; height: 600px; " /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; "&gt;Sembra che gli item blu siano andati meglio del previsto, a differenza dei gialli.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Per spiegarcene le ragioni possiamo integrare&lt;span class="Apple-style-span"&gt; &lt;/span&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; queste viste anche valori relativi alle competenze della &lt;a href="http://blog.crisp.se/henrikkniberg/2009/02/27/1235769840000.html"&gt;skill matrix&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Tipicamente una entry nella skill matrix è vuota, oppure ha un punto, o un asterisco.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Quando un componente del team lavora su un task di una certa area tecnologica, ricopiamo sul task stesso il suo grado di competenza relativo, come da skill matrix, cioè  un asterisco, un punto o niente.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Nel redistribuire gli item alla fine dello sprint abbiamo qualcosa come:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;a href="http://4.bp.blogspot.com/-pGxIFZ9yQEA/Tl5dacK-WuI/AAAAAAAAAgc/NTNviuXiwyU/s1600/TaskTimeLine%2B%25282%2529.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;span class="Apple-style-span"&gt;&lt;img src="http://4.bp.blogspot.com/-pGxIFZ9yQEA/Tl5dacK-WuI/AAAAAAAAAgc/NTNviuXiwyU/s400/TaskTimeLine%2B%25282%2529.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5647053691589384930" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 800px; height: 600px; " /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span"&gt;&lt;p style="margin-bottom: 0cm; widows: 2; orphans: 2; display: inline !important; "&gt;&lt;/p&gt;&lt;/span&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"&gt;Si vede che gli item che sono andati meglio della media sono stati portati a termine da persone che secondo la skill matrix erano i più competenti in quell'area. Questo non sorprende.&lt;/span&gt;&lt;/div&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt;&lt;span class="Apple-style-span"&gt;Le informazioni che emergono possono essere interpretate in diversi modi: per esempio per ri-aggiornare la skill matrix,  per verificare se non siano state sottovalutate le complessità di particolari aree tecniche, e così via...&lt;/span&gt;&lt;/p&gt;&lt;div style="font-style: italic; "&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify; margin-bottom: 0cm; font-style: normal; widows: 2; orphans: 2; "&gt; &lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-5609606672161554030?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/5609606672161554030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=5609606672161554030' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5609606672161554030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5609606672161554030'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2011/08/non-era-nello-sprint-backlog-item-non.html' title='Non era nello Sprint Backlog: item non pianificati, e tecniche del prigioniero'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-bKTmn1dS8io/TlnV1QuwZUI/AAAAAAAAAgM/eHXcDLS5WDM/s72-c/Unplanneditemschartstartday10-2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-688127242833945729</id><published>2010-12-15T14:54:00.006+01:00</published><updated>2010-12-17T14:49:50.447+01:00</updated><title type='text'>codebreaker in javascript + underscore.js</title><content type='html'>Prosegue la versione in più linguaggi del &lt;a href="http://katas.softwarecraftsmanship.org/?p=27"&gt;codebreaker &lt;/a&gt;kata.&lt;br /&gt;Ora è la volta di una &lt;a href="http://vimeo.com/17779970"&gt;versione in javascript&lt;/a&gt;, che utilizza come ambiente &lt;a href="http://visionmedia.github.com/jspec/"&gt;jspec &lt;/a&gt;e &lt;a href="http://www.mozilla.org/rhino/"&gt;rhino&lt;/a&gt;., e usa la libreria &lt;a href="http://documentcloud.github.com/underscore/"&gt;underscore.js&lt;/a&gt;&lt;br /&gt;Tali ambienti sono installati in una macchina virtuale Ubuntu.&lt;br /&gt;Per i primi 10 secondi c'è un po' di blink dello schermo, e la musica di sottofondo parte dopo qualche minuto.&lt;br /&gt;Lo screenacast include la parte di inizializzazione del progetto, per i primi due minuti e mezzo, il tempo netto di esecuzione è poco più di 10 minuti.&lt;br /&gt;&lt;br /&gt;La sequenza dei test è la seguente:&lt;br /&gt;(nota: tutte le funzioni che iniziano con _. fanno parte della libreria "underscore.js")&lt;br /&gt;&lt;br /&gt;time, guess   secret: [commento] -&gt; answer&lt;br /&gt;&lt;br /&gt;3:00 - "xxxx" "rgby": nessun match -&gt; ""&lt;br /&gt;&lt;br /&gt;3:25 -  "yxxx" "rgby": un match imperfetto (prima posizione)-&gt; "n" (risolto con un if)&lt;br /&gt;&lt;br /&gt;3:55 -  "xyxx" "rgby": un match imperfetto (seconda posizione) -&gt; "n" (risolto con un or aggiunto all'if precedente)&lt;br /&gt;&lt;br /&gt;4:10 - . refactoring -&gt; i due or dell'if precedente vengono trasformati in un ciclo for su tutti gli elementi del guess (e questo significa che il codice sarà in grado di gestire anche i singoli match imperfetti in terza e quarta posizione, anche se non viene scritto nessun ulteriore test di questo tipo).&lt;br /&gt;&lt;br /&gt;4:35 - "byxx" "rgby" : due match imperfetti -&gt; nel ciclo for, in caso di match, si accumula il risultato da restituire (concatenazione di 'm'), anziché uscire immediatamente. Questo intuitivamente risolve altri casi di match imperfetti (di diverso numero e diverse posizioni) e quindi non vengono aggiunti altri casi di test simili.&lt;br /&gt;&lt;br /&gt;0:51 .refactoring -&gt; il ciclo for viene rimpiazzato dal costrutto _.each&lt;br /&gt;&lt;br /&gt;5:30 "yyxx" "rgby" -&gt; un solo  match "m" anziché due, perché la 'y' occorre una volta nel secret. Soluzione: ogni volta che viene contato un match, il relativo colore viene rimosso dal secret stesso, così non verrà più contato. (nota: non è così banale "dedurre" questo "requisito" imo).&lt;br /&gt;&lt;br /&gt;6:30 .refactoring: viene estratto il metodo che restituisce, da una stringa, la stessa senza uno specifico carattere (nota: lì introduco un bug perché aggiungo la chiamata al nuovo metodo senza cancellare il codice che esegue la rimozione, quindi la rimozione viene fatta due volte: il bug viene scoperto e corretto più avanti.&lt;br /&gt;&lt;br /&gt;7:22 .refactoring -&gt; trasformo la chiamata _.each() nella chiamata _.reduce(). Questo consente di eliminare l'uso di una variabile di accumulazione del risultato (toReturn) e di tagliare due righe. (nota avrei dovuto accorgermi del baco descritto sopra perché la riga in questione ha una lunghezza sospetta)&lt;br /&gt;&lt;br /&gt;8:02 .refactoring -&gt; l'intenzione è di separare la logica del conteggio del numero dei match dal fatto di volerlo rappresentare in una stringa di 'm'. Dal metodo mark così creato, ne creo uno nuovo (countNonPositionals), che anziché accumulare in una stringa tanti 'm' quanti sono i match non positionali, li accumula in un numero (a questo punto lui non sa come sarà presentato il risultato)&lt;br /&gt;&lt;br /&gt;8:16 .refactoring -&gt; eseguo una combinazione di _.reduce e _.range applicata alla funzione countPositionals per ottenere una concatenazione di m pari al numero di match non positionali (e questo sostituisce l'attuale funzionalità della "mark")&lt;br /&gt;&lt;br /&gt;8:51 .refactoring -&gt; introduco un metodo apposito che trasforma un numero in una sequenza di caratteri&lt;br /&gt;&lt;br /&gt;10:00 "rxxx" "rgby" : match perfetto in prima posizione -&gt; duplico i metodi mark e  countNonPositionals in positionalMatch e countPositionals. Usano la stessa logica, salvo accumulare le 'p' al posto delle 'm' e usare la logica di confronto posizione per posizione, anziché la logica del "contiene". Viene anche tolta la chiamata alla rimozione dei caratteri che matchano (comincio ad accorgermi che qualcosa non va, a riguardo della logica di rimozione duplicata, ma non metto ancora a posto il bug ereditato nel punto originario, cioè nella countNonPositionals).&lt;br /&gt;&lt;br /&gt;11:30 refactoring del test (o correzione di errore nel test stesso) -&gt; devo chiamare la positionalMatch anziché la mark (che solo dopo unificherà entrambe le logiche).&lt;br /&gt;&lt;br /&gt;11:36 nuovi test: match posizionale in seconda posizione e doppio match posizionale (non cambio nulla del codice perché già passa questi test)&lt;br /&gt;&lt;br /&gt;12:13 il test che chiama la logica del match posizionale, ora chiama la mark stessa (che fin'ora contava solo i match non posizionali). -&gt; inizio a concatenare le logiche delle due chiamata (non chiamo esplicitamente la positionalMatch perché in teoria è destinata a scomparire), mi accorgo che anziché restituire "p" viene restituito "pm" e presumo che il non posizionale "intruso" 'm' sia un riconteggio come "match non posizionle" di quello precedente. Posso risolvere elimino dal conteggio dei non posizionali, il numero dei posizionali. Lo faccio clonando la countNonPositionals in countAnyMatch, e poi trasformando la countNonPositionals in modo che restituisca il valore della chiamata a countAnyMatch cui viene sottratto il risultato della chiamata a countPositionals (togliendo cioè il falsi non posizionali).&lt;br /&gt;Da lì in poi ci sono vari casi di test significativi che passano, dal che si comincia a pensare che siamo arrivati all'algoritmo giusto, salvo la correzione del bug, come da punto seguente:&lt;br /&gt;&lt;br /&gt;14:45  "rryy" "yyrr" -&gt; mi aspetto quattro match imperfetti, ne vengono fuori solo due a causa del bug della doppia rimozione in caso di match nella countAnyMatch (ex countNonPositionals). Dopo un attimo di incertezza elimino il bug.&lt;br /&gt;&lt;br /&gt;Conclusioni: è un po' più complicato della versione originaria in C#, ma forse il risultato finale è più espressivo, almeno per quanto riguarda la funzione "mark".&lt;br /&gt;È quasi completamente stateless, e l'uso della libreria _. avvicina la soluzione a quello che si farebbe tipicamente con linguaggi funzionali o estensioni come LinQ.&lt;br /&gt;&lt;br /&gt;In teoria non è previsto che in un "kata" con un bug introdotto e poi corretto, ma è comunque interessante.&lt;br /&gt;&lt;br /&gt;Nel libro di Rspec lo stesso problema viene trattato in vari modi. Sarebbe da riguardare per qualche confronto.&lt;br /&gt;&lt;br /&gt;Ciao.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-688127242833945729?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/688127242833945729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=688127242833945729' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/688127242833945729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/688127242833945729'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/12/codebreaker-in-javascript-underscorejs.html' title='codebreaker in javascript + underscore.js'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-3047825448040127991</id><published>2010-11-12T12:42:00.009+01:00</published><updated>2010-11-12T15:47:42.383+01:00</updated><title type='text'>NUnit Growl Notification</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_bUxSGU1m8WY/TN1IFuA6PZI/AAAAAAAAAXE/tUHLr0_wbAs/s1600/nonoktest.png"&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_bUxSGU1m8WY/TN1C6hz8mUI/AAAAAAAAAW8/q_CEGtoYjmI/s1600/screenshotgreen.png"&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;This is a simple explaination of the NUnit growl notification AddIn.&lt;br /&gt;&lt;a href="https://github.com/tonyx/NUnitGrowlAddIn"&gt;https://github.com&lt;/a&gt;&lt;a href="https://github.com/tonyx/NUnitGrowlAddIn"&gt;/tonyx/NUnitGrowlAddIn&lt;/a&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;It has been tested on &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_bUxSGU1m8WY/TN1ISxAbYuI/AAAAAAAAAXM/-x-3IRNcpxs/s1600/nonoktest.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 248px; height: 374px;" src="http://2.bp.blogspot.com/_bUxSGU1m8WY/TN1ISxAbYuI/AAAAAAAAAXM/-x-3IRNcpxs/s400/nonoktest.png" alt="" id="BLOGGER_PHOTO_ID_5538662603965555426" border="0" /&gt;&lt;/a&gt;NUnit 2.5.5. and NUnit 2.5.7.&lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;Here is the main documentation about writing NUnit plugins:&lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;&lt;a href="http://nunit.org/index.php?p=nunitAddins&amp;amp;r=2.5.8"&gt;http://nunit.org/index.php?p=nunitAddins&amp;amp;r=2.5.8&lt;/a&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;As far as I know to build it correctly you need to add the proper versions of nunit and growl assemblies in the lib directory. In this way I got working builds for Nunit 2.5.5 and 2.5.7.&lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;I tested them in two differenet Windows 7 machines, 64 bit arch.&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;The target framework is 3.5, and works under 4.0 as well.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;The binaries included are for NUnit 2.5.7.&lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_bUxSGU1m8WY/TN1IcKJiN2I/AAAAAAAAAXU/BYJsdcjgboo/s1600/oktest.png"&gt;&lt;img style="float: right; margin: 0pt 0pt 10px 10px; cursor: pointer; width: 246px; height: 174px;" src="http://2.bp.blogspot.com/_bUxSGU1m8WY/TN1IcKJiN2I/AAAAAAAAAXU/BYJsdcjgboo/s400/oktest.png" alt="" id="BLOGGER_PHOTO_ID_5538662765333460834" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;However I included prebuild binaries for Nunit 2.5.7.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;I encourage people to rebuild it and test in other platforms.&lt;br /&gt;&lt;br /&gt;I found an&lt;a href="http://nunitgrowladdin.codeplex.com/"&gt; equivalent project&lt;/a&gt;, but no compatibile with other version but Nunit 2.5.5.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;I need those tools for games like doing katas with continuous test/build and so on.&lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;Another useful project at it is autobuild:&lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;&lt;a href="http://code.google.com/p/autobuildtool/"&gt;http://code.google.com/p/autobuildtool/&lt;/a&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt;Hopefully stuffs like those will be used also when writing production code, and no just katas, to make you focus on TDD cycle. &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Here is, essentially, how does it work:&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;the interfaces implemented are  Iaddin and EventListener&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;the constructor instantiates the  notification types and register them to the growlconnector&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;the Install method actually  registers the instance in order to make it recognized as an  EventListener for nunit related events (suitestarted, teststarted  and son on...)&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;the custom behaviour (notification  to growl) is coded in methods like RunFinished an so on..&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;My aim was to visualize, after each build (actually continuous build, using autobuild):&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;an ok, greeen, notification when  all the test passes, with the number of test passed&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;a non ok, red, notification when  at least one test fails or has an error, with the number of failures  and errors, and the number of total tests as well&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;"&gt;a non ok, red, notification for  each failed test, with the actual and expected values specified.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;So there will be one green notification of the number of failing and error tests +1 after each build (actually, each source file saved, if using autobuild).&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;In normal tdd ciclye you will get one green notification or two red notifications, that should be a good reminder that you are supposed to actually work on the failing test to get rid of them.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;Some screenshots:&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;a href="http://2.bp.blogspot.com/_bUxSGU1m8WY/TN1CrIuyJ_I/AAAAAAAAAW0/f6WfO7rTVkI/s1600/screenshotred.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 644px; height: 402px;" src="http://2.bp.blogspot.com/_bUxSGU1m8WY/TN1CrIuyJ_I/AAAAAAAAAW0/f6WfO7rTVkI/s400/screenshotred.png" alt="" id="BLOGGER_PHOTO_ID_5538656425581094898" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;A screenshot of a failing test:&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;a href="http://2.bp.blogspot.com/_bUxSGU1m8WY/TN1C6hz8mUI/AAAAAAAAAW8/q_CEGtoYjmI/s1600/screenshotgreen.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 619px; height: 386px;" src="http://2.bp.blogspot.com/_bUxSGU1m8WY/TN1C6hz8mUI/AAAAAAAAAW8/q_CEGtoYjmI/s400/screenshotgreen.png" alt="" id="BLOGGER_PHOTO_ID_5538656690011674946" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;A two and half minutes video:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://player.vimeo.com/video/16750261" width="400" frameborder="0" height="300"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://vimeo.com/16750261"&gt;Nunit AddIn for Growl&lt;/a&gt; from &lt;a href="http://vimeo.com/user2906925"&gt;tonyx&lt;/a&gt; on &lt;a href="http://vimeo.com/"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;Thanks for reading, feedback are welcome.&lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-3047825448040127991?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/3047825448040127991/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=3047825448040127991' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3047825448040127991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3047825448040127991'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/11/nunit-growl-notification.html' title='NUnit Growl Notification'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_bUxSGU1m8WY/TN1ISxAbYuI/AAAAAAAAAXM/-x-3IRNcpxs/s72-c/nonoktest.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-3606923504647251978</id><published>2010-10-25T22:37:00.013+02:00</published><updated>2010-10-29T19:02:24.811+02:00</updated><title type='text'>Codebreaker in F#</title><content type='html'>(english version of this post comes later, may be :D )&lt;br /&gt;&lt;br /&gt;Ho studiato un po' di F#, finalizzando lo studio ad un kata, quello del codebreaker (marking guess), già a suo tempo affrontato in C# (&lt;a href="http://www.vimeo.com/13072671"&gt;http://www.vimeo.com/13072671&lt;/a&gt;)   (ma che non ho mai commentato).&lt;br /&gt;&lt;br /&gt;Ecco il link di questa nuova versione in F#: &lt;a href="http://www.vimeo.com/16177730"&gt;http://www.vimeo.com/16177730&lt;/a&gt;   &lt;a href="http://vimeo.com/16155666"&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://player.vimeo.com/video/16177730" frameborder="0" height="300" width="400"&gt;&lt;/iframe&gt;&lt;p&gt;&lt;a href="http://vimeo.com/16177730"&gt;codebreaker, marking guess, in F#&lt;/a&gt; from &lt;a href="http://vimeo.com/user2906925"&gt;tonyx&lt;/a&gt; on &lt;a href="http://vimeo.com/"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Imparare un linguaggio nuovo è stato uno dei miei buoni propositi quando  sono tornato dalla &lt;a href="http://parlezuml.com/softwarecraftsmanship/"&gt;Software Craftsmanship conference&lt;/a&gt; tenutasi a Bletchley Park il 7 ottobre. A proposito: non ho scritto nessun post sull'argomento. Forse è un po' tardi per questo, vabbe', sopravvoliamo.&lt;br /&gt;&lt;br /&gt;Un commento, a grandi linee su questo  codebreaker in F#&lt;br /&gt;&lt;br /&gt;Uso un piccolo wrapper (gu' presente nel file sorgente) che consente l-uso stringhe anziché liste in modo da poter scrivere "xxxx" anziché  ['x';'x';'x';'x'].&lt;br /&gt;&lt;br /&gt;Oppure un test del tipo AssertEquals(['m'] , guess ['y'; 'x';'x';'x'] ['r';'g';'b';'y'] )  lo posso scrivere così shouldBe "m" guess "yxxx" "rgby"&lt;br /&gt;&lt;br /&gt;È zucchero sintattico.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Nella sostanza: non si tratta di una mera trasposizione in F# dell'algoritmo usato nella versione C#.&lt;br /&gt;&lt;br /&gt;Ho tentato  soprattutto di sfruttare  le caratteristiche di questo linguaggio ed in particolare dei costrutti ricorsivi, e poi ho fatto un po' più di refactoring, e di separazione di responsabilità (anche se penso che siano mancati alcuni passi alla fine).&lt;br /&gt;&lt;br /&gt;Per esempio:&lt;br /&gt;&lt;br /&gt;nel secondo test il colore corretto (ma che non è non nella giusta posizione) è il primo, e siccome uso il pattern matching [H::T] dove H è la testa della lista, viene facile usare H per la logica che mi serve ai fini del caso rappresentato dal test, e tenere la coda T per il resto (la chiamata ricorsiva).&lt;br /&gt;&lt;br /&gt;Il codice per passare il secondo test è&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let mark guess secret =&lt;br /&gt;match guess with&lt;br /&gt;| H::T when List.contains H -&gt; ['m']&lt;br /&gt;| _ -&gt; []&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Il codice per passare il terzo test (in cui il match è il secondo elemento, ovvero la testa della coda T) è:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let &lt;span style="font-style: italic;"&gt;rec &lt;/span&gt;mark guess secret&lt;br /&gt;match guess with&lt;br /&gt;|H::T when List.contains H secret -&gt; ['p']&lt;br /&gt;&lt;span style="font-style: italic;"&gt;|H::T -&gt; mark T secret&lt;/span&gt;&lt;br /&gt;_ -&gt; []&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notare ce ho aggiunto il "rec" (per dire al compilatore che mark verrà chiamata ricorsivamente) ed ho eseguito la chiamata ricorsiva sulla coda (mark T secret).&lt;br /&gt;&lt;br /&gt;Il caso aggiuntivo del doppio match si risolve aggiungendo, in caso di match, oltre alla 'p',  il risultato della chiamata ricorsiva in coda (mark T secret)&lt;br /&gt;&lt;br /&gt;Non ho intenzione di spiegare tutto il kata, e sorvolo il caso dei test sui match non posizionali perché è del tutto analogo.&lt;br /&gt;&lt;br /&gt;Mi limito ad osservare che verso la fine un po' di lavoro viene fatto per togliere alle funzioni di match posizionale e non posizionale la responsabilità di costruire il risultato (sequenze d 'p' ed 'm') e spostarlo verso un'altra funzione, facendo in modo che suddette funzioni si limitino a contare i match, lasciando ad altri il compito di rappresentarlo con dei 'p' 'm', o come si vuole.&lt;br /&gt;&lt;br /&gt;In soldoni, per esempio la funzione di calcolo dei match posizionali, è prima questa (che restituisce tanti 'p' quanti sono suddetti match):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec positionalMatch guess secret =&lt;br /&gt;match guess, secret with&lt;br /&gt;| H::T, H1, T1  when H = H1 -&gt; &lt;span style="color: rgb(51, 204, 0);"&gt;'p' @&lt;/span&gt; positionalMatch T T1&lt;br /&gt;| H::T, H1, T1 -&gt; positionalMatch T T1&lt;br /&gt;|  _  -&gt;&lt;span style="color: rgb(51, 204, 0);"&gt; []&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ma poi diventa questa&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec positionalMatch guess secret =&lt;br /&gt;match guess, secret with&lt;br /&gt;| H::T, H1, T1  when H = H1 -&gt;&lt;span style="color: rgb(51, 204, 0);"&gt; 1 +&lt;/span&gt; positionalMatch T T1&lt;br /&gt;| H::T, H1, T1 -&gt; positionalMatch T T1&lt;br /&gt;|  _  -&gt;&lt;span style="color: rgb(51, 255, 51);"&gt; 0&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;che appunto accumula il risultato in un numero, anziché in una sequenza.&lt;br /&gt;&lt;br /&gt;Per la trasformazione del numero in sequenza utilizzo questo trucchetto, che mostra qualche finezza di questo linguaggio:&lt;br /&gt;&lt;br /&gt;[1..count] |&gt; Seq.fold (fun acc x -&gt; acc @ ['p']) []&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;che più o meno potrebbe essere spiagato come:&lt;br /&gt;mandare la sequenza da uno fino a count in "pipeline" ad una funzione che opera accumulando un certo valore appendendovi un 'p' e partendo da una lista vuota, e restituendo alla fine tale risultato.&lt;br /&gt;&lt;br /&gt;In altri linguaggi sarebbe bastato forse scrivere qualcosa come ['p']*count, per ottenere la stessa cosa, ma comunque... sempre meglio che un ciclo for.&lt;br /&gt;&lt;br /&gt;Per finire:&lt;br /&gt;&lt;br /&gt;È facile intuire che il codice che conta i match non posizionali include nel conteggio anche quelli posizionali, cosa che non va bene nel risultato. Bisogna restituire questi match al netto dei match posizionali, che vanno indicati in modo diverso (con i 'p').&lt;br /&gt;&lt;br /&gt;Questo problema veniva risolto (nella vecchia versione del kata) con un trucchetto: eliminando dalla concatenazione del risultato posizionali + non posizionali un numero di caratteri pari ai posizionali stessi.&lt;br /&gt;&lt;br /&gt;Però se il risultato richiesto fosse stato invertito (prima i non posizionali e poi i posizionali) questa cosa non avrebbe funzionato.&lt;br /&gt;&lt;br /&gt;Per prevenire questo problema è meglio fare in modo che i non posizionali siano già al "netto" dei posizionali prima di concatenarli. In questo modo si introduce minore resistenza a certi cambiamenti desiderati (come questo di invertire le 'p' con le 'm').&lt;br /&gt;&lt;br /&gt;È un po' quanto fatto qui (anche se c'è spazio per miglioramenti), aiutati dal fatto che i match, dopo il refactoring,  vengono effettivamente contati, indipendentemente dal fatto che poi verranno rappresentati con dei 'p', dei 'm' o in un particolare ordine o altro.&lt;br /&gt;&lt;br /&gt;Ma non mi prolungo oltre, anche se da dire ne avrei.&lt;br /&gt;Penso che I kata non vadano commentati. Vanno fatti, vanno visti, vanno "goduti" e, ovviamente, vanno migliorati.&lt;br /&gt;&lt;br /&gt;Per riferimenti:&lt;br /&gt;&lt;br /&gt;La versione di Corey Haines (con una rapida introduzione del problema)&lt;br /&gt;&lt;a href="http://katas.softwarecraftsmanship.org/?p=27"&gt;http://katas.softwarecraftsmanship.org/?p=27&lt;/a&gt; (a sua volta presa dal testo su Rspec)&lt;br /&gt;&lt;br /&gt;La versione in IronPython di Mark Heath:&lt;br /&gt;&lt;a href="http://vimeo.com/15329417"&gt;http://vimeo.com/15329417&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;La mia versione in C#:&lt;br /&gt;&lt;a href="http://katas.softwarecraftsmanship.org/?p=168"&gt;http://katas.softwarecraftsmanship.org/?p=168&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-3606923504647251978?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/3606923504647251978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=3606923504647251978' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3606923504647251978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3606923504647251978'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/10/codebreaker-in-f.html' title='Codebreaker in F#'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-3631577646330449936</id><published>2010-09-15T00:38:00.008+02:00</published><updated>2010-09-18T14:06:35.545+02:00</updated><title type='text'>Qcv (Quality of non-declining velocity curve)</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/_bUxSGU1m8WY/S9rsDx6bntI/AAAAAAAAAUA/Z0PfQrRS6sA/s1600/Immagine1.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 693px; height: 516px;" src="http://3.bp.blogspot.com/_bUxSGU1m8WY/S9rsDx6bntI/AAAAAAAAAUA/Z0PfQrRS6sA/s320/Immagine1.png" alt="" id="BLOGGER_PHOTO_ID_5465940647449698002" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt; &lt;p style="margin-bottom: 0.5cm;" lang="en-US"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;span lang="en-US"&gt;This  curve is a sort of model about how theoretically the practices are  related to the quality, and how the quality is related to the velocity.&lt;br /&gt;&lt;br /&gt;Some practices related to the quality are very obvious, code convention, pair programming, for instance.&lt;br /&gt;&lt;br /&gt;The quality is related to the velocity because a good code base makes the next feature cheaper.&lt;br /&gt;At the other side, a bad code base means that you will go slower.&lt;br /&gt;&lt;br /&gt;The Qcv level so it is the "&lt;a href="http://peripateticaxiom.blogspot.com/2009_05_31_archive.html"&gt;quality of non declining velocity&lt;/a&gt;", a point such that you will keep the same velocity.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0.5cm;"&gt;&lt;span lang="en-US"&gt;&lt;br /&gt;Almost the same concept has been introduced under the name of the &lt;a href="http://blog.jbrains.ca/permalink/the-qualityspeed-barrier"&gt;quality/speed barrier&lt;/a&gt;,  that  can be said in this way: "there is a point where below it you need to go slower  to go better, but above it you go faster because you go better."  (&lt;a href="http://www.ustream.tv/recorded/4722190"&gt;said J.B. Rainsberger in this video 00:58&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;So how do we know where we are?&lt;br /&gt;Doing lesser and lesser story point at any iteration, means being under Qcv, seems to me.&lt;br /&gt;&lt;br /&gt;The main question is what to do then?&lt;br /&gt;Introducing "quick fix" is not a medicine to go faster because it means corrupting the code base, so it's even worst.&lt;br /&gt;&lt;br /&gt;Instead, some time must be spent to re-inject the lost quality.&lt;br /&gt;&lt;br /&gt;Can you convince the p.o. to do it? It's about how to convince the p.o. to accept tech stories.&lt;br /&gt;According to Henrik Kniberg, in "&lt;a href="http://www.infoq.com/minibooks/scrum-xp-from-the-trenches"&gt;Scrum and Xp from The Trenches&lt;/a&gt;"  it should be possible:&lt;/span&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;Team:  “We have some  internal tech stuff that needs to be done. We would like  to budget  10% of our time for that, i.e. reduc focus factor from 75%  to 65%.  Is that OK?”   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;Product owner: “Hell  no! We don’t have time!”   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;Team:  “Well, look  at the last sprint (all heads turn to the velocity scrawls  on the  whiteboard). Our estimated velocity was 80, and our actual  velocity  was 30, right?”   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;PO: “Exactly! So we  don’t have time to do internal tech stuff. We Need new features!”   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;Team:  “Well, the  reason why our velocity turned out to be so bad was because  we spent  so much time trying to put together consistent releases for   testing”.   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;PO: “Yes, and?”   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;Team: “Well, our  velocity will probably continue being that bad if we don’t do  something about it.”   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt; PO: “Yes,  and?”   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;  Team: “So we  propose that we take approximately 10% off of this sprint  to set up  a continuous build server and other stuff that   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;will  take the pain  off of integration. This will probably increase our  sprint velocity  by at least 20% for each subsequent sprint, forever!”    &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;PO: “Oh really? Why  didn’t we do this last sprint then?!”   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;Team: “Er...  because you didn’t want us to...”   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p lang="en-US"&gt;PO: “Oh, um, well fine, sounds like a good  idea to do it now then!”&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: italic;" lang="en-US"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: italic;" lang="en-US"&gt;p.s.  I spent some time thinking about the numbers of the example. Here is my ideas about:  if the team don't do tech stories, they will keep going slower: 30 story  points (instead of 80), so the focus factor will be 28% (instead of  75%).&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: italic;" lang="en-US"&gt;If  they will do the tech story at the next sprint, so they can come back  at a normal velocity of 80 story point (focus factor 75%) they need to  subtract the 10% of the time of the next sprint for it (and should do it  at the beginning of the sprint to capitalize as earlier as possible  this value). So there is left the 90% of the time of the next sprint  doing normal stories at the normal velocity, so the number of story points  will be 72,  instead of 80, and thus the focus factor should be 67.5%  (not far from the suggested value of 65%, actually), instead of 75%.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-3631577646330449936?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/3631577646330449936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=3631577646330449936' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3631577646330449936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3631577646330449936'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/09/qdv-quality-of-non-declining-velocity.html' title='Qcv (Quality of non-declining velocity curve)'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_bUxSGU1m8WY/S9rsDx6bntI/AAAAAAAAAUA/Z0PfQrRS6sA/s72-c/Immagine1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-1377135277223097557</id><published>2010-09-12T11:24:00.007+02:00</published><updated>2010-09-13T11:17:17.640+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prisoner dilemma'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='xp'/><category scheme='http://www.blogger.com/atom/ns#' term='tit for tat'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>Dilemma del prigioniero iterato e principi agili</title><content type='html'>&lt;p&gt;&lt;span lang="it-IT"&gt;Il modello del &lt;a href="http://en.wikipedia.org/wiki/Prisoner%27s_dilemma"&gt;dilemma del prigioniero&lt;/a&gt; mostra che la strategia più razionale, “defeat”, non è quella ottimale, tuttavia nel &lt;a href="http://en.wikipedia.org/wiki/Prisoner%27s_dilemma#The_iterated_prisoner.27s_dilemma"&gt;dilemma del prigioniero iterato&lt;/a&gt; esiste un evidente vantaggio usando strategie “irrazionali” (ma il termine più fortunato è “&lt;a href="http://en.wikipedia.org/wiki/Superrational"&gt;superrazionali&lt;/a&gt;”).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span lang="it-IT"&gt;Qui abbiamo una &lt;a href="http://jamesalliban.wordpress.com/2008/08/05/visualisation-of-prisoner%E2%80%99s-dilemma/"&gt;interessante rappresentazione visuale del processo&lt;/a&gt;.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;" lang="it-IT"&gt;I metodi agili sono secondo me un banco di prova interessante di questo modello.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;span lang="it-IT"&gt;Nel &lt;a href="http://agilemanifesto.org/"&gt;manifesto agile&lt;/a&gt; si parla di collaborazione, e nei metodi che si ispirano a questo manifesto sono previste le iterazioni, quindi, considerando una iterazione come una mossa, le strategie “superrazionali” del dilemma del prigioniero, basate sulla &lt;a href="http://en.wikipedia.org/wiki/Tit_for_tat"&gt;possibilita' di cooperare&lt;/a&gt; anche senza essere sicuri che tale cooperazione sia corrisposta, sembrano adeguate.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;" lang="it-IT"&gt;Per esempio:&lt;/p&gt; &lt;p style="margin-bottom: 0cm;" lang="it-IT"&gt;Il customer si aspetta che ad una prima iterazione venga portata a termine la feature 'A'.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;" lang="it-IT"&gt;Il customer la descrive nel suo linguaggio, il team la interpreta, e la implementa.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;span lang="it-IT"&gt;In linea di principio la descrizione che fa il customer della feature non potrà mai essere abbastanza precisa da non generare equivoci, altrimenti la descrizione stessa sarebbe talmente "&lt;a href="http://en.wikipedia.org/wiki/Effective_method"&gt;effettiva&lt;/a&gt;" da rappresentare un "programma" (cosa che spetta al team).&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;" lang="it-IT"&gt;Di principio sembra ineluttabile che il team alla fine dell'iterazione possa scoprire che quanto implementato non e' quello che voleva il customer.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;" lang="it-IT"&gt;La strategia “defeat” del customer sarebbe quella di innescare un conflitto basato su cose in linea di principio indimostrabili, o iniziare facendo descrizioni abbastanza vaghe da aumentare la probabilita' che qualcosa vada apparentemente storto, in modo da puntare ad un “blame game” in una posizione di vantaggio.&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;span lang="it-IT"&gt;La strategia “defeat” del team sarebbe invece quella di implementare l'interpretazione a loro più comoda della feature 'A', e non cercare di capire veramente le intenzioni del Customer, o di non proporgli gli strumenti (non necessariamente tecnici, vedi cap. 4 di “&lt;a href="http://www.infoq.com/minibooks/scrum-xp-from-the-trenches"&gt;Scrum and Xp from the Trenches&lt;/a&gt;”) più adatti per ridurre le incomprensioni.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;span lang="it-IT"&gt;(aggiungiamo pure la strategia “superirrational” del Customer che rifiuta di adottare questi strumenti, o quella “superirrational” del team che propone questi strumenti ma senza &lt;a href="http://blog.crisp.se/henrikkniberg/2010/09/01/1283373060000.html"&gt;coglierne le vere ragion&lt;/a&gt;i, - vedere anche alla voce “&lt;a href="http://en.wikipedia.org/wiki/Cargo_cult_science"&gt;cargo cult&lt;/a&gt;”)&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;span lang="it-IT"&gt;Usare sistematicamente il “defeat” nel modello del dilemma del prigioniero reiterato è una strategia perdente, e dunque è più accettabile per entrambi la strategia cooperativa dell'assumere il reciproco interesse a capirsi, e migliorarsi, cosa che rientra nei principi del &lt;a href="http://agilemanifesto.org/"&gt;manifesto agile&lt;/a&gt; e, a maggior ragione, del &lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;manifesto for software crafsmanship&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-1377135277223097557?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/1377135277223097557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=1377135277223097557' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/1377135277223097557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/1377135277223097557'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/09/dilemma-del-prigioniero-iterato-e.html' title='Dilemma del prigioniero iterato e principi agili'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-4229833915270264407</id><published>2010-09-12T00:15:00.006+02:00</published><updated>2010-09-12T21:58:39.065+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='kanban'/><category scheme='http://www.blogger.com/atom/ns#' term='lean'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>Washing the dishes using Kanban</title><content type='html'>&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;No irony. I think I experienced the Kanban principles when I was involved in washing the dishes in a restaurant. We were two of us committed in that activity, and there was no strict task division, though, nobody know why, it ended that I used to dry and the colleague to wash. Here is a picture of the phases:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_bUxSGU1m8WY/TIvd9nbSA4I/AAAAAAAAAWQ/jzPwb-YtcVE/s1600/piattikanban1.png"&gt;&lt;img style="float: right; margin: 0pt 0pt 10px 10px; cursor: pointer; width: 665px; height: 388px;" src="http://2.bp.blogspot.com/_bUxSGU1m8WY/TIvd9nbSA4I/AAAAAAAAAWQ/jzPwb-YtcVE/s400/piattikanban1.png" alt="" id="BLOGGER_PHOTO_ID_5515746219270472578" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt; &lt;/p&gt;&lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;It's quite obvious that there is the need to make sure that the less time as possible is spent from the beginning and the end of all the phases (lead time), that there is a natural wip limit given by the limited space available, and that a good indicator of problems are the "air bubles", and it's also obvious how to detect when we get close to the wip limit, because of the limited physical room available. Here I can show a case of reaching the wip limit because of a context switch.&lt;br /&gt;In my case the context switch used to happen when I were assigned the task of clean some mussles (which means, remove the linen), in order to be cooked. I had to interrupt my activity for a while to tho this. When I returned to the normal activity, the typical situation that I used to find was as follows:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_bUxSGU1m8WY/TIvgH3c0W-I/AAAAAAAAAWo/nWHwpJb76yQ/s1600/lavaggiopiatti3.png"&gt;&lt;img style="float: right; margin: 0pt 0pt 10px 10px; cursor: pointer; width: 651px; height: 398px;" src="http://1.bp.blogspot.com/_bUxSGU1m8WY/TIvgH3c0W-I/AAAAAAAAAWo/nWHwpJb76yQ/s400/lavaggiopiatti3.png" alt="" id="BLOGGER_PHOTO_ID_5515748594393832418" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p style="margin-bottom: 0cm;"&gt;&lt;span lang="en-US"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/p&gt;&lt;p style="margin-bottom: 0cm;"&gt;&lt;span lang="en-US"&gt;There is a bubble air in the "ready" state because while I was busy elsewhere, nobody was drying the dishes, and it's evident that it was a problem: the system was releasing nothing and so any activity related to the previous phases did not produce any value yet. The wip limit was reached for the items before the ready state.&lt;br /&gt;A mind set focused on the goal of getting things done mainly in order to produce a result, no matter how, could be taking a look at the state of the system, and act consequently, instead of just doing anybody some predefined activity (I wash, you dry, any other consideration is out of my business).&lt;br /&gt;From this point of view, for me the issue is not about if &lt;a href="http://www.gabrielelana.it/archives/174"&gt;Kanban is agile or not&lt;/a&gt; , but, moreover, that the system can show dysfunctions that you should care about as a whole team, in other word kanban is just a messenger, and so being agile or not is not a about kanban itself,  it's about you.&lt;br /&gt;&lt;br /&gt;In the same way, it's clear that this does not change "directly" the nature of the specific operations, that you cannot avoid: you have to pass those phases, unless you change completely the method - i.e. adopt a washing machine.&lt;br /&gt;&lt;br /&gt;There were no chance to do differently to optimize because we were not so many worker, and you can't predict how many context switches could happen for me or whoever, and so you had to "see" things, get the feedback and act consequently.&lt;br /&gt;&lt;br /&gt;Obviously, in the above example there were no need of any cards or board, because there is no need a symbolic representation to communicate something of a system that the system by itself already shows, but assuming you deal with situations where this is not true, so the system can't communicate directly his state, then you need a symbolic representation of it, and Kanban does it.&lt;br /&gt;&lt;br /&gt;Again, obviously, Kanban does not represent a working method, but with Kanban (and with Scrum as well) you have better chances to get the information needed in order to improve, and, then, may be, also pick up practices and methods that fit better. &lt;/span&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-4229833915270264407?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/4229833915270264407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=4229833915270264407' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/4229833915270264407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/4229833915270264407'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/09/wash-dishes-using-kanban.html' title='Washing the dishes using Kanban'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_bUxSGU1m8WY/TIvd9nbSA4I/AAAAAAAAAWQ/jzPwb-YtcVE/s72-c/piattikanban1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-5544722113797141149</id><published>2010-09-11T21:45:00.009+02:00</published><updated>2010-09-12T00:02:02.808+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='kanban'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>Lavare i piatti con Kanban</title><content type='html'>Non c'è ironia. Credo di aver sperimentato il concetto di Kanban quando lavavo i piatti in un ristorante. Eravamo in due in questa attività. In teoria non c'era alcuna divisione del lavoro specifica, anche se alla fine, non si sa perché, era più facile che io asciugassi e il collega lavasse. Ecco una immagine delle varie fasi:&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_bUxSGU1m8WY/TIvd9nbSA4I/AAAAAAAAAWQ/jzPwb-YtcVE/s1600/piattikanban1.png"&gt;&lt;img style="float: right; margin: 0pt 0pt 10px 10px; cursor: pointer; width: 665px; height: 388px;" src="http://2.bp.blogspot.com/_bUxSGU1m8WY/TIvd9nbSA4I/AAAAAAAAAWQ/jzPwb-YtcVE/s400/piattikanban1.png" alt="" id="BLOGGER_PHOTO_ID_5515746219270472578" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;è abbastanza ovvio che è necessario far passare il minor tempo possibile tra l'entrata all'uscita dal sistema (lead time),  che esiste un wip  limit naturale dovuto a motivi di spazio, e che un buon indicatore dei  problemi siano le "bolle d'aria" ed il superamento del wip limit, che  accadono per esempio in casi legati al context switch. Nel mio caso il problema del context switch era che periodicamente ero chiamato a pulire delle cozze (che significa rimuovere il bisso), perché fossero pronte per essere preparate in qualche piatto. Quando riprendevo l'attività dei piatti ecco un po' la situazione che trovavo:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_bUxSGU1m8WY/TIvgH3c0W-I/AAAAAAAAAWo/nWHwpJb76yQ/s1600/lavaggiopiatti3.png"&gt;&lt;img style="float: right; margin: 0pt 0pt 10px 10px; cursor: pointer; width: 651px; height: 398px;" src="http://1.bp.blogspot.com/_bUxSGU1m8WY/TIvgH3c0W-I/AAAAAAAAAWo/nWHwpJb76yQ/s400/lavaggiopiatti3.png" alt="" id="BLOGGER_PHOTO_ID_5515748594393832418" border="0" /&gt;&lt;/a&gt;C'è una bolla d'aria nello stato "pronto" perché nel periodo in cui ero impegnato altrove i piatti non venivano asciugati ed è abbastanza evidente che questo era un problema: il sistema non stava rilasciando nulla e dunque ogni attività che nel frattempo era stata fatta relativa alle fasi precedenti non aveva (ancora) prodotto alcun valore. Il wip limit naturale era lo spazio fisico occupato dalla pila di piatti da asciugare.&lt;br /&gt;Un mind set focalizzato sull'obiettivo di fare le cose per produrre un risultato, non importa come, avrebbe dovuto essere quello di vedere lo stato del sistema, e agire di conseguenza, anziché applicare una mentalità basata sulla semplice divisione dei compiti (io lavo tu asciughi). Da questo punto di vista per me la questione non è tanto se &lt;a href="http://www.gabrielelana.it/archives/174"&gt;kanban sia agile o meno&lt;/a&gt;, ma piuttosto che è utile perché sulla base delle disfunzioni che kanban mostra, si possono prendere dei provvedimenti, che però necessitano di per sé di un mind set collaborativo, comunicativo, ovvero agile.&lt;br /&gt;&lt;br /&gt;È altrettanto chiaro che ciò non cambia "direttamente" la natura delle operazioni specifiche, che sono ineludibili: non puoi fare a meno di quelle fasi, a meno di non cambiare completamente metodo - es. dotarsi di una lavastoviglie.&lt;br /&gt;&lt;br /&gt;Non si poteva fare molto diversamente per ottimizare perché le persone erano poche, e non era prevedibile quanti context switch ci sarebbero stati per me, o per chiunque altro, e dunque era necessario "vedere" le cose, ed ottenere e gestire il feedback che da questo stato giungeva, ed agire di conseguenza.&lt;br /&gt;&lt;br /&gt;Ovviamente nell'esempio in questione non sono necessari i cartellini dato che non c'è bisogno di una rappresentazione per comunicare quello che il sistema già comunica di per sé, ma supponiamo di avere altre realtà in cui il sistema non sia in grado di comunicarle lo stato direttamente, allora c'è bisogno di una rappresentazione simbolica di questo sistema, ed la Kanban board riesce a darla.&lt;br /&gt;Naturalmente non è che Kanban rappresenti un metodo di lavoro, ma piuttosto con Kanban (così come con Scrum) si ottengono probabilmente le informazioni necessarie a migliorare, e dunque anche a scegliere le pratiche e i metodi più adeguati.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-5544722113797141149?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/5544722113797141149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=5544722113797141149' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5544722113797141149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5544722113797141149'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/09/lavare-i-piatti-con-kanban.html' title='Lavare i piatti con Kanban'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_bUxSGU1m8WY/TIvd9nbSA4I/AAAAAAAAAWQ/jzPwb-YtcVE/s72-c/piattikanban1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-8967447345408245548</id><published>2010-08-08T19:26:00.009+02:00</published><updated>2010-08-13T19:20:54.126+02:00</updated><title type='text'>Scrum e XP dalle trincee</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_bUxSGU1m8WY/TF7o-6GhcbI/AAAAAAAAAVc/PvHVF1zRkFc/s1600/front+cover.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 212px; height: 320px;" src="http://1.bp.blogspot.com/_bUxSGU1m8WY/TF7o-6GhcbI/AAAAAAAAAVc/PvHVF1zRkFc/s320/front+cover.png" alt="" id="BLOGGER_PHOTO_ID_5503091962139472306" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Ho tradotto, con &lt;a href="http://blogs.ugidotnet.org/luka/Default.aspx"&gt;Luca Minudel&lt;/a&gt;, "Scrum and XP from the Trenches". Un racconto agile vissuto sul... fronte di guerra, per usare una fortunata metafora dell'autore Henrik Kniberg. È un testo che merita di essere riletto. Un messaggio molto chiaro di questo libro è che Scrum non è una ricetta e non è un insieme di 'best practices' da applicare come da manuale aspettandosi che poi tutto funzionerà come un orologio. Al contrario: è un insieme di strumenti che consentono di misurarsi e migliorarsi nell'ambito di un processo empirico. Sta a chi usa Scrum cercare di  capire come utilizzare i suoi semplici tools, come favorire i miglioramenti necessari nel particolare contesto in cui si trova. E il contesto è sempre unico, come ci ricorda Henrik quando sottolinea che "io stesso potrei applicarlo in un modo diverso se mi trovassi in un contesto diverso".&lt;br /&gt;Consiglio di leggerlo, o dirileggerlo.&lt;br /&gt;&lt;br /&gt;p.s. per commentare la traduzione, contattatemi pure, qui sul blog oppure ad uno dei miei indirizzi di email tonyx(at)yahoo(dot)com  e tonyx1(at)gmail(dot)com&lt;br /&gt;&lt;br /&gt;Il testo è disponibile su InfoQ: &lt;a href="http://www.infoq.com/minibooks/scrum-xp-from-the-trenches"&gt;http://www.infoq.com/minibooks/scrum-xp-from-the-trenches&lt;/a&gt;&lt;br /&gt;p.p.s. il "compagnio di pair" della traduzione, Luca, agilista di lunga data, è invece contattabile sul suo blog: &lt;a href="http://blogs.ugidotnet.org/luka/Default.aspx"&gt;http://blogs.ugidotnet.org/luka/Default.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-8967447345408245548?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/8967447345408245548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=8967447345408245548' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8967447345408245548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8967447345408245548'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/08/scrum-e-xp-dalle-trincee.html' title='Scrum e XP dalle trincee'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_bUxSGU1m8WY/TF7o-6GhcbI/AAAAAAAAAVc/PvHVF1zRkFc/s72-c/front+cover.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-8411248498687815014</id><published>2010-07-06T22:58:00.003+02:00</published><updated>2010-07-06T23:01:46.850+02:00</updated><title type='text'>My Codebreaker, marking guess on www.katacasts.com</title><content type='html'>&lt;object width="400" height="300"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=13072671&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1"&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=13072671&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;p&gt;&lt;a href="http://vimeo.com/13072671"&gt;CodeBreaker marking guess revised&lt;/a&gt; from &lt;a href="http://vimeo.com/user2906925"&gt;tonyx&lt;/a&gt; on &lt;a href="http://vimeo.com/"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;small&gt;By &lt;a href="http://katas.softwarecraftsmanship.org/?author=7" title="Posts by Corey Haines"&gt;Corey Haines&lt;/a&gt; in &lt;a href="http://katas.softwarecraftsmanship.org/?cat=4" title="View all  posts in Katas" rel="category"&gt;Katas&lt;/a&gt;,  &lt;a href="http://katas.softwarecraftsmanship.org/?cat=3" title="View all  posts in Software Craftsmanship" rel="category"&gt;Software Craftsmanship&lt;/a&gt;&lt;/small&gt;                      &lt;/p&gt;&lt;p&gt;"After a long break, we have a fantastic katacast to present to  you. Antonio Lucca contacted me with a new, C# version of the  codebreaker kata. I started watching it and was blown away. Is that C#?  In Vim? With autotest-like functionality? Super sweet! Without more  rambling from me"&lt;/p&gt;&lt;p&gt;&lt;a href="http://katas.softwarecraftsmanship.org/?p=168"&gt;link on www.katacasts.com&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-8411248498687815014?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/8411248498687815014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=8411248498687815014' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8411248498687815014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8411248498687815014'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/07/my-codebreaker-marking-guess-on.html' title='My Codebreaker, marking guess on www.katacasts.com'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-7077652602129428439</id><published>2010-04-30T16:39:00.010+02:00</published><updated>2010-09-15T00:55:57.396+02:00</updated><title type='text'>Quality of non declining velocity curve</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_bUxSGU1m8WY/S9rsDx6bntI/AAAAAAAAAUA/Z0PfQrRS6sA/s1600/Immagine1.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 693px; height: 516px;" src="http://3.bp.blogspot.com/_bUxSGU1m8WY/S9rsDx6bntI/AAAAAAAAAUA/Z0PfQrRS6sA/s320/Immagine1.png" alt="" id="BLOGGER_PHOTO_ID_5465940647449698002" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt; &lt;p style="margin-bottom: 0.5cm;" lang="en-US"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;" lang="en-US"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0cm;"&gt;&lt;span lang="en-US"&gt;This curve is a sort of model about how theoretically the practices are related to the quality, and how the quality is related to the velocity.&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-7077652602129428439?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/7077652602129428439/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=7077652602129428439' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/7077652602129428439'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/7077652602129428439'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/04/quality-of-non-declining-velocity-curve.html' title='Quality of non declining velocity curve'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_bUxSGU1m8WY/S9rsDx6bntI/AAAAAAAAAUA/Z0PfQrRS6sA/s72-c/Immagine1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-1894920028715726815</id><published>2010-04-29T14:05:00.005+02:00</published><updated>2010-04-29T23:45:59.871+02:00</updated><title type='text'>discussion about quality scope resources time variables</title><content type='html'>Discussion about the effect of quality on the process, for example defining the quality as the variable that affect the speed, and the independence, of implementing the next features. Inspired by the &lt;a href="http://www.jbrains.ca/permalink/218"&gt;speed quality barrier&lt;/a&gt; of &lt;a href="http://www.jbrains.ca/"&gt;J.B.&lt;/a&gt;  and &lt;a href="http://peripateticaxiom.blogspot.com/2009_05_31_archive.html"&gt;quality of non decreasing velocity&lt;/a&gt; (Qdv) of &lt;a href="http://twitter.com/keithb_b"&gt;@keith_b&lt;/a&gt; models. The claim is that there is sustainable development while being over the quality of non declining velocity level, and so there could be a discussion about the fact that some practices are economically justified if it can be proved that they make possible being over the Qdv.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="width: 425px;" id="__ss_3888519"&gt;&lt;strong style="display: block; margin: 12px 0pt 4px;"&gt;&lt;a href="http://www.slideshare.net/tonyx/4-variables-quality" title="4 variables + quality "&gt;four variables&lt;/a&gt;&lt;/strong&gt;&lt;object id="__sse3888519" height="355" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=presentazione3-100428171840-phpapp01&amp;amp;stripped_title=4-variables-quality"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;embed name="__sse3888519" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=presentazione3-100428171840-phpapp01&amp;amp;stripped_title=4-variables-quality" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="355" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="padding: 5px 0pt 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/tonyx"&gt;tonyx&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-1894920028715726815?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/1894920028715726815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=1894920028715726815' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/1894920028715726815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/1894920028715726815'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/04/discussion-about-quality-scope.html' title='discussion about quality scope resources time variables'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-4954180693554573900</id><published>2010-03-22T00:23:00.011+01:00</published><updated>2010-03-22T20:41:07.088+01:00</updated><title type='text'>bowling kata ocp way (extended comment)</title><content type='html'>Some more notes about my &lt;a href="http://github.com/tonyx/katabowling"&gt;"ocp bowling kata"&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;An execution of a generic bowling is a serie of frames, each composed of some rolls. &lt;br /&gt;&lt;br /&gt;Se sequence {5,5} is allowed in a single frame. The sequence {10,1} is not, because if the first roll in a frame is 10 then the frame is over.&lt;br /&gt;&lt;br /&gt;To model those validation is used the Delegates technique, introducing &lt;a href="http://github.com/tonyx/katabowling/blob/master/ocpBowling/ConstraintAndDescription.cs"&gt;constraints&lt;/a&gt; witch return true or false on a frame to check if the frame is valid according to some specific bowling instance.&lt;br /&gt;&lt;br /&gt;Here there are the constraints needed for the plain ordinary frames from index 0 to 9:&lt;br /&gt; &lt;div style="width:400px;height: 300px; overflow-x:  scroll; overflow-y:  scroll;border:1px solid black;"&gt;&lt;br /&gt;&lt;table cellpadding="4" cellspacing="1" width="120%" border=0&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Constraint sumOfAllRollMustbeLessThanTen = &lt;br /&gt;    (x =&gt; x.Rolls.Sum() &lt;= 10);&lt;br /&gt;Constraint ifFirstRollIsTenThanTheFrameIsOver = &lt;br /&gt;    (x =&gt; (!(x.Rolls[0] == 10) || x.Rolls.Count == 1));&lt;br /&gt;Constraint ifFirstRollIsLessThanTenThenThereIsAnotherRollInTheFrame = &lt;br /&gt;    (x =&gt; (!(x.Rolls[0] &lt; 10) || x.Rolls.Count == 2));&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Those constraints are composed (by &amp;&amp;) and injected using the call: SetConstraintForFrame().&lt;br /&gt;&lt;br /&gt;There is the possibility that a frame with different index has different constraints.&lt;br /&gt;The 10th frame in the terrestrial bowling in fact has different constraints:&lt;br /&gt;&lt;br /&gt; &lt;div style="width:400px;height: 300px; overflow-x:  scroll; overflow-y:  scroll;border:1px solid black;"&gt;&lt;br /&gt;&lt;table cellpadding="4" cellspacing="1" width="120%" border=0&gt;                  &lt;br /&gt;&lt;pre&gt;&lt;code&gt;        &lt;br /&gt;Constraint sumRollsNoHigherThanThirty = &lt;br /&gt;     x =&gt; x.Rolls.Sum() &lt;= 30;              &lt;br /&gt;Constraint ifFirstRollIsTenThanThereIsAtLeastAnotherRoll = x =&gt;        &lt;br /&gt;    !(x.Rolls[0]==10)||x.Rolls.Count &gt; 1;&lt;br /&gt;&lt;br /&gt;Constraint ifSecondRollIsTenThenThereIsAnotherRoll =&lt;br /&gt;    x =&gt; (!(x.Rolls.Count &gt; 1 &amp;amp;&amp;amp; x.Rolls[1] == 10) || x.Rolls.Count == 3);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;(see the &lt;a href="http://github.com/tonyx/katabowling/blob/master/ocpBowling/BowlingFactory.cs"&gt;factory&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Note that the following logical rule has been used:&lt;br /&gt;if A then B is the same as !A || B&lt;br /&gt;&lt;br /&gt;There are also rules to calculate the &lt;a href="http://github.com/tonyx/katabowling/blob/master/ocpBowling/IBonusRuleForFrame.cs"&gt;score and the bonus&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://github.com/tonyx/katabowling/blob/master/ocpBowling/TerrestrianSpareBonusRule.cs"&gt;Spare &lt;/a&gt; rule says that there is a bonus given by the next roll, and the &lt;a href="http://github.com/tonyx/katabowling/blob/master/ocpBowling/TerrestrianFirstEightFramesStrikeBonusRule.cs"&gt;Strike &lt;/a&gt; rule returns as a bonus the next two rolls.&lt;br /&gt;&lt;br /&gt;Score is divided by the &lt;a href="http://github.com/tonyx/katabowling/blob/master/ocpBowling/IScoreRuleForFrame.cs"&gt;plain score&lt;/a&gt; and the bonus, so also the plain score rule (generally given by the rolls) can be injected.&lt;br /&gt;&lt;br /&gt;I still don't know if unit test should allocate frames or single rolls.&lt;br /&gt;&lt;br /&gt;At the moment there are both in the &lt;a href="http://github.com/tonyx/katabowling/blob/master/ocpBowling/TerrestrialBowlingTest.cs"&gt;tests &lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For instance to compute zero score using frame is as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;        [Test]&lt;br /&gt;        public void TestAllZeroes()&lt;br /&gt;        {&lt;br /&gt;            Frame frame = new Frame(0,0);&lt;br /&gt;            for (int i = 0; i &lt; 10; i++)&lt;br /&gt;            {&lt;br /&gt;                terrestrialGame.AddFrame(frame);&lt;br /&gt;            }&lt;br /&gt;            Assert.AreEqual(0, terrestrialGame.Score());&lt;br /&gt;        }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and the following is the equivalent that uses rolls:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;        [Test]&lt;br /&gt;        public void TestAllZeroesByRolling()&lt;br /&gt;        {&lt;br /&gt;            for (int i=0;i&lt;20;i++)&lt;br /&gt;            {&lt;br /&gt;                terrestrialGame.Roll(0);                &lt;br /&gt;            }&lt;br /&gt;            Assert.AreEqual(0,terrestrialGame.Score());&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To test the constraints I need ti add frames in the test, but i can also say that the user should be exposed just the Roll method, so the method that get frames could become private. &lt;br /&gt;&lt;br /&gt;That means eliminate the tests based on frames (if we don't want to test private methods).&lt;br /&gt;&lt;br /&gt;The "bowling marziano" is based on just three frames of no more than tre rolls, and for any strike the bonus is the result of the last frame.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-4954180693554573900?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/4954180693554573900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=4954180693554573900' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/4954180693554573900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/4954180693554573900'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/03/bowling-kata-ocp-way-extended-comment.html' title='bowling kata ocp way (extended comment)'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-2985099520995602600</id><published>2010-03-16T23:34:00.006+01:00</published><updated>2010-03-17T00:33:15.694+01:00</updated><title type='text'>quick c# localization by java properties files and reflection</title><content type='html'>A quick way to localize C# application is given by &lt;a href="http://github.com/tonyx/LabelsLocalization"&gt;this example&lt;/a&gt;.&lt;br /&gt;There is a trivial windows form application and a LabelManager project.&lt;br /&gt;&lt;br /&gt;This is a sketch of how it works.&lt;br /&gt;Visual Studio generates, for any form, two files. The second one is automatically filled with name ending by .designer.cs, that should not be edited, and that contains a InitializeComponent() function that assign values to widget according to visual development.&lt;br /&gt;&lt;br /&gt;Assignment to Text element are in the form:&lt;br /&gt;&lt;br /&gt;this.label1.Text = "This label is in english";&lt;br /&gt;&lt;br /&gt;You know that the full path of the label1 element (by namespace.classname) is:&lt;br /&gt;&lt;br /&gt;WindowsformsApplication1.SampleForm.label1.Text&lt;br /&gt;&lt;br /&gt;So to localize this label in any language an international.properties file can contain the localized values espressing the fully qualified element property, preceded by a locale string, and followed by the desired assignment, as follows:&lt;br /&gt;&lt;br /&gt;it.WindowsFormsApplication1.SampleForm.label1.Text=questo testo è in italiano&lt;br /&gt;ru.WindowsFormsApplication1.SampleForm.label1.Text=&lt;span id="result_box" class="short_text"&gt;&lt;span style="background-color: rgb(255, 255, 255);" title="this text is in english"&gt;Этот текст на &lt;/span&gt;&lt;/span&gt;&lt;span id="result_box" class="short_text"&gt;&lt;span style="background-color: rgb(235, 239, 249);" title="this text is in russian"&gt;русском языке&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://github.com/tonyx/LabelsLocalization/blob/master/WindowsFormsApplication1/App.config"&gt;App.config&lt;/a&gt; shoould contains the value (ru or it) for the current localization, in order to choose the version (italian or russian, in this case).&lt;br /&gt;Note: the international.properties is encoded in utf-8 to manage special chars.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://github.com/tonyx/LabelsLocalization/blob/master/WindowsFormsApplication1/SampleForm.cs"&gt;call &lt;/a&gt;(not the definition) to InitializeComponent() must be followed by an UpdateUi(this) call that will change those properties according to locale and to the international.properties file, using a LabelUtils package.&lt;br /&gt;&lt;br /&gt;Some script file can be useful to generate easily structure of the international.properties.&lt;br /&gt;Until now I just used stuffs like this bash command:&lt;br /&gt;for i in `find . | grep ".cs$"`; do echo $i; cat $i | egrep "Text ="; done;&lt;br /&gt;&lt;br /&gt;(you need a bash shell interpreter)&lt;br /&gt;&lt;br /&gt;This approach is original, and may require much more tests, and efficiency improvement, particularly about exceptions handling.&lt;br /&gt;&lt;br /&gt;In few steps to use this approach :&lt;br /&gt;create your forms and assign text values as usual by Visual Studio.&lt;br /&gt;At any time (also when your application is completely done), detect all the properties assignable by strings, for example using some bashing.&lt;br /&gt;Create an international.properties files assigning values to any properties by locale.&lt;br /&gt;Assign locale in the App.config&lt;br /&gt;Be sure that international.properties will be contained in the build directory, for example adding some copy directive in the  AfterBuild target section of the  &lt;a href="http://github.com/tonyx/LabelsLocalization/blob/master/WindowsFormsApplication1/WindowsFormsApplication1.csproj"&gt;vs build file&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Suggestions and contributions are welcome.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;p.s. I mentioned about bash and the sample command:&lt;br /&gt;for i in `find . | grep ".cs$"`; do echo $i; cat $i | egrep "Text ="; done;&lt;br /&gt;&lt;br /&gt;the '`' may not be available in all the keyboards layout.&lt;br /&gt;Change keyboard layout, or use the following command instead:&lt;br /&gt;for i in $(find . | grep ".cs$"); do echo $i; cat $i | egrep "Text ="; done;&lt;br /&gt;&lt;br /&gt;Ciao.&lt;br /&gt;Tony&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-2985099520995602600?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/2985099520995602600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=2985099520995602600' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/2985099520995602600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/2985099520995602600'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/03/quick-c-localization-by-java-properties.html' title='quick c# localization by java properties files and reflection'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-4095207144609949016</id><published>2010-02-28T14:45:00.006+01:00</published><updated>2010-03-04T01:02:20.866+01:00</updated><title type='text'>ocp bowling kata</title><content type='html'>Started implementing in c# the &lt;a href="http://github.com/tonyx/katabowling"&gt;bowling kata in the ocp way&lt;/a&gt;.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &lt;a href="http://matteo.vaccari.name/blog/archives/293"&gt;ocp kata&lt;/a&gt; rule does not allow you to implement any new feature without having a base code respecting the &lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle"&gt;open closed principle&lt;/a&gt;.&lt;div&gt;If it is not possibile, you have to refactor the base code at it.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In this way you are forced to improve the object oriented design.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Not so easy, and I think that this kata requires much more time than two or three &lt;a href="http://www.pomodorotechnique.com/"&gt;pomodoros&lt;/a&gt; imo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ciao.&lt;/div&gt;&lt;div&gt;T.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-4095207144609949016?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/4095207144609949016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=4095207144609949016' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/4095207144609949016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/4095207144609949016'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/02/ocp-bowling-kata.html' title='ocp bowling kata'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-3032684961939691675</id><published>2010-02-14T15:37:00.003+01:00</published><updated>2010-05-14T03:07:52.123+02:00</updated><title type='text'>J. B. Rainsberger and Corey Haines discuss software business and development issues</title><content type='html'>It was fun for me partecipating by chat to this discussion, making few questions:&lt;br /&gt;&lt;a href="http://www.ustream.tv/flash/video/4722190"&gt;http://www.ustream.tv/flash/video/4722190&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-3032684961939691675?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/3032684961939691675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=3032684961939691675' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3032684961939691675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3032684961939691675'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/02/j-b-rainsberger-and-corey-haines.html' title='J. B. Rainsberger and Corey Haines discuss software business and development issues'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-1867542879175968746</id><published>2010-01-04T19:33:00.004+01:00</published><updated>2010-02-07T14:00:23.793+01:00</updated><title type='text'>string calculator kata</title><content type='html'>I uploaded a new video about the stringCalculator kata:&lt;br /&gt;&lt;br /&gt;&lt;object width="400" height="300"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=8758532&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=8758532&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;p&gt;&lt;a href="http://vimeo.com/8758532"&gt;stringcalculator kata&lt;/a&gt; from &lt;a href="http://vimeo.com/user2906925"&gt;tonyx&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Other videos availables from other friends are:&lt;br /&gt;&lt;a href="http://vimeo.com/8206748" target="_blank"&gt;http://www.vimeo.com/8206748&lt;/a&gt;&lt;br /&gt;&lt;a href="http://vimeo.com/8326880" target="_blank"&gt;http://www.vimeo.com/8326880&lt;/a&gt;&lt;br /&gt;&lt;a href="http://vimeo.com/8506325" target="_blank"&gt;http://www.vimeo.com/8506325&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.vimeo.com/8087998" target="_blank"&gt;http://www.vimeo.com/8087998&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-1867542879175968746?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/1867542879175968746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=1867542879175968746' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/1867542879175968746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/1867542879175968746'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/01/string-calculator-kata.html' title='string calculator kata'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-223736016015527866</id><published>2010-01-01T23:02:00.016+01:00</published><updated>2010-01-03T11:43:19.301+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tdd testing'/><title type='text'>Tests can show presence of bugs, and not their absence?</title><content type='html'>Some interesting discussions are related to the famous statement:&lt;br /&gt;"&lt;i&gt;program testing can be used to show the presence of bugs, but never to show their absence!&lt;/i&gt;"&lt;br /&gt;which is a variant of the fact that "absence of evidence &lt;i&gt;is not&lt;/i&gt; evidence of the absence".&lt;br /&gt;&lt;br /&gt;The discussions takes a simple &lt;a href="http://peripateticaxiom.blogspot.com/2009/12/bayesian-testing.html"&gt;example&lt;/a&gt;:&lt;br /&gt;"the fact that there is no evidence that there is an elephant here in the room, &lt;i&gt;is&lt;/i&gt; &lt;i&gt;not&lt;/i&gt; an evidence that there is no elephant in the room".&lt;br /&gt;We can drop the "not" because it is very unlikely that an elephant is here without being any evidence so:&lt;br /&gt;"the fact that there is no evidence that there is an elephant here in the room, &lt;i&gt;acually&lt;/i&gt; &lt;i&gt;is&lt;/i&gt; an evidence that there is no elephant in the room!".&lt;br /&gt;&lt;br /&gt;Seems reasonable, about being elephant in this room or not that "absence of evidence &lt;i&gt;is&lt;/i&gt; &lt;i&gt;also&lt;/i&gt; evidence of absence", but what if we talk about a fly:&lt;br /&gt;"the fact that there is no evidence that there is a fly in this room is &lt;i&gt;not&lt;/i&gt; an evidence that there is not a fly in this room".&lt;br /&gt;&lt;br /&gt;The question is about "how much is close to zero the probability that I'm doing a mistake using the rule "absence of evidence implies evidence of absence"?&lt;br /&gt;It's about the probability that using an &lt;a title="abductive" href="http://en.wikipedia.org/wiki/Abductive_reasoning" id="ojka"&gt;abductive&lt;/a&gt; inference logical rule we get the wrong conclusion.&lt;br /&gt;&lt;br /&gt;Probability of being in mistakes in terms of conditional probability:&lt;br /&gt;p(there is an elephant|no evidence of elephant) is low (probability that there is an elephant in this room given that there is no evidence that an elephant is in this room)&lt;br /&gt;p(there is a fly| no evidence of fly) is higher (probability that there is a fly in this room given that there is no evidence that a fly is here in this room)&lt;br /&gt;&lt;br /&gt;If there are no evidence of being a fly here does not mean that we could really conclude reasonably that there is not a fly here.&lt;br /&gt;&lt;br /&gt;Let's go back to the software testing question. The software testing analogy, is closer to the elephant or the fly example?&lt;br /&gt;How much confident we are that "no evidence of bugs (i.e. tests passes) &lt;i&gt;is&lt;/i&gt; evidence of no bugs"?&lt;br /&gt;&lt;br /&gt;if p(bug | test passes) = 0 then "no evidence =&gt; evidence of not" would be a valid logical role.&lt;br /&gt;&lt;br /&gt;But can be p(bug | test passes) =0?&lt;br /&gt;&lt;br /&gt;That would mean: we are sure that we are not wrong when we interpret "all test passes" as "there is no bug".&lt;br /&gt;&lt;br /&gt;From theoretical computer science the answer is that we could never be sure of it, i.e. the previous statement is theoretically wrong.&lt;br /&gt;The "&lt;a href="http://en.wikipedia.org/wiki/Rice_theorem"&gt;Rice theorem&lt;/a&gt;" states that cannot exist any automated procedure (testing program) that can recognize if another program (tested program) has some particular property (being bug free).&lt;br /&gt;&lt;br /&gt;However it does mean not so much practically speaking, I mean, for example because of the following reasons:&lt;br /&gt;- what do we mean by bug? From some point of view there does not exist a program bug free.&lt;br /&gt;- we need p(bug | test passes) close to zero, not zero.&lt;br /&gt;- Rice theorem talks about the impossibility that there exist a program that take in input any other program, like using it as a black box. Here is different: in tdd the program under test is not a black box. It's something that &lt;span style="font-style: italic;"&gt;I&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt; know because it's what I'm writing&lt;span style="font-style: italic;"&gt; &lt;/span&gt;in order to solve a problem that I &lt;span style="font-style: italic;"&gt;&lt;/span&gt;know. Program grows without breaking existing tests, and that's a way to lower the probability of introducing bug by program changing.&lt;br /&gt;- tests are a way to rewrite specifications in a language suitable for the coder and for the code under test. Test cannot be perfect as the specifications can't.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-223736016015527866?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/223736016015527866/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=223736016015527866' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/223736016015527866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/223736016015527866'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2010/01/tests-can-show-presence-of-bugs-not.html' title='Tests can show presence of bugs, and not their absence?'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-3969587058564825791</id><published>2009-12-26T19:11:00.001+01:00</published><updated>2009-12-26T19:11:31.792+01:00</updated><title type='text'>quality of non decreasing velocity</title><content type='html'>About the "quality of non decreasing velocity" (Q_cv) concept. (&lt;a title="http://peripateticaxiom.blogspot.com/2009_05_31_archive.html" href="http://peripateticaxiom.blogspot.com/2009_05_31_archive.htmlhttp://peripateticaxiom.blogspot.com/2009_05_31_archive.html" id="vn46"&gt;http://peripateticaxiom.blogspot.com/2009_05_31_archive.html&lt;/a&gt;)&lt;br&gt;&lt;br&gt;That model states that in any project the velocity can increase or decrease depending on the quality. Q_cv is a threshold such that, if your base code quality is higher, then your velocity will be increasing, and if lower, it will be decreasing.&lt;br&gt;&lt;br&gt;You can figure out easily some empirical evidence of about being under the Q_cv: do start doing "quick and dirty" bad code, and because of the bad quality, in the long run, maintenance will be very difficult, slower and eventually much more dirty.&lt;br&gt;&lt;br&gt;Mathematically: dV/dt ~ Q -Q_cv&lt;br&gt;This is a nice mathematical way to say that sacrifice the quality means being slower in the long run (perhaps being quicker in the short term).&lt;br&gt;&lt;br&gt;I would say that fitting over the Q_cv threeshold means being in the area of sustainable quality.&lt;br&gt;&lt;br&gt;Objections?&lt;br&gt;Pick up one of them, or add yours :)&lt;br&gt;&lt;br&gt;&lt;br&gt;1) "the models works (if it works) only in the long run, and it doesn't say what is, and how you can measure, the Q_cv, so how can you know if it worth the effort?"&lt;br&gt;2) "suppose I know Q_c, I also know I'm not able to fit in the over Q_cv/sustainable quality level [area], [thus I know it does not worth the effort].&lt;br&gt;3) "quality is perceived as aesthetic, and not pragmatic."&lt;br&gt;4) "in the short term, quality means being slower, particularly if you are not used to. Refactoring, unit test and mocking needs time and skills"&lt;br&gt;5) may be you can have empirical evidence that being the wort is the quality, the higher is the negative impact to the velocity, but it does not prove that there really exist this Q_cv threeshold, i.e. an area of sustainable quality.&lt;br&gt;&lt;br&gt;Commenti.&lt;br&gt;Andrea (cui ora ho dato diritti di scruttura sul documento):&lt;br&gt;&lt;i&gt;&lt;font face="Verdana"&gt;Io ho dei dubbi sul fatto che aumentare la qualità rallenti nel breve periodo.&lt;/font&gt;&lt;br&gt;&lt;/i&gt;&lt;div&gt;&lt;i&gt;&lt;font face="Verdana"&gt;Quello che costa è l'apprendimento di una&lt;br /&gt;tecnologia o di una metodologia. Una volta appreso non costa più.&lt;br /&gt;Quindi non è che ad esempio il TDD ti rallenta. Ti rallenta solo finché&lt;br /&gt;non l'hai appreso.&lt;/font&gt;&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;Luca: &lt;br&gt;1 comment about the "in long run". if today the team do a quick and dirty fix on one code area and tomorrow the team have to add a feature in the same code area, that it will be in the short run. so when you measure the velocity of the team working on a specific code area, than the velocity decrease immediately. Users are interested in a steady flow of features so quality do matters. here is an interesting post on the topic &lt;a title="To Fix Or Not To Fix?: Another Good Question" href="http://www.threeriversinstitute.org/blog/?p=321" id="h8-5"&gt;To Fix Or Not To Fix?: Another Good Question&lt;/a&gt;&lt;br&gt;1 more comment about " how can you know if it worth the effort?": should measure the number of new bugs, the velocity of the team and compare the velocity of another team implementing a similar feature (i.e. adding a new payment methods to the web apps).&lt;br&gt;&lt;br&gt;About Andrea comment I do agree, the bottleneck when striving for quality is skills and talent, not time: hire the right person, create a team where skilled/experienced dev are the majority and so can quickly teach to newcomers. One post in topic: &lt;a title="Turning Skills into Money" href="http://www.threeriversinstitute.org/blog/?p=385" id="am.5"&gt;Turning Skills into Money&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-3969587058564825791?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/3969587058564825791/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=3969587058564825791' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3969587058564825791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3969587058564825791'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2009/12/quality-of-non-decreasing-velocity.html' title='quality of non decreasing velocity'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-6254531101148590908</id><published>2009-12-08T17:50:00.006+01:00</published><updated>2009-12-08T20:27:17.464+01:00</updated><title type='text'>A modular adapter</title><content type='html'>This post is related to some code I wrote about creating a way to map different but similar objects, and is related to the adapter pattern.&lt;br /&gt;&lt;br /&gt;This is not a "standard" way to use the adapter pattern, so if you are looking for the official adapter pattern, this post is not for you.&lt;br /&gt;&lt;br /&gt;Suppose that two classes A and B do similar stuffs, in different way, and we are not able to decide which one we are going to use.&lt;br /&gt;We want to find how they are similar, and how can we deal about deciding witch one we are going to really use at run time, in terms of how initialize them (in the A way or in the B way), and witch one will be the actual class used (real A o real B, provided that they will be viewed as a common interface).&lt;br /&gt;&lt;br /&gt;We want to manage wrappers that maps one to another and create an abstraction layer that hides the real class, and manage in run time the concrete implementation.&lt;br /&gt;&lt;br /&gt;Here is an example:&lt;br /&gt;StringString manages and print strings, and is created passing the plain String objects:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class StringString {&lt;br /&gt;   private String string;&lt;br /&gt;  &lt;br /&gt;   public StringaString(String string) {&lt;br /&gt;      this.string = string;&lt;br /&gt;   }&lt;br /&gt;   public void print() {&lt;br /&gt;      System.out.println(string);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The char version is called StringChar:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;public class StringChar implements StringaGetter {&lt;br /&gt;   private char[] chars;&lt;br /&gt;   public StringaChar(char[] chars) {&lt;br /&gt;      this.chars = chars;&lt;br /&gt;   }&lt;br /&gt;   public void print() {&lt;br /&gt;      System.out.println(chars);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;They do really the same thing, but they are not created in the same way.&lt;br /&gt;&lt;br /&gt;The wrapping code that allows to create the StringChar from String object is the conversion from String to char array string.toCharArra() and the wrapping code to initialize the StringChar having the charArray is new String(aCharArray).&lt;br /&gt;&lt;br /&gt;What about creating of an abstraction layer between the how to create, and what it will be? &lt;br /&gt;We will need to manage the wrappers between them, in order to be able, at run time to decide witch contract we are going to obey for the object creation/method,  and what the concrete implementation will be.&lt;br /&gt;&lt;br /&gt;We could choose any combination.&lt;br /&gt;&lt;br /&gt;We are also going to change both the objects in order to implement a common interface so we will inspect them in a unique way established by an implemented interface, whatever is their actual class.&lt;br /&gt;&lt;br /&gt;Here are our steps:&lt;br /&gt;&lt;br /&gt;1) the common interface that both should implement is StringGetter:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public interface StringaGetter {&lt;br /&gt;    public String getString();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;2) both classes are slightly modified to to implement that interface from now:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;public class StringaString implements StringGetter {&lt;br /&gt;    private String string;&lt;br /&gt;    &lt;br /&gt;    // wee will see this later&lt;br /&gt;    @convertible(contractClass = StringGetter.class)&lt;br /&gt;    public StringaString(String string) {&lt;br /&gt;      this.string = string;&lt;br /&gt;    }&lt;br /&gt;    public void print() {&lt;br /&gt;      System.out.println(string);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public String getString() {&lt;br /&gt;      return string;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class StringaChar implements StringGetter {&lt;br /&gt;    private char[] chars;&lt;br /&gt;&lt;br /&gt;    @convertible(contractClass = StringGetter.class)&lt;br /&gt;    public StringaChar(char[] chars) {&lt;br /&gt;         this.chars = chars;&lt;br /&gt;    }&lt;br /&gt;    public void print() {&lt;br /&gt;       System.out.println(chars);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public String getString() {&lt;br /&gt;        return new String(chars);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Both the classes are different in the way they are created and have some new behavior that obey to the contract defined by the StringGetter interface.&lt;br /&gt;Moreover, we added a @convertible(contractClass = StringGetter.class) tag to the constructor.&lt;br /&gt;Any other class that implements StringGetter interface and that add the same annotation to the constructor could be used for the same purposes.&lt;br /&gt;&lt;br /&gt;The next step is to create an abstraction layer that will let us select any creational contracts, and any concrete implementation that means, the "apparent" implementation and the "actual" implementation.&lt;br /&gt;&lt;br /&gt;This abstraction layer manages a map of wrappers.&lt;br /&gt;A wrapper is an implementation of the following interface:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public interface Wrapper {&lt;br /&gt;    Object[] wrap(Object[] object);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For example the StringToChar wrapper is the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class StringToChar implements Wrapper{&lt;br /&gt;    public Object[] wrap(Object[] object) {&lt;br /&gt;        return new Object[]{((String)object[0]).toCharArray()};&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;which converts a 1 size Object[] array containing a String to a one size Object[] array containing the corresponding charArray().&lt;br /&gt;&lt;br /&gt;The opposite is the CharToString wrapper:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class CharToString implements Wrapper {&lt;br /&gt;    public Object[] wrap(Object[] object) {&lt;br /&gt;        return new Object[]{new String((char[])object[0])};&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We need to inform our abstraction layer about using the two wrappers:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ConversionMap.getInstance().setMapper(&lt;br /&gt;   StringString.class.getConstructor(new Class[]{String.class}),&lt;br /&gt;   StringChar.class.getConstructor(new Class[]{char[].class}),&lt;br /&gt;   StringGetter.class,&lt;br /&gt;   new StringToChar());&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The conversion from the parameters suitable for the former constructor to the latter that will be used in order to manage objects that implements the StringGetter.class interface is a StringToChar.&lt;br /&gt;&lt;br /&gt;This is about the reverse direction:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ConversionMap.getInstance().setMapper(&lt;br /&gt;   StringChar.class.getConstructor( new Class[]{char[].class}),&lt;br /&gt;   StringString.class.getConstructor(new Class[]{String.class}),&lt;br /&gt;   StringGetter.class,&lt;br /&gt;   new CharToString());&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;At the end: we are going to put the "wrappable" constructors in a map, managed by the "modular factory", and giving them a name:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  MapOfConverterModularFactory mapConv = new MapOfConverterModularFactory(StringaGetter.class);&lt;br /&gt;  mapConv.putImplementation("charString",&lt;br /&gt;    StringaChar.class.getConstructor(new Class[]{char[].class}));&lt;br /&gt;  mapConv.putImplementation(&lt;br /&gt;    "StrinString",StringaString.class.getConstructor(new Class[]{String.class}));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And now we can choose to select witch implementation to use for the creational purposes and witch one the real implementation:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  mapConv.setCurrentImplementation("charString");&lt;br /&gt;  mapConv.setRereferenceImplementation("StrinString");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Current is the "actual", and reference is the "apparent".&lt;br /&gt;&lt;br /&gt;We were used to call StringString myString = new StringString("hello");&lt;br /&gt;and now we will instead call:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;StringGetter ob = (StringGetter)mapConv.getObject(&lt;br /&gt;   new Object[]{"hello"})&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And ob is built according to the StringString style, and of course, his current concrete class is StringChar:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;assertEquals(ob.getClass(),StringaChar.class);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is the opposite situation:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  mapConv.setReferenceImplementation("charString");&lt;br /&gt;  mapConv.setCurrentImplementation("StrinString");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We were used to call StringString myString = new StringString("hello");&lt;br /&gt;and now we will instead call:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;StringGetter ob = (StringGetter)mapConv.getObject(&lt;br /&gt;  new Object[]{new char[]{'h','e','l','l','o'}));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And ob is built according to the StringString style, and of course, his current concrete class is StringString:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;assertEquals(ob.getClass(),StringString.class);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;All the code will be on line asap.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Tony (8/12/2009)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-6254531101148590908?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/6254531101148590908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=6254531101148590908' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/6254531101148590908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/6254531101148590908'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2009/12/this-post-is-related-to-some-code-i.html' title='A modular adapter'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-3967128991174332424</id><published>2009-11-29T21:05:00.018+01:00</published><updated>2009-12-10T00:53:36.737+01:00</updated><title type='text'>agile and team dynamics learning values</title><content type='html'>One of the first agile principle I learned is that we should introduce learning culture and remove blaming culture.&lt;br /&gt;Blaming culture comes up easily. It is proved being &lt;a href="http://www.sciencedaily.com/releases/2009/11/091119194124.htm"&gt;viral &lt;/a&gt;and, in the long run, dangerous for the organization.&lt;br /&gt;&lt;br /&gt;So no wonder that, particularly in critical and expensive fields such as  the I.T., you can easily see the blaming game.&lt;br /&gt;&lt;br /&gt;We need to introduce values that can step by step remove such unsustainable attitudes, and replace them with something better, technical ans social as well.&lt;br /&gt;&lt;br /&gt;The chances to have success depends on knowing the following factors:&lt;br /&gt;what is going on in terms of the "&lt;a href="http://www.google.it/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=1&amp;amp;ved=0CAwQFjAA&amp;amp;url=http%3A%2F%2Fbooks.mcgraw-hill.com%2Ftraining%2Fdownload%2F0071408827%2F37.doc&amp;amp;rct=j&amp;amp;q=iceberg+model+of+human+behaviour&amp;amp;ei=etsSS_GAPIeQsAaq6pGQAw&amp;amp;usg=AFQjCNHx8-2O-8907FAE0wNd0NRIavEe4A"&gt;iceberg model of human behaviour&lt;/a&gt;",&lt;br /&gt;what kind of mindset have the players: &lt;a href="http://en.wikipedia.org/wiki/Kohlberg%27s_stages_of_moral_development"&gt;pre-conventional, conventional, or post-conventional&lt;/a&gt;,&lt;br /&gt;do you have enough &lt;a href="http://en.wikipedia.org/wiki/Power_%28philosophy%29#Five_bases_of_power"&gt;referent power&lt;/a&gt;?&lt;br /&gt;&lt;br /&gt;The better you know that, and the better you can understand how much work is still needed to move to a learning/comunicative/healthy environment.&lt;br /&gt;&lt;br /&gt;If you can exercise this "referent power", the simpler thing that you could suggest is:  simple tools, simple communications, simple solutions, simple descriptions, simple documentation; a sprint backlog and a product backlog, or kanban, a daily stand up meeting, a shared wiki, discourage the use of emails for task related communications.&lt;br /&gt;&lt;br /&gt;Is that all?&lt;br /&gt;Not.&lt;br /&gt;If you consider it enough, then it will probably will turn out in something like the "&lt;a href="http://martinfowler.com/bliki/FlaccidScrum.html"&gt;flaccid scrum&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;I think that scrum tools are only the starting points. We have been able to write a backlog, and that means that  we know that the P.O. knows what she wants, and, at least once, we probably know also how much can we do in a sprint, and we had the opportunity to discuss that between"pigs" and no "chikens".&lt;br /&gt;&lt;br /&gt;This should be a good way to start a process that should allow us to learn by our feebacks.&lt;br /&gt;&lt;br /&gt;The feedback could hopefully be, during a daily Scrum, something like the following: "I worked on this backlog item, I tested it (manually?), &lt;span style="font-style: italic;"&gt;but&lt;/span&gt; I found that the code was not so &lt;span style="font-style: italic;"&gt;clean &lt;/span&gt;so it toke much more time than we estimated, and probably I need more time working on it, and moreover I'm not sure if there is something else broken somewhere, so I need to work on it a little bit more on tests, and so on..."&lt;br /&gt;&lt;br /&gt;So, we will realize this: the estimation have &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; be fulfilled because we have not been able to describe a clear &lt;span style="font-weight: bold;"&gt;definition of&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;done&lt;/span&gt;, and we underestimated the side effect of implementing new features, because of preexisting unclean code without automated tests.&lt;br /&gt;Those things are "wrong", but this kind of feedback is &lt;span style="font-weight: bold;"&gt;very good&lt;/span&gt;, as long as we can use this knowledge as an answer to learn, and consider that the questions contains what we need.&lt;br /&gt;&lt;br /&gt;There is the possibility that such statement will not considered the key to find more answers, but just to play again the blaming game.&lt;br /&gt;Consider for example this answer to the report of the developer: "yes but that means that &lt;span style="font-weight: bold;"&gt;you&lt;/span&gt; guys didn't do unit test, and &lt;span style="font-weight: bold;"&gt;you&lt;/span&gt; guys didn't write clean code..."&lt;br /&gt;respect of the following: "yes &lt;span style="font-weight: bold;"&gt;and&lt;/span&gt; that means that the next time we should have much more consideration about internal quality as a unnegotiable part of the scope for any task, so unit testing and refactoring will be simply included in our activities."&lt;br /&gt;&lt;br /&gt;Then there comes again the role of the coach (or scrum master) that is the one that makes the system move in the "learning way", instead of the chaotic way.&lt;br /&gt;&lt;br /&gt;How? Difficult to answer, but one thing to know is that during difficult un-comfort situation, the learning can be much more powerful. Ben Fuchs:&lt;br /&gt;&lt;br /&gt;"When we are exiting the comfort zone, it will be the time we least want to examine ourselves - and the seduction of self-righteous certainty of our positions will resist any questioning. But this is exactly the time to notice our reflex reactions, slow down and practice all the coaching and communications skills we have learned in seminars. If you can catch the process in the moment when it flares up, then the learning is much more powerful than after its over." (&lt;a href="http://tech.groups.yahoo.com/group/deepdynamics/message/70"&gt;link&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;29/11/2009&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-3967128991174332424?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/3967128991174332424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=3967128991174332424' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3967128991174332424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3967128991174332424'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2009/11/agile-and-team-dinamics-learning-values.html' title='agile and team dynamics learning values'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-5448326853201437397</id><published>2009-04-19T13:46:00.008+02:00</published><updated>2009-04-19T18:16:36.561+02:00</updated><title type='text'>toward an open closed equals and subclassing strategy</title><content type='html'>I have to say that this is a very buzz title.&lt;br /&gt;&lt;br /&gt;I'm going to write about equals, subclassing, interchangeability between concrete representations... stuffs like that.&lt;br /&gt;&lt;br /&gt;Object identity is difficult to define for me.&lt;br /&gt;&lt;br /&gt;In some languages like java the .equals() as defined in the Object class indicates that the other object is the same object. It is stored the same memory location.&lt;br /&gt;That implementation is the same as the '==' operator.&lt;br /&gt;&lt;br /&gt;The equals is supposed to be overriden for any not mutable object so the meaning will be: object with the same state.&lt;br /&gt;The java Set apis don't store duplicate objects, where an object is a duplicate of another if the former and the latter are equals (respect of the equals method implementation).&lt;br /&gt;&lt;br /&gt;Some other examples can be less obvius:&lt;br /&gt;think about classes that manages some rational numbers api we are wording on.&lt;br /&gt;&lt;br /&gt;Will 1/2 equals to 2/4 for some rational numbers apis we are implementing?&lt;br /&gt;&lt;br /&gt;And what if we talk about "fractions".&lt;br /&gt;Some math guys (domain experts) would tell us that the two fracitions "1/2" and "2/4" are technically not equals, but the two "rational numbers" 1/2 and 2/4 are the same.&lt;br /&gt;&lt;br /&gt;New Rational(1,2).equals(new Rational(2,4)) will be true, and new Fraction(1,2).equals(2,4) will be false.&lt;br /&gt;&lt;br /&gt;So our choose depends of the name.&lt;br /&gt;&lt;br /&gt;Does it make sense? mmm... yes, as long as we agree that we act under the umbrella of algebraic principles like"rational numbers are actually the equivalence classes of fractions, where the equivalence is defined as the fraction n/d is equivalent to n2/d2 if .....  [any definition that you like. One is: (n/d) * (d2/n2) = a/b where a and be are two equals relative number]"&lt;br /&gt;&lt;br /&gt;Too heavy!&lt;br /&gt;&lt;br /&gt;Yeah... right, but this is the art of computer programming: how much I'll go deep to the domain, to be consistent with some common sense future expectation, apply some design principles and so on...&lt;br /&gt;&lt;br /&gt;Or we can avoid that: for example we are not going to write a unit test like&lt;br /&gt;assertEquals(new Rational(1,2), new Rational(2,4));&lt;br /&gt;&lt;br /&gt;Any time we display to the user a fraction, then we do GCD calculation and reduce the fraction, so the system will work perfectly as a black box.&lt;br /&gt;&lt;br /&gt;Some other guy can get my code and say: for the I think that we deserve that kind of test, and if it does not work, then we have a problem. Even if there is no domain specification, customer requirement, about that. It's just common sense, comes up with least astonishing result, or because, for my math, algebraic background it is really strange that the domain is modelled without recognizing such obvius thing.&lt;br /&gt;&lt;br /&gt;Thinking in this way is ok, and you can go much more deeper, also with much more implications, and the suggested solution can be reasonabile, but not obvius in the way it could be implemented.&lt;br /&gt;&lt;br /&gt;Coexistence of different implementations of complex numbers: polar and rectangular.&lt;br /&gt;&lt;br /&gt;There can even be different actual classes for them. Why not? Team A assumed rectangular representation, team B assumed polar representation and they developed their own implementations.&lt;br /&gt;&lt;br /&gt;They were thinking about the "same" thing, but they did not implemented them in a compatibile way.&lt;br /&gt;&lt;br /&gt;Now do we want make those classes working together? How?&lt;br /&gt;&lt;br /&gt;Will we make them collapse in the same class? With two different constructor? One that takes the real and img parameter, and another one that takes the angle and magnitude?&lt;br /&gt;&lt;br /&gt;Can be done, if the two constructor are not both considered as the same type (float, or double, for instance).&lt;br /&gt;&lt;br /&gt;Another way to think that is like a pattern that abstracts the actual representation by a factory, and a way to define a metalevel description of equivalence.&lt;br /&gt;&lt;br /&gt;The object will be seen only by an interface, (a "contract") with all the "observers" methods, and the equals can be implemented just cheking the fact that the other class implements the contract interface and that the interface defined observers produce all the same result.&lt;br /&gt;&lt;br /&gt;Makes sense?&lt;br /&gt;Can be: we are looking for something like&lt;br /&gt;&lt;br /&gt;myObjectFactory.setImplementation("rectangular)&lt;br /&gt;a = myObjectFactory.getObject(1,1);&lt;br /&gt;myObjectFactory.setImplementation("polar")&lt;br /&gt;b= myObjectFactory.getObject(sqrt(2),math.PI/4)&lt;br /&gt;//a.equals(b) is true&lt;br /&gt;&lt;br /&gt;and, moreover, we are free to use any implementation, and decide at run time to select any of them without changing the behavior of the program.&lt;br /&gt;&lt;br /&gt;The next step is the ability to hide also the object creation diversity, disinguishing from the "apparent" implementation and the "actual" implementation:&lt;br /&gt;&lt;br /&gt;myObjectFactory.setApparentImplementation("rectangular");&lt;br /&gt;myObjectFactory.setRealImplementation("polar");&lt;br /&gt;a = myObjectFactory.getObject(1,1);&lt;br /&gt;// a.getClass() will return Polar&lt;br /&gt;myObjectFactory.setRealImplementation("rectangular");&lt;br /&gt;b= myObjectFactory.getObject(1,1,);&lt;br /&gt;&lt;br /&gt;// a.getClass() will return rectangular&lt;br /&gt;// a.equals(b) is true&lt;br /&gt;&lt;br /&gt;We need to add at some metaclasses level the code conversion between different representations, and some guarantee about interchangeability, like with a lot of unit tests, even with random generated samples.&lt;br /&gt;&lt;br /&gt;Let's go back to plain numbers. Another issue can be the "extensions":&lt;br /&gt;we defined math about relative numbers, and we would like to extend those relative numbers to rationals.&lt;br /&gt;&lt;br /&gt;They will be perfectly compatible. you can do 1+ 1/2 and get 3/2 as result.&lt;br /&gt;&lt;br /&gt;We can see rationals as a class extension of naturals, and make the things work so 1 and 1/1 are considered equals.&lt;br /&gt;&lt;br /&gt;Making that kind of thing works, can be not trivial, if you don't want surprises. There are two kind of equals implementations: instanceof and getClass().&lt;br /&gt;The "instanceof" based implementation of equals does not respect the equals contract (being reflexive, transitive, simmetric), however the .getClass() based implementation returns false for objects that belongs to different classes.&lt;br /&gt;So comparison with subclasses will be always false, then 1 and 1/1 will not be equals.&lt;br /&gt;We can modify the rational number extendings the tests, including checking if the class belongs to the rational subclass.&lt;br /&gt;&lt;br /&gt;That would be necessary for any extensions, and in that sense our equals implementation is not closed to extension.&lt;br /&gt;&lt;br /&gt;There is an equals implementation tecnique, based on tree traversal, (google keywords: "secrect of equals") that is actually open to extensions and closed to modification.&lt;br /&gt;&lt;br /&gt;Being always closed to modification can be impossible.&lt;br /&gt;You will much more likely try to be closed to modification and open to extensions respect of the more likely future code evolutions (strategical clousure).&lt;br /&gt;Fortunately for the equals there exist a closed (to subclassing) solution, so there is not strategy to think.&lt;br /&gt;It is not so easy to understand, and any IDE generates the equals only according to the "instance of" or "getClass" alternatives.&lt;br /&gt;Moreover, nowadays people don't like subclassing at all.&lt;br /&gt;&lt;br /&gt;The mainstream approach is avoiding subclassing and prefer  composition, so seems to me that nobody also cares about smart equals strategy open to extensions respect of subclassing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-5448326853201437397?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/5448326853201437397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=5448326853201437397' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5448326853201437397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5448326853201437397'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2009/04/open-closed-to-equals-and-subclassing.html' title='toward an open closed equals and subclassing strategy'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-3807116212086546464</id><published>2008-11-02T13:32:00.003+01:00</published><updated>2008-11-02T13:54:25.724+01:00</updated><title type='text'>Preview, development version of "Rosita"</title><content type='html'>Rosita is an open source tool to practice your vocabulary of a language that you are learning.&lt;br /&gt;&lt;br /&gt;It is based on:&lt;br /&gt;1) an input text area where you write down the word you are going to memorize&lt;br /&gt;2) an html/xml parsing engine that tries to looks up the translations of the words on google dictionary, completing the text are with tab separated format word + translation&lt;br /&gt;3) a check box based exercise to play to memorize them.&lt;br /&gt;4) an engine to lookup and visualize related sentences containing the words that you are practicing&lt;br /&gt;&lt;br /&gt;The current set of terms can be saved and loaded in xml format (utf-8 encoded).&lt;br /&gt;&lt;br /&gt;At a development phase, it supports just russian-english. In the next build I'll include other language pairs. Stay tuned.&lt;br /&gt;&lt;br /&gt;A scenario of use of this tool can be the integtration with lingq (&lt;a href="www.lingq.com"&gt;www.lingq.com&lt;/a&gt;) because the new learnig words (lingqs) can be easily exported by copy and paste into the rosita text area.&lt;br /&gt;&lt;br /&gt;&lt;a href="Rosita%20is%20an%20open%20source%20tool%20to%20practice%20your%20vocabulary%20during%20your%20foreign%20language%20learning%20%20It%20is%20based%20on:%201%29%20an%20input%20text%20area%20where%20you%20write%20down%20the%20word%20you%20are%20going%20to%20memorize%202%29%20an%20html/xml%20parsing%20engine%20that%20tries%20to%20looks%20up%20the%20translations%20of%20the%20words%20on%20google%20dictionary,%20completing%20the%20text%20are%20with%20tab%20separated%20format%20word%20+%20translation%203%29%20a%20check%20box%20based%20exercise%20to%20play%20to%20memorize%20them.%204%29%20an%20engine%20to%20visualize%20related%20sentences%20containing%20the%20words%20that%20you%20are%20practicing%20%20The%20current%20set%20of%20terms%20can%20be%20saved%20and%20loaded%20in%20xml%20format%20%28utf-8%20encoded%29.%20%20At%20a%20development%20phase,%20it%20supports%20just%20russian-english.%20In%20the%20next%20build%20I%27ll%20include%20other%20language%20pairs.%20Stay%20tuned.%20%20A%20scenario%20of%20use%20of%20this%20tool%20can%20be%20the%20integtration%20with%20lingq%20%28www.lingq.com%29%20that%20allows%20you%20the%20creation%20of%20new%20lingq.%20%20http://code.google.com/p/rosita/"&gt;http://code.google.com/p/rosita/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-3807116212086546464?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/3807116212086546464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=3807116212086546464' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3807116212086546464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/3807116212086546464'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2008/11/preview-development-version-of-rosita.html' title='Preview, development version of &quot;Rosita&quot;'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-5275767213856200</id><published>2008-04-22T17:11:00.003+02:00</published><updated>2008-04-22T17:16:12.729+02:00</updated><title type='text'>Object substitutability with a random check to ensure equivalent behavior</title><content type='html'>To read the article follow this &lt;a href="http://alucca.mondora.com/2008/04/certifiable-substitutability-for.html"&gt;link.&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;Cheers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-5275767213856200?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/5275767213856200/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=5275767213856200' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5275767213856200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5275767213856200'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2008/04/object-substitutability-with-random.html' title='Object substitutability with a random check to ensure equivalent behavior'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-445955208381612344</id><published>2008-02-18T19:21:00.004+01:00</published><updated>2010-11-14T12:25:41.523+01:00</updated><title type='text'>how to find what jar contain a particular class?</title><content type='html'>Using the Unix bash shell:&lt;br /&gt;&lt;br /&gt;if your current directory contains all the jar to scan, and the class you are looking for contains a substring like some.package.MyClass:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;for i in `ls *.jar`;&lt;br /&gt;do echo $i;&lt;br /&gt;jar -tvf $i | grep some.package.MyClass;&lt;br /&gt;done;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Your jars can be in different subdirectories, at any level, under the current directory. Then you can use:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;for i in `find . -name | egrep ".*\.jar$"`;&lt;br /&gt;do echo $i; jar -tvf $i | grep some.package.MyClass;&lt;br /&gt;done;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The result is the list of all the jars, and if a particular jar contains a class that maatches the string you specified (some.package.MyClass), then the complete name of such classe is prompted after the jar.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Enjoy&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-445955208381612344?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/445955208381612344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=445955208381612344' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/445955208381612344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/445955208381612344'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2008/02/how-to-find-what-jar-contain-particular.html' title='how to find what jar contain a particular class?'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-719654473848761022</id><published>2008-02-11T21:04:00.000+01:00</published><updated>2008-02-11T21:05:19.774+01:00</updated><title type='text'>No, you can't</title><content type='html'>&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/EUKINg8DCUo&amp;rel=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/EUKINg8DCUo&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-719654473848761022?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/719654473848761022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=719654473848761022' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/719654473848761022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/719654473848761022'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2008/02/no-you-cant.html' title='No, you can&apos;t'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-609699729600439671</id><published>2007-12-31T10:56:00.000+01:00</published><updated>2007-12-31T10:59:59.926+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='obama'/><category scheme='http://www.blogger.com/atom/ns#' term='giuliani'/><category scheme='http://www.blogger.com/atom/ns#' term='fun'/><category scheme='http://www.blogger.com/atom/ns#' term='presidential'/><title type='text'>Obama Girl vs Giuliani Girl</title><content type='html'>&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/ekSxxlj6rGE&amp;rel=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/ekSxxlj6rGE&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-609699729600439671?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/609699729600439671/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=609699729600439671' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/609699729600439671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/609699729600439671'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/12/obama-girl-vs-giuliani-girl.html' title='Obama Girl vs Giuliani Girl'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-8422331043289046244</id><published>2007-12-30T14:48:00.000+01:00</published><updated>2007-12-31T09:57:03.246+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='open closed'/><category scheme='http://www.blogger.com/atom/ns#' term='data types'/><category scheme='http://www.blogger.com/atom/ns#' term='depdency inversion'/><category scheme='http://www.blogger.com/atom/ns#' term='abstraction'/><category scheme='http://www.blogger.com/atom/ns#' term='subclass'/><category scheme='http://www.blogger.com/atom/ns#' term='annotations'/><title type='text'>possibile use of java annotations to declare type mapping betwenn different representation of abstract types</title><content type='html'>As we can find looking back at this textbook (&lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book.html"&gt;Structure and Interpratations of Computer Programs&lt;/a&gt;) and particularly to this  &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-17.html#%_sec_2.4.1"&gt;chapter&lt;/a&gt;, in order to have a sound data type hierarchy there must be a strong relation between different concrete implementation of an abstract data type.&lt;br /&gt;&lt;br /&gt;The relation could simply be "the caller, that expects an abstract type, should not be aware of the particular actual type".&lt;br /&gt;&lt;br /&gt;Who and how is responsible to make possible that the concrete type does not violates the caller expectations?&lt;br /&gt;&lt;br /&gt;In the simple case of an immutable type, it is enough for us that there is a sound mapping attributes that is able to convert an instance of an actual type to the equivalent instance of the other actual type.&lt;br /&gt;&lt;br /&gt;Where do we put this mapping?&lt;br /&gt;&lt;br /&gt;For any constructor it will be declared how to convert his parameters, to the parameters needed by another constructor, in order to get an equivalent object, no matter if it is the same or of a different actual type.&lt;br /&gt;&lt;br /&gt;The mapping is possible using the following mathematical relation between polar and rectangular reresentation of complex numbers:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://mitpress.mit.edu/sicp/full-text/book/ch2-Z-G-60.gif"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px;" src="http://mitpress.mit.edu/sicp/full-text/book/ch2-Z-G-60.gif" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://mitpress.mit.edu/sicp/full-text/book/ch2-Z-G-61.gif"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px;" src="http://mitpress.mit.edu/sicp/full-text/book/ch2-Z-G-61.gif" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The miniproject, with some unit tests, is versioned &lt;a href="http://code.google.com/p/turlproject/"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The link between the caller and the actual implementation is provided by a factory, that is able to introspect the annotations to obtain the mapper that will be used to get a particular implementation.&lt;br /&gt;&lt;br /&gt;Any new implementation should declare a mapping between different preexisting implementation.&lt;br /&gt;&lt;br /&gt;We note that in this example we are using immutable objects.&lt;br /&gt;Would we investigate also to mutable as well, we should be aware that it will not be just a matter of equivalence during object creation, but also after any repeated sequences of step that can change object state.&lt;br /&gt;&lt;br /&gt;There is some work to address this issue as well.&lt;br /&gt;&lt;br /&gt;Let's see some sketch of the underlining ideas:&lt;br /&gt;&lt;br /&gt;Definition of complex:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;public interface ComplexNumber {&lt;br /&gt; public double getReal();&lt;br /&gt; @observer public double getImg();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;Here a Rectangular implementation:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;public class RectangularComplexNumber implements ComplexNumber {&lt;br /&gt;protected double real;&lt;br /&gt;protected double img;&lt;br /&gt;&lt;br /&gt;@instanceConverter(instanceConverterMap = CartesianToPolarMapper.class)&lt;br /&gt;public RectangularComplexNumber(double real, double img) {&lt;br /&gt;this.real=real;&lt;br /&gt;this.img = img;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public double getReal() {&lt;br /&gt;return real;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public double getImg() {&lt;br /&gt;return img;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Polar representation has a different constructor, and two extra methods. It mantains also angle and magnitude, not just img and real:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;public class ComplexNumberPolar implements ComplexNumber {&lt;br /&gt;protected double magnitude;&lt;br /&gt;protected Angle angle;&lt;br /&gt;&lt;br /&gt;protected double real;&lt;br /&gt;protected double img;&lt;br /&gt;&lt;br /&gt;@instanceConverter (instanceConverterMap = PolarToCartesianMapper.class)&lt;br /&gt;{&lt;br /&gt; this.magnitude = magnitude;&lt;br /&gt; this.angle = angle;&lt;br /&gt;&lt;br /&gt; this.real = magnitude*Math.cos(angle.getValue());&lt;br /&gt; this.img =  magnitude*Math.sin(angle.getValue());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public double getReal() {&lt;br /&gt; return real;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public double getImg() {&lt;br /&gt; return magnitude*Math.sin(angle.getValue());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public boolean equals(Object object)&lt;br /&gt;{&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public int hashCode()&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;public String toString()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;We can see the two attributes associated to each constructor, respectively&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;@instanceConverter (instanceConverterMap = RectangularToPolarMapper.class)&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;/span&gt;@instanceConverter (instanceConverterMap = PolarToCartesianMapper.class)&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;This new attribute is defined in this way, and specify by default an identity mapper:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;@Retention(RetentionPolicy.RUNTIME)&lt;br /&gt;@Target(ElementType.CONSTRUCTOR)&lt;br /&gt;public @interface instanceConverter {&lt;br /&gt;Class instanceConverterMap() default IdentityToObject.class;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We specified different mappers&lt;br /&gt;&lt;pre&gt;&lt;code&gt;public class RectangularToPolarMapper implements WrapperToObject{&lt;br /&gt;public Wrapper getWrapperForClassConstructorWithParameters(&lt;br /&gt; Class targetClass,&lt;br /&gt; Class targetParamsTypes[],&lt;br /&gt; Class[] originParamsTypes)&lt;br /&gt; {&lt;br /&gt;&lt;br /&gt; if (targetClass.equals(ComplexNumberPolar.class)) {&lt;br /&gt;     return new CartesianToPolar();&lt;br /&gt; }&lt;br /&gt; throw new RuntimeException("wrapper not defined for the target class");&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;The returned  "wrapper", is the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;public class CartesianToPolar implements Wrapper {&lt;br /&gt;public Object[] wrap(Object[] object) {&lt;br /&gt; return new Object[] {Math.sqrt((Math.pow((Double) object[0],2.0))+Math.pow((Double) object[1],2.0)),new Angle(Math.atan2((Double) object[1], (Double) object[0]))};&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is the one that is returned to make the inverse transformation:&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;pre&gt;&lt;br /&gt;public class PolarToCartesian implements Wrapper{&lt;br /&gt;public Object[] wrap(Object[] object) {&lt;br /&gt; return new Object[]{(Double)object[0]*&lt;br /&gt;Math.cos(((Angle)object[1]).getValue()),&lt;br /&gt;(Double)object[0]*Math.sin(((Angle)object[1]).getValue())};&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The guy that uses all that stuffs is the factory, that provide a link from abstraction type to actual type:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class ComplexNumbersFactory {&lt;br /&gt;....&lt;br /&gt;public static ComplexNumber getComplexFromCartesianPar(double first ,double second)&lt;br /&gt;{&lt;br /&gt;if (RECTANGULAR.equals(implementation))&lt;br /&gt;{&lt;br /&gt;    return new ComplexNumberCartesian(first,second);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if (POLAR.equals(implementation))&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    ComplexNumber converted = (ComplexNumber) Utilities.getInstanceOfThisActualGivenConstructorOfOther(&lt;br /&gt;ComplexNumberPolar.class,ComplexNumberCartesian.class,&lt;br /&gt;new Object[]{first,second},&lt;br /&gt;new Class[]{double.class,double.class},&lt;br /&gt;new Class[]{double.class,Angle.class});&lt;br /&gt;    return converted;&lt;br /&gt;}&lt;br /&gt;throw new RuntimeException("unadmitted implementation mode "+implementation);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;He fails if the lookup of the mappers fails, and it is a good thing, because it means that someone extended the concrete implementation without providing a way to relate the concrete implementation to the others.&lt;br /&gt;&lt;br /&gt;Just for curiosity, the reflection based mapper lookup is done by the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  public static Object getInstanceOfThisActualGivenConstructorOfOther(&lt;br /&gt;Class targetClass,&lt;br /&gt;Class originClass,&lt;br /&gt;Object[] instanceOriginCompatible,&lt;br /&gt;Class[] instanceOriginClasses,&lt;br /&gt;Class[] instTargetClass)&lt;br /&gt;{&lt;br /&gt; try {&lt;br /&gt;     Constructor constructor = originClass.getConstructor(instanceOriginClasses);&lt;br /&gt;     WrapperToObject wrapper = (WrapperToObject) constructor.getAnnotation(instanceConverter.class).instanceConverterMap().newInstance();&lt;br /&gt;     Object[] convertedPars = ((wrapper.getWrapperForClassConstructorWithParameters(targetClass, instTargetClass,instanceOriginClasses).wrap(instanceOriginCompatible)));&lt;br /&gt;     Constructor targetConstructor = targetClass.getConstructor(instTargetClass);&lt;br /&gt;     Object convertedObject = targetConstructor.newInstance(convertedPars);&lt;br /&gt;     return convertedObject;&lt;br /&gt;&lt;br /&gt; } catch (Exception e) {&lt;br /&gt;     throw new RuntimeException(e);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The factory shows a (real,img) way to construct the object, thus it has nothing to do if the concrete implementation is RECTANGULAR, otherwhise it lookups the mapper examining the constructor, and return the Polar concrete type.&lt;br /&gt;&lt;br /&gt;At the end, we can show some junit test to verify that the things are ok:&lt;br /&gt;&lt;pre&gt;   ComplexNumber first = new ComplexNumberCartesian(1.0,1.0);&lt;br /&gt;// the actual of first is Rectangular&lt;br /&gt;ComplexNumbersFactory.setImplementation(ComplexNumbersFactory.POLAR);&lt;br /&gt;&lt;br /&gt;ComplexNumber second= ComplexNumbersFactory.getComplexFromCartesianPar(1.0,1.0);&lt;br /&gt;// the actual of second is Polar.&lt;br /&gt;&lt;br /&gt;assertEquals(((ComplexNumberPolar)second).getAngle(),new Angle(Math.PI/4));&lt;br /&gt;assertEquals(((ComplexNumberPolar)second).getMagnitude(),Math.sqrt(2.0));&lt;br /&gt;// no cast exeption&lt;br /&gt;&lt;br /&gt;assertEquals(first,second);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Everything works as expected for the number 1+&lt;span style="font-style: italic;"&gt;i.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Summary&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;A concrete type can be more efficient than another, but we need a save way to change concrete types.&lt;br /&gt;&lt;br /&gt;Attribute are used to annotate to constructors how they are related to other constructor to guarantee cross types equivalences.&lt;br /&gt;&lt;br /&gt;Something more than using only "extends"  or "implements" keywords.&lt;br /&gt;&lt;br /&gt;The due of plugging attributes to the constructor declaring the mapper is like saying: hi, if you are going to create a new implementation, you should also take care of how to make possible substitution between any other preexisting implementation with yours, and of course we expect that it will not affect any behavior expected from the other implementations.&lt;br /&gt;&lt;br /&gt;(just a little note: the code is &lt;a href="http://code.google.com/p/turlproject/"&gt;versioned&lt;/a&gt;, and it has also been refactored, soo can be a little bit different from how it has been shown in this post).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Regards, and Happy New Year!&lt;br /&gt;&lt;br /&gt;T.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-8422331043289046244?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/8422331043289046244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=8422331043289046244' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8422331043289046244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8422331043289046244'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/12/possibile-use-of-java-annotations-to.html' title='possibile use of java annotations to declare type mapping betwenn different representation of abstract types'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-2039916261341011505</id><published>2007-12-16T18:26:00.000+01:00</published><updated>2007-12-16T18:27:06.349+01:00</updated><title type='text'>A Video of the New York Times, about Italy and Beppe Grillo</title><content type='html'>&lt;a href="http://www.nytimes.com/2007/12/13/world/europe/13italy.html?_r=1&amp;amp;oref=slogin"&gt;http://www.nytimes.com/2007/12/13/world/europe/13italy.html?_r=1&amp;amp;oref=slogin&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="355" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/kn5odfqaKzo&amp;amp;rel=1"&gt;&lt;param name="wmode" value="transparent"&gt;&lt;embed src="http://www.youtube.com/v/kn5odfqaKzo&amp;amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" height="355" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-2039916261341011505?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/2039916261341011505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=2039916261341011505' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/2039916261341011505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/2039916261341011505'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/12/video-of-new-york-times-about-italy-and.html' title='A Video of the New York Times, about Italy and Beppe Grillo'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-8356364789787601521</id><published>2007-12-09T21:55:00.000+01:00</published><updated>2007-12-09T21:56:47.882+01:00</updated><title type='text'>web 2.0 in 5 minutes</title><content type='html'>&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/NLlGopyXT_g&amp;rel=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/NLlGopyXT_g&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-8356364789787601521?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/8356364789787601521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=8356364789787601521' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8356364789787601521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8356364789787601521'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/12/web-20-in-5-minutes.html' title='web 2.0 in 5 minutes'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-8910916736110574506</id><published>2007-12-09T11:12:00.000+01:00</published><updated>2007-12-09T11:13:01.662+01:00</updated><title type='text'>Dancing with "mini" in Galway. December 2006</title><content type='html'>&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/dqf_mWXXNd4&amp;rel=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/dqf_mWXXNd4&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-8910916736110574506?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/8910916736110574506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=8910916736110574506' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8910916736110574506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8910916736110574506'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/12/dancing-with-mini-in-galway-december.html' title='Dancing with &quot;mini&quot; in Galway. December 2006'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-1077900513765245455</id><published>2007-12-08T14:16:00.001+01:00</published><updated>2007-12-08T14:17:35.384+01:00</updated><title type='text'>Vilnius - Katedros aikštė</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm3.static.flickr.com/2355/2086455673_b95b2102bf.jpg?v=0"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px;" src="http://farm3.static.flickr.com/2355/2086455673_b95b2102bf.jpg?v=0" alt="" border="0" /&gt;&lt;/a&gt;One of the ordinary paving stones, about halfway between the cathedral and the bell tower, has been replaced with a not-so-ordinary paving stone. It’s the ‘miracle stone’, and it’s tucked under a piece of glass that has recently been replaced so that you can actually see through it (a miracle in itself round here). Embedded into the miracle stone, in coloured letters, is the Lithuanian word for miracle – STEBUKLAS. It’s written in a circle with a single S forming both the start and the end of the word. The stone marks the point where in 1989 two million hand-holding Balts joined together and formed a human chain that spanned the 650km between Vilnius and Tallinn. The tile has become a symbol of freedom and hope and, supposedly, can make your dreams come true. Stand on the tile, make a wish, and turn full-circle clockwise.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-1077900513765245455?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/1077900513765245455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=1077900513765245455' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/1077900513765245455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/1077900513765245455'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/12/vilnius-katedros-aikt.html' title='Vilnius - Katedros aikštė'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-8038664434315521324</id><published>2007-11-24T17:28:00.000+01:00</published><updated>2007-11-24T17:37:17.916+01:00</updated><title type='text'>Odds, by Stanislaw Lem.</title><content type='html'>You can find on line &lt;a href="http://cse.ucdavis.edu/%7Echaos/courses/ncaso/Readings/Lem_Odds_NY1978.html"&gt;here&lt;/a&gt; an ironic essay of the famous science fiction polish writer, Stanislaw Lem (Solaris). It has been published in the book "Perfect Vacuum", a collection of book reviews of nonexistent works of literature.&lt;br /&gt;&lt;br /&gt;"Lem is Harpo Marx and Franz Kafka and Isaac Asimov rolled up into one and down the white rabbit's hole" (Detroit News)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-8038664434315521324?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/8038664434315521324/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=8038664434315521324' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8038664434315521324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/8038664434315521324'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/11/odds-by-stanislaw-lem.html' title='Odds, by Stanislaw Lem.'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-5570555658485098111</id><published>2007-10-20T22:43:00.000+02:00</published><updated>2007-11-08T14:08:41.635+01:00</updated><title type='text'>httpxmlfixture</title><content type='html'>Recently I worked on a fixture for &lt;a href="http://fitnesse.org/"&gt;fitnesse&lt;/a&gt;, for xml xpath based acceptance test and test driven development for web applications.&lt;br /&gt;&lt;br /&gt;It continues the approach introduced by this &lt;a href="http://today.java.net/pub/a/today/2005/11/22/fitnesse-testing-for-agile-web-development.html?page=3"&gt; fixture&lt;/a&gt; that allows to check xpath respect to the content of a web page. Test can check if some nodes identified by xpath are present or not, if they contain some expected value, and how many nodes match the expression.&lt;br /&gt;&lt;br /&gt;I added the following features:&lt;br /&gt;&lt;br /&gt;- test pages that requires authenntication (basic o, in some cases, form)&lt;br /&gt;-  test pages not well formed, using  &lt;a href="http://jtidy.sourceforge.net/"&gt;jTidy&lt;/a&gt; as preprocessor&lt;br /&gt;- manage cookies and so cokies based session&lt;br /&gt;- manage post and get based parameters subscription.&lt;br /&gt;- ability to generate test from statical pages.&lt;br /&gt;&lt;br /&gt;This approach allows acceptance tests for web application only for server side plain web application (no javascript/ajax)&lt;br /&gt;&lt;br /&gt;A sketch of the process of a "costumer test driven development" using this approach could be described as follows: you have a statical html, and you are going to modify some part of it to let it became dynamical (by some server side logic).&lt;br /&gt;&lt;br /&gt;Creating the page is not viable by "test first".&lt;br /&gt;We can just have for free a test that has success if applied to the page.&lt;br /&gt;After we have the test ready, then we can modify, or reuse, it according to some user story that the page is involved to.&lt;br /&gt;In this case we have a test first.&lt;br /&gt;&lt;br /&gt;For example, suppose that we have the prototipe of the page, that contains a table.&lt;br /&gt;The tabloe is the part that must be dynamical.&lt;br /&gt;&lt;br /&gt;The customer says that "in the table there will be some data previously submitted by a form provided in another page".&lt;br /&gt;&lt;br /&gt;To go a little bit deeper through this concept. The statical page could be something like the following:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head/&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;table&amp;gt;&lt;br /&gt;&amp;lt;tr&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;entry1&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;tr&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;entry2&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;tr&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;entry3&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;applying a stylesheet that generates the test from the page, you get the following test:&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;| Value | /html/body/table/tr/td |  entry1 |&lt;br /&gt;| Value | /html/body/table/tr[2]/td |  entry2 |&lt;br /&gt;| Value | /html/body/table/tr[3]/td |  entry3 |&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You can start coding creating a jsp that renders the page in the same way, where the data will be not hard coded. It will be retriven from a db.&lt;br /&gt;&lt;br /&gt;The customer probabily doesn't care about db, or any persistency stuffs. He just asks that "the user will submit some data on that form, and the data will appear in the table".&lt;br /&gt;(Thus such kind of test dos not involve business logic tier.)&lt;br /&gt;&lt;br /&gt;A test based description of that story, can be as follows:&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;|newUrlPost|http://myserver/submitaction.jsp|&lt;br /&gt;|NameValuePair|entryname|entryX|&lt;br /&gt;|newUrlGet|http://myserver/visualize.jsp |&lt;br /&gt;|AValue|/html/body/table/tr[*]/td |  entryX |&lt;br /&gt;&lt;br /&gt;that means somethig like "the submitaction.jsp you are going to implement, will expect a parameter named entryname. If the sumitted parameter is entryX, then, if you navigate to the page visualize.jsp, the entryX should be present in any part of the table"&lt;br /&gt;&lt;br /&gt;This test describes what you will get, and you can start coding the submitaction.jsp and visualize.jsp until the tests doesn't fail.&lt;br /&gt;&lt;br /&gt;To conclude, we can call this stuff an approach like:&lt;br /&gt;&lt;br /&gt;. design the statical page,&lt;br /&gt;. create test that matches if applied to the page,&lt;br /&gt;. modify/reuse/rearrange the test according to a user story where the page is involved,&lt;br /&gt;. code until the test doesn't fail&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-5570555658485098111?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/5570555658485098111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=5570555658485098111' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5570555658485098111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5570555658485098111'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/10/httpxmlfixture.html' title='httpxmlfixture'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-4245993436817476262</id><published>2007-10-17T10:28:00.000+02:00</published><updated>2007-10-17T10:45:10.301+02:00</updated><title type='text'>annotations to mutators and observers to show empirical evidence of substitutability</title><content type='html'>I created a new project about experiment on object oriented notion of  subclasing/substitutability based  on annotations.&lt;br /&gt;&lt;br /&gt;http://testlspjava5.googlecode.com/&lt;br /&gt;&lt;br /&gt;You annotate mutator methods, and observer methods.&lt;br /&gt;Mutators act to change object state, observer to inspect object state.&lt;br /&gt;Instance generator is also defined, by annotations, to any mutator, to generate a (repeatable ) sequence of parameters to be applied to the methods.&lt;br /&gt;&lt;br /&gt;A "random" computation on class is done involving the class, and is based on a repeatable sequence of instance generated to be applied to mutators methods.&lt;br /&gt;It is repeated a second time, involving the subclass instead of the class. The empirical evidence of substitutability is the fact that at any step of the first and the second computation, there is equivalence, where equivalence is defined by same observable state, defined in terms of observer methods.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-4245993436817476262?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/4245993436817476262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=4245993436817476262' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/4245993436817476262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/4245993436817476262'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/10/annotations-to-mutators-and-observers.html' title='annotations to mutators and observers to show empirical evidence of substitutability'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-1556515230197520260</id><published>2007-06-07T16:14:00.000+02:00</published><updated>2007-06-20T15:07:08.770+02:00</updated><title type='text'>more about lsp and equals</title><content type='html'>This post is related to a previous &lt;a href="http://tonyxzt.blogspot.com/2007/01/liskov-substitution-principle-in-java.html"&gt;post&lt;/a&gt;, about relation between the "liskov substitution principle" and the technical  methods choosen to implement equals.&lt;br /&gt;&lt;br /&gt;Equals is a method derived from the Object class, that takes Object as parameter, and obviously can be overridden. If the method is not overridden, then the result is true if the two object are the same object. If the method is overridden,  the comparison against any non null object returns true if the two object are  to be considered equivalent for the domain of the program.&lt;br /&gt;Only immutable objects should redefine equals.&lt;br /&gt;A widely used technique to redefine equals is considering potentially equals only objects belonging to the same class (check is done using getClass()).&lt;br /&gt;&lt;br /&gt;If the object belongs to subclasses? The fact that only object belonging to the same class, and not to subclasses, can be "equals" to an object, can be considered a violation of the Liksov substitution principle, so instead of getClass() the check can be done using instanceof.&lt;br /&gt;However this can lead to an equals implementation that violates the equals contract.&lt;br /&gt;There exists a workaround to this, explained &lt;a href="http://www.angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals-2.html"&gt;here&lt;/a&gt;, that solves this issue, (without mentioning lsp).&lt;br /&gt;There are few examples of &lt;a href="http://sampleliskov.googlecode.com/svn/trunk/src/com/tonyx/lab/liskov/exerc7/"&gt;code&lt;/a&gt; (and &lt;a href="http://sampleliskov.googlecode.com/svn/trunk/src/test/com/tonyx/lab/liskov/exerc7/"&gt;unit tests)&lt;/a&gt; implemented using this technique.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Angelika Langer,  coauthor of the paper about the comparison strategy that I consider a solution, sent me a personal email telling me that this issue about "equals" has nothing to do with LSP: "Talking about LSP in conjunction with the  implementation technique chosen for "equals" is a red herring".&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;In her opinion the big issue is just that Java forces you to redefine equals because of the way it works in conjunction with collections, and so you are forced to use different semantics comparisons using the same method name.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;She told me that the issue is basically a java design flaw, and anything about LSP.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Moreover she invited me to take a look, for example, "at the containers in &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;the C++ standard library.  They do not require any hard-wired function &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;names for equals or compareTo thereby allowing to avoid the problem of &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;different semantics under the umbrella of the same function name"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I would agree on that, however, I just think that LSP *has* to do with equals implementation because:&lt;br /&gt;the principle has to do with object behavior and object behavior has to do with it's methods, including "equals".&lt;br /&gt;This is my very humble opinion.&lt;br /&gt;&lt;br /&gt;A way to define lsp is:&lt;br /&gt;"&lt;span style="font-style: italic;"&gt;function that uses pointers or references to base classes must be able to use objects of derived classes without knowing it&lt;/span&gt;" (&lt;a href="http://www.objectmentor.com/resources/articles/lsp.pdf"&gt;http://www.objectmentor.com/resources/articles/lsp.pdf&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;In any non final classes, equals method, if implemented via getClass(), always return false when applied to subclasses  (unless it "knows" such subclasses i.e. coded so that the getClass()  comparison is made also for all known subclasses of the class. This is a violation of lsp in those terms :  "&lt;span style="font-style: italic;"&gt;[if] a function does not conform to the LSP, then that function uses a pointer or reference to a base class, but must know about all the derivatives of that base class.&lt;/span&gt;")&lt;br /&gt;&lt;br /&gt;If the comparison is made using instanceof, then class objects can be equal to subclass objects (without making the equals method having to know them, but there is the risk that the equals is not transitive, simmetric, and so violates the equals contract.&lt;br /&gt;For examples see: &lt;a href="http://angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals.html"&gt;http://angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals.html&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;For other references about the "instanceof" vs "getClass()" argument in implementing equals see also:&lt;br /&gt;&lt;a href="http://www.artima.com/intv/bloch17.html"&gt;http://www.artima.com/intv/bloch17.html&lt;/a&gt; (curiusly Joshua Bloch is for "instanceof", to preserve the possibility to make comparison to subclass objects, and in the same time in his book the example is based on _final_ classes, that cannot be subclassed).&lt;br /&gt;&lt;br /&gt;About examples that show when class/subclass equality has sense:&lt;br /&gt;&lt;br /&gt;a Rectangle with only positive values of X and Y is subclassed with a Rectangle that can be instantiated with negative X and Y values as well.&lt;br /&gt;&lt;br /&gt;(It is a subclass that weakens the "precondition" and thus, incidentally, is compliant by the design by contract specifications.)&lt;br /&gt;&lt;br /&gt;If rectangle redefines equals by getClass() then RectangleWithNegatives(1,1) is not equals to RectangleImpl(1,1).&lt;br /&gt;&lt;br /&gt;In &lt;span style="font-style: italic;"&gt;this&lt;/span&gt; case instanceof solves the problem (and is compliant with equals contract).&lt;br /&gt;getClass does not.&lt;br /&gt;&lt;br /&gt;There are cases in witch subclasses extend other attributes (new dimension, color and so on...)&lt;br /&gt;and in such cases &lt;span style="font-style: italic;"&gt;instanceof&lt;/span&gt; does not respect equals contract (see, again &lt;a href="http://angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals.html"&gt;http://angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals.html&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;You can simply avoid the problem  considering rectangle with color not subclass of rectangle  and rather  a composition of rectangle and color.&lt;br /&gt;&lt;br /&gt;However, if you &lt;span style="font-style: italic;"&gt;do&lt;/span&gt; subclass it, then:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;if&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;you want that your equals implementation will be able to return true if applied to object of the class and to object of a derived class as well.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-style: italic;"&gt;and&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;in your domain there is an equivalence relation between (a subset of) subclass objects and class object and you look for an implementation of equals that fulfills this equivalence and equals contract &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-style: italic;"&gt;and&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;you want an "equals" solution  "closed" against subclasses (i.e. does not need to know subclasses),&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-style: italic;"&gt;then&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the aproach of equals shown in &lt;a href="http://www.angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals-2.html"&gt;http://www.angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals-2.html&lt;/a&gt; and implemented in my examples is appropriate.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Possible critics:&lt;br /&gt;a - "the lsp does not hold in java at all".&lt;br /&gt;b - "avoid subclassing: it is dangerous. Use different solutions, like composition"&lt;br /&gt;c - easy to talk about toy examples. And what about real problems?&lt;br /&gt;&lt;br /&gt;a) yes. It is easy to say that "lsp does not hold in java". Lsp states that S is subtype of T if you can do some class/subclass substitution without changing the behaviour of any program.&lt;br /&gt;&lt;br /&gt;"&lt;span style="font-style: italic;"&gt;If for each object o1  of type S there is an object o2  of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;It's easy to show programs that changes their behaviour making substitution.&lt;br /&gt;&lt;br /&gt;example, all the programs that contain the statement: if myObject.getClass().equals(T.class).&lt;br /&gt;&lt;br /&gt;It is defined in terms of T, and if it is applied to any different class, including subclass, returns always false, and if applied to any object of T returns true.&lt;br /&gt;So for all object of any class different from T, there is no possibility to substitute such object with object of T, and thus in Java cannot exist any class that is subclass of T (!).&lt;br /&gt;I.e. no class in java can be subclassed without violating LSP.&lt;br /&gt;&lt;br /&gt;See also (&lt;a href="http://alblue.blogspot.com/2004/07/java-liskov-substution-principle-does.html"&gt;http://alblue.blogspot.com/2004/07/java-liskov-substution-principle-does.html&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;The interpretation is ok. Then: avoid subclassing.&lt;br /&gt;&lt;br /&gt;Another approach is to weaken the lsp definition in the following way:&lt;br /&gt;&lt;br /&gt;given that in our language "lsp does not hold strictly" then it is &lt;span style="font-style: italic;"&gt;our&lt;/span&gt; option to implement our classes and subclasses in a way that if we use them in a clean object oriented approach, then lsp holds.&lt;br /&gt;Using run time type information is not what we mean by clean  object oriented approach.&lt;br /&gt;&lt;br /&gt;So we can apply the statement in this way: "if you subclass, do it in a way that lsp holds if your object are used in a pure oo"&lt;span style="font-style: italic;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;b) "avoid subclass". Avoid subclass when we know that is so dangerous.&lt;br /&gt;Why is it dangerous? Because we cannot predict what happens during subclassing. Something unexpected happens because we do not comply with some principles like lsp? (Design by contract)?  Sounds like "The chiken and the egg".&lt;br /&gt;So: use object oriented, and follow design principles, and apply the same unit tests related of any class, to subclasses as well, then you will not be afraid of subclass.&lt;br /&gt;&lt;br /&gt;c) what about real examples? I'm working on it. Any hint is welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-1556515230197520260?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/1556515230197520260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=1556515230197520260' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/1556515230197520260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/1556515230197520260'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/06/how-sp-and-equals-implementation-are.html' title='more about lsp and equals'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-7932292377442420649</id><published>2007-04-14T12:26:00.000+02:00</published><updated>2007-05-08T13:58:39.572+02:00</updated><title type='text'>google acquires doubleclick</title><content type='html'>A very big step:&lt;br /&gt;&lt;a href="http://www.businessweek.com/technology/content/apr2007/tc20070414_675511.htm?chan=top+news_top+news+index_businessweek+exclusives"&gt;http://www.businessweek.com/technology/content/apr2007/tc20070414_675511.htm?chan=top+news_top+news+index_businessweek+exclusives&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;Now any banner used by doubleclick can show "personalized" content per user profiled by click through analysis that doubleclick potencially already own *and* user analysis stored by google ads, google search, text analysis on the gmail account and so on...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-7932292377442420649?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/7932292377442420649/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=7932292377442420649' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/7932292377442420649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/7932292377442420649'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/04/google-aquires-doubleclick.html' title='google acquires doubleclick'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-6895813697752846393</id><published>2007-03-07T12:03:00.000+01:00</published><updated>2007-03-07T12:31:44.028+01:00</updated><title type='text'>tree traversal "equals" implementation</title><content type='html'>I tested the "tree traversal" approach to the implementation of equals.&lt;br /&gt;&lt;br /&gt;It is not so straighforward to understand, but you don't need to do it to be sure it works. I just wrote unit tests that checks that simmetry, transitivity contract is respected combining class/subclasses and differnet branches of a same class herarchy. It is enough to prove thet it works.&lt;br /&gt;&lt;br /&gt;Using this approach, if you extend any class A to class B, and you redefine the "equals" method for A, then for two object &lt;span style="font-style: italic;"&gt;a1&lt;/span&gt;, and &lt;span style="font-style: italic;"&gt;a2&lt;/span&gt;, belonging to A, initialized in the same way,  &lt;span style="font-style: italic;"&gt;a1.equals(a2)&lt;/span&gt; is true, &lt;span style="font-style: italic;"&gt;and&lt;/span&gt;  &lt;span style="font-style: italic;"&gt;a1.equals(b1)&lt;/span&gt; is true for any b belonging to B initialized int the same way of a1 (and eventual extra fields that are in b and not in a, must have default values).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-6895813697752846393?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/6895813697752846393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=6895813697752846393' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/6895813697752846393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/6895813697752846393'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/03/tree-traversal-equals-implementation.html' title='tree traversal &quot;equals&quot; implementation'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-5865722269091072002</id><published>2007-02-16T16:21:00.000+01:00</published><updated>2007-02-16T17:26:18.623+01:00</updated><title type='text'>tree traversal for mixed type comparison</title><content type='html'>In the follwing link something better about "mixed type" implementation of equals. I'll apply it to the examples about my previus post.&lt;br /&gt;http://www.angelikalanger.com/Conferences/Slides/JavaEquals-ACCU-2002.pdf&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-5865722269091072002?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/5865722269091072002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=5865722269091072002' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5865722269091072002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/5865722269091072002'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/02/tree-traversal-for-mixed-type.html' title='tree traversal for mixed type comparison'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2819327489527180569.post-2747391200666345733</id><published>2007-01-09T00:07:00.000+01:00</published><updated>2007-01-17T18:16:24.772+01:00</updated><title type='text'>Liskov Substitution Principle in Java</title><content type='html'>I'm working on some examples that show what is, as I can understand, the meaning of the Liskov Substitution Principle, and how you can deal with it in Java.&lt;br /&gt;&lt;br /&gt;The home of the project is http://code.google.com/p/sampleliskov/&lt;br /&gt;&lt;br /&gt;A lot of issues are pointed out, particularly  about the implementation of equals in a way that respects the principle and the equals contract (transitivity, simmetry, reflexivity) as well.&lt;br /&gt;&lt;br /&gt;Another point is a sort of randomized test that shows statistical evidence that two objects are substituble.&lt;br /&gt;&lt;br /&gt;You can find on the net  a lot of opinions and example of code, that advocates implementation of equals by &lt;span style="font-style: italic;"&gt;getClass&lt;/span&gt;, or by &lt;span style="font-style: italic;"&gt;instanceof&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;You can put on google keywords like "some objects are not equals than other" or "equals liskov substitution principle Bloch" to find those opinions.&lt;br /&gt;&lt;br /&gt;Essentially: the guys that prefer to implement equals by &lt;span style="font-style: italic;"&gt;getClass &lt;/span&gt;say that &lt;span style="font-style: italic;"&gt;using instanceof&lt;/span&gt; violates the equals contract (simmetry and so on...), and the guys that advoacate &lt;span style="font-style: italic;"&gt;instanceof &lt;/span&gt;says that implementing it with &lt;span style="font-style: italic;"&gt;getClass &lt;/span&gt; doesn't respect the Liskov Substitution Principle.&lt;br /&gt;&lt;br /&gt;The second is true, but I think that the first is not necessarily true, and it's I'm trying to investigate.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Issues about intanceof may happen when you compare a class with its subclass: there can be no transitivity, or, after fixing this,  no simmetry.&lt;br /&gt;&lt;br /&gt;After this experience  I'm confident that it is possible to address this issue in a simple way: when you compare a class with any class that is recognized as a your subclass then you delegate to the subclass the equality check.&lt;br /&gt;&lt;br /&gt;This check is also "open" to extentions and so it does not violate another related principle that is called "open closed".&lt;br /&gt;&lt;br /&gt;Other parts of the code are related to other issues about lsp and some way to detect lsp violation without using any  "design by contract" extension framework.&lt;br /&gt;&lt;br /&gt;A simple approach is: use Junit and rewrite the same tests you wrote for the class, for the subclass as well, and if those tests does not succed, then the principle is violated.&lt;br /&gt;&lt;br /&gt;Another triky approach I experimented suggests a sort  of "randomized" test: generate a random sequance of state for the object of the class, repeat it for the object of the subclass and then  check their "equality".&lt;br /&gt;&lt;br /&gt;Tonino&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;P.s.: I want to make clearer something about this "&lt;/span&gt;equals&lt;span style="font-style: italic;"&gt;" concept, because you can argue, correctly,  that "equals" is not the correct term. It rather should be called "&lt;/span&gt;equivalent state&lt;span style="font-style: italic;"&gt;" or "&lt;/span&gt;similar&lt;span style="font-style: italic;"&gt;".&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;In fact two mutable objects should not implement &lt;/span&gt;equals&lt;span style="font-style: italic;"&gt; as "same state", but as "same object". (from Barbara liskov - Program development in java, pag 94).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;I can use, for mutable object, another method, like "similar", according to Liskov .&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;I'd have to  change the code a little bit in order to be more compliant with object orientation.&lt;br /&gt;I'll write a "revised version" of  this post.&lt;br /&gt;&lt;br /&gt;However: it does not change the mainstream ideas  I focused that are:&lt;br /&gt;- the implementation of equals in a way that allows mixed type comparison between type and subtypes,&lt;/span&gt; &lt;span style="font-style: italic;"&gt;with "open closed principle" &lt;/span&gt;compliancy&lt;br /&gt;&lt;span style="font-style: italic;"&gt;- the "randomized" test that shows statistical evidence that two object are substituble.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2819327489527180569-2747391200666345733?l=tonyxzt.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tonyxzt.blogspot.com/feeds/2747391200666345733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2819327489527180569&amp;postID=2747391200666345733' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/2747391200666345733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2819327489527180569/posts/default/2747391200666345733'/><link rel='alternate' type='text/html' href='http://tonyxzt.blogspot.com/2007/01/liskov-substitution-principle-in-java.html' title='Liskov Substitution Principle in Java'/><author><name>Antonio Lucca</name><uri>http://www.blogger.com/profile/13458215940711528728</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://4.bp.blogspot.com/_bUxSGU1m8WY/TQlb7xVNDSI/AAAAAAAAAXg/VG6wr4a_eTs/s1600-R/tonyx2.png'/></author><thr:total>1</thr:total></entry></feed>
