<?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:blogger='http://schemas.google.com/blogger/2008' 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-5356363081772370386</id><updated>2024-11-01T09:27:22.466+01:00</updated><category term="TDD"/><category term="DDD"/><category term="NUnit"/><category term="PSD"/><category term="Unit Test"/><category term="Visual Studio"/><category term="scrum.org"/><category term="training"/><category term="ATDD"/><category term="CQRS"/><category term="Communauté de pratique"/><category term="IDE"/><category term="Java"/><category term="LINQ"/><category term="MSTest"/><category term="PSM"/><category term="SOLID"/><category term="Scrum"/><category term="agile testing"/><category term="atelier"/><category term="coaching"/><category term="coding dojo"/><category term="général"/><category term="kata"/><category term="logiciel libre"/><category term="moteur de recherche"/><category term="principes agiles"/><category term="refactoring"/><title type='text'>Ernst&#39;s Thoughts</title><subtitle type='html'>On things such as agile development, web development, .Net, Java, etc.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-1828720729471201263</id><published>2015-04-26T16:59:00.000+02:00</published><updated>2015-04-26T16:59:17.698+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="NUnit"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Unit Test"/><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio"/><title type='text'>Développement ASP.NET piloté par les tests (partie 2)</title><content type='html'>&lt;div style=&quot;font-family: Calibri; margin: 0in;&quot;&gt;
Ce billet fait partie d&#39;une série sur le &lt;a href=&quot;http://ernststhoughts.blogspot.fr/2015/04/developpement-aspnet-pilote-par-les.html&quot; target=&quot;_blank&quot;&gt;développement ASP.NET piloté par les tests&lt;/a&gt;.&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3 style=&quot;font-family: Calibri; margin: 0in;&quot;&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Le premier test&lt;/span&gt;&lt;/h3&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
Dans le &lt;a href=&quot;http://ernststhoughts.blogspot.fr/2015/04/developpement-aspnet-pilote-par-les.html&quot; target=&quot;_blank&quot;&gt;dernier billet&lt;/a&gt;, j&#39;ai présenté les raisons qui me poussent à partir de la page blanche
lorsqu&#39;il s&#39;agit de créer une application web que je maîtrise dans tous ses
aspects. Assez confiant de cette stratégie, je me lance dans le développement
de l&#39;application. J&#39;ai une idée très imprécise du périmètre de cette
application. Tout ce que je sais pour l&#39;instant c&#39;est que ce sera une
application web qui affichera les scores de matchs de tennis. &lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ol style=&quot;direction: ltr; font-family: Calibri; font-size: 11pt; font-weight: bold; margin-bottom: 0in; margin-left: 0.375in; margin-top: 0in; unicode-bidi: embed;&quot; type=&quot;1&quot;&gt;
&lt;li style=&quot;margin-bottom: 0px; margin-top: 0px; vertical-align: middle;&quot; value=&quot;1&quot;&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;Accès à l&#39;application web&lt;/span&gt;&lt;/li&gt;
&lt;ol style=&quot;direction: ltr; font-size: 11pt; margin-bottom: 0in; margin-left: 0.375in; margin-top: 0in; unicode-bidi: embed;&quot; type=&quot;a&quot;&gt;
&lt;li style=&quot;margin-bottom: 0px; margin-top: 0px; vertical-align: middle;&quot; value=&quot;1&quot;&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;Message de bienvenue&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 0px; margin-top: 0px; vertical-align: middle;&quot;&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;Liste
      des matchs en cours&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 0px; margin-top: 0px; vertical-align: middle;&quot;&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;Créer
      un nouveau match&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 0px; margin-top: 0px; vertical-align: middle;&quot;&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;Charte
      graphique&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
C&#39;est déjà pas mal
comme exigences. Et même si on est loin d&#39;avoir un ensemble complet de
fonctionnalités, j&#39;ai beaucoup à mettre en place en terme d&#39;environnement et
d&#39;infrastructure de développement. La question est donc par où commencer ?
Etant donné que je me laisse guider par les tests, la réponse est à la fois
facile et non évidente. Facile, parce qu&#39;il me faut bien sûr commencer par un
test. Non évidente parce qu&#39;il me faut trouver le premier test.&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
La plupart des
tutoriels du développement piloté par les tests débutent par un test unitaire,
c’est-à-dire un test qui vérifie le comportement ou le résultat d&#39;une méthode
d&#39;une classe. Bien que je comprenne la pédagogie de cette approche, dans la
pratique c&#39;est loin d&#39;être la façon la plus efficace de débuter un projet. En
effet, il y a risque de s’égarer dans des détails et considérations techniques
sans vraiment progresser dans mon but qui est de livrer une version
fonctionnelle de cette application. J’utilise les tests pour me donner des
objectifs précis et atteignables tout en m’assurant qu’à la fin
j’aurai&amp;nbsp;quelque chose de tangible pour un utilisateur.&amp;nbsp; Mon premier test ne sera donc pas un test
unitaire mais plutôt un test fonctionnel qui va vérifier qu&#39;une fonctionnalité
utile du point de vue d&#39;un utilisateur est bien présente dans l&#39;application.&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
Je décide donc de me
concentrer sur le message de bienvenue de la page d&#39;accueil.&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ol style=&quot;direction: ltr; font-family: Calibri; font-size: 11pt; margin-bottom: 0in; margin-left: 0.375in; margin-top: 0in; unicode-bidi: embed;&quot; type=&quot;1&quot;&gt;
&lt;li style=&quot;margin-bottom: 0; margin-top: 0; vertical-align: middle;&quot; value=&quot;1&quot;&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;Accès à l&#39;application&lt;/span&gt;&lt;/li&gt;
&lt;ol style=&quot;direction: ltr; font-size: 11pt; margin-bottom: 0in; margin-left: 0.375in; margin-top: 0in; unicode-bidi: embed;&quot; type=&quot;a&quot;&gt;
&lt;li style=&quot;margin-bottom: 0; margin-top: 0; vertical-align: middle;&quot; value=&quot;1&quot;&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;Message de
      bienvenue&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;direction: ltr; font-size: 11pt; margin-bottom: 0in; margin-left: 0.375in; margin-top: 0in; unicode-bidi: embed;&quot; type=&quot;a&quot;&gt;
&lt;li style=&quot;color: #7f7f7f; margin-bottom: 0; margin-top: 0; vertical-align: middle;&quot; value=&quot;2&quot;&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;Liste
      des matchs en cours&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;color: #7f7f7f; margin-bottom: 0; margin-top: 0; vertical-align: middle;&quot;&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;Créer un nouveau match&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;color: #7f7f7f; margin-bottom: 0; margin-top: 0; vertical-align: middle;&quot;&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;Charte graphique&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;div style=&quot;color: #7f7f7f; font-family: Calibri; font-size: 11.0pt; margin-left: .75in; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-size: 11pt; margin: 0in;&quot;&gt;
&lt;span style=&quot;font-family: Calibri;&quot;&gt;Il me faut donc
créer un test qui accède à la page d&#39;accueil de l&#39;application et vérifie la
présence du message de bienvenue. Puisque je n&#39;ai pas encore codé l&#39;application
ce test va évidemment échouer. Par contre ce premier test est capital car une
fois rédigé, il me permet de savoir sans équivoque que j&#39;ai terminé le premier
des 4 points qui satisferont&lt;/span&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Calibri;&quot;&gt;les utilisateurs. &lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
Je vais donc créer
une solution qui ne contiendra pour l&#39;instant que mon projet de tests.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnWpFi_7hsg1Gx40lgkOFhAmM3RRxvypkrgHe5vJYRLQD2SSpZUH85uoTEctZXPpglMJOW2ghOVxSJHfJFkgJqpHXgDL-KEzVUT1YUTXBliD-2wkwVlc2WiHSQRb0J9ofP48iSHPQYgY0/s1600/project+creation.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnWpFi_7hsg1Gx40lgkOFhAmM3RRxvypkrgHe5vJYRLQD2SSpZUH85uoTEctZXPpglMJOW2ghOVxSJHfJFkgJqpHXgDL-KEzVUT1YUTXBliD-2wkwVlc2WiHSQRb0J9ofP48iSHPQYgY0/s1600/project+creation.png&quot; height=&quot;388&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
Une des premières
décisions à prendre est quel framework de test utiliser. J&#39;ai toujours préféré
l&#39;API d&#39;assertion de NUnit à celui de MSTest. Ma prochaine tâche consiste à
installer NUnit et vérifier que tout fonctionne bien dans mon environnement.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4Cfdz_Behot49WMpnRPRN1QS6xK9B41gl1LqjOzDmelgUWb6AHMa69nyexhJEoBgQD06rmQgMiqqabZvLZkGx6m2_MobGv2VljJcMtldu0Ckc8CqWJluzULmjwq-ApVrP8DCtx77XamA/s1600/install+nunit.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4Cfdz_Behot49WMpnRPRN1QS6xK9B41gl1LqjOzDmelgUWb6AHMa69nyexhJEoBgQD06rmQgMiqqabZvLZkGx6m2_MobGv2VljJcMtldu0Ckc8CqWJluzULmjwq-ApVrP8DCtx77XamA/s1600/install+nunit.png&quot; height=&quot;186&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
En
passant, je suis dans le TGV vers Karlsruhe… Il n&#39;y a pas d&#39;accès wifi à
Internet comme l&#39;indique le message d&#39;alerte de Nuget. Une chance que j&#39;ai déjà
installé Nunit sur ma machine. J&#39;espère que je pourrai me rendre au bout de
l&#39;exercice…&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
Je crée mon premier
test. Rien d&#39;époustouflant pour l&#39;instant. Je veux juste m&#39;assurer que j&#39;aurai
un feedback lorsque quelque chose ne va pas. Pour cela, la tactique consiste à
créer un test qui échoue forcément et voir comment Visual Studio s&#39;organise pour
m&#39;avertir de cet échec. La classe &lt;code&gt;BasicTest&lt;/code&gt; avec son assertion d&#39;échec &lt;code&gt;Assert.Fail();&lt;/code&gt; devrait suffire.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRZdJ1wREVlqiTjABrSmyZrWJCOiVf7FcWrEKHZDC_XPHRt-JovMjC7uLS43L0SurvsvFE0SS-oUBD4un8hDDDEi-zXDKQ1NDdVx6MvHAqyk2mMtEoreZ6lUxAOvc87UZeM7fEeYKgnCY/s1600/premier+test.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRZdJ1wREVlqiTjABrSmyZrWJCOiVf7FcWrEKHZDC_XPHRt-JovMjC7uLS43L0SurvsvFE0SS-oUBD4un8hDDDEi-zXDKQ1NDdVx6MvHAqyk2mMtEoreZ6lUxAOvc87UZeM7fEeYKgnCY/s1600/premier+test.png&quot; height=&quot;344&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
En passant comme je
suis installé côté fenêtre et que je voyage de jour,&amp;nbsp; la réverbération me pousse à adopter le thème
de couleur &#39;Light&#39; car je n&#39;arrive plus à voir ce que j&#39;écris...&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
Je lance les tests
avec la combinaison &lt;code&gt;Ctrl+R, A&lt;/code&gt; et alors que je m&#39;attendais à avoir une indication claire d&#39;échec, rien ne semble s&#39;être produit. &lt;span style=&quot;font-size: 11pt;&quot;&gt;Incrédule, je m&#39;y prends à plusieurs reprises pour me
rendre à l&#39;évidence, &lt;a href=&quot;http://qqcitations.com/citation/156716&quot; target=&quot;_blank&quot;&gt;Einstein avait bien raison&lt;/a&gt;… Il me faut prendre du recul. Mes tests ne sont pas reconnus
par l&#39;explorateur de test de Visual Studio. En fouillant dans ma mémoire, je
retrouve non sans mal l&#39;information que j&#39;oubliais: il me faut installer
NunitTestAdapter.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7R8mEaU7IEm-d6wa4LhiahfPLhS6eRLoGy_gjfZijst9xkSi39GQqxjBGtk6s-TLsJbAgYT4BQkrGASqUvJVlkSqWpHzDJeTIu9R6mI7JaxqzGawfJXhcwRtUhBu2vZzE3fu0Y-wFh3A/s1600/install+nunit+test+adapter.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7R8mEaU7IEm-d6wa4LhiahfPLhS6eRLoGy_gjfZijst9xkSi39GQqxjBGtk6s-TLsJbAgYT4BQkrGASqUvJVlkSqWpHzDJeTIu9R6mI7JaxqzGawfJXhcwRtUhBu2vZzE3fu0Y-wFh3A/s1600/install+nunit+test+adapter.png&quot; height=&quot;150&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
J&#39;ai changé quelque
chose! Voyons voir si j&#39;obtiens d&#39;autres résultats! &lt;code&gt;Ctrl+R, A&lt;/code&gt;…&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;span style=&quot;font-style: italic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF7Qg1rLtAf2ezADWbtZI4mfx9ZKsxYyqzqlRhoFnUet3BIa4Sv5idyvsgK331YtXbmh7RP-u2RTh-f3vaOXuujKqvpPdZRndwa_jqOLVTfHtHwzmgqj4sbwiD5R54ezBGh6YsdU03hgg/s1600/no+failing+test.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF7Qg1rLtAf2ezADWbtZI4mfx9ZKsxYyqzqlRhoFnUet3BIa4Sv5idyvsgK331YtXbmh7RP-u2RTh-f3vaOXuujKqvpPdZRndwa_jqOLVTfHtHwzmgqj4sbwiD5R54ezBGh6YsdU03hgg/s1600/no+failing+test.png&quot; height=&quot;344&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
On avance, car la console m&#39;indique bien que Visual Studio a trouvé et exécuté 1 test. Pourtant, je n&#39;ai
aucune indication d&#39;échec. Est-ce mon test qui est mal écrit ? J&#39;affiche
l&#39;explorateur de test et... voilà!&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXhazTgiL3-num4-_xYsZGFyzRfAEhjGIdQ_Oa6LKi8kjxCUgIRVwlcwf3OxhHvCBd3sxvu_uKJWnbCgB0FVYSPgO1JooG6JC9iHDCe9QQgnZCa-MqG5-B6h-W_VZV1QIECNVVu0eysME/s1600/results+from+visual+studio+test+explorer.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXhazTgiL3-num4-_xYsZGFyzRfAEhjGIdQ_Oa6LKi8kjxCUgIRVwlcwf3OxhHvCBd3sxvu_uKJWnbCgB0FVYSPgO1JooG6JC9iHDCe9QQgnZCa-MqG5-B6h-W_VZV1QIECNVVu0eysME/s1600/results+from+visual+studio+test+explorer.png&quot; height=&quot;344&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
Je vois que le test
a bien échoué. Toutefois, j&#39;ai du explicitement afficher l&#39;explorateur de tests. Ce n&#39;est pas malin ça. Le feedback est très important pour le
cycle TDD et ce comportement de Visual Studio risque de me causer pas mal de
confusions. Aussi j&#39;abandonne l&#39;explorateur de tests et adopte de préférence
l&#39;exécuteur de tests de &lt;i&gt;Resharper.&lt;/i&gt; Avec la tout aussi pratique combinaison&amp;nbsp;&lt;code&gt;Ctrl+U, L&lt;/code&gt; j&#39;obtiens un feedback immédiat sans être obligé de chercher la bonne
fenêtre.&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH6jJA-lEDHJraMNoAjHB4j5aV_21YHOcFJy9KL6qjcFvbwNOkhdpqhm5SnnISSBRoEC9t49gcVRkmw5pL_UGqg0zg8q4PRlfkUXSBBeyjuwJJL4HF1_ykyGlb5gsRhVONc9xv-6sd8vQ/s1600/resharper+to+the+rescue.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH6jJA-lEDHJraMNoAjHB4j5aV_21YHOcFJy9KL6qjcFvbwNOkhdpqhm5SnnISSBRoEC9t49gcVRkmw5pL_UGqg0zg8q4PRlfkUXSBBeyjuwJJL4HF1_ykyGlb5gsRhVONc9xv-6sd8vQ/s1600/resharper+to+the+rescue.png&quot; height=&quot;344&quot; title=&quot;&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
Pour faire passer ce
test au vert, rien de plus simple. Cette fois-ci, exceptionnellement, je
corrige le test en remplaçant l&#39;assertion d&#39;échec par une assertion triviale du
genre &lt;code&gt;Assert.IsTrue(true);&lt;/code&gt; et le tour
est joué!&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmt4nxXKWXEi01Qra7HxQEFBAP5lgjHo90sJXWnCVDldeLN0d4-fMXuuG5eKdh1iPSfjKp2am2e1bSJwF2KcIkZMm89L0ltV51J0huWfW9PgBcejl7mMo-q1i_yRcTEVyifWUpXwNz1TY/s1600/green.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmt4nxXKWXEi01Qra7HxQEFBAP5lgjHo90sJXWnCVDldeLN0d4-fMXuuG5eKdh1iPSfjKp2am2e1bSJwF2KcIkZMm89L0ltV51J0huWfW9PgBcejl7mMo-q1i_yRcTEVyifWUpXwNz1TY/s1600/green.png&quot; height=&quot;344&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;
&lt;div style=&quot;font-size: 11pt; margin: 0in;&quot;&gt;
Ce premier test peut
sembler futile car, en soi, il ne teste absolument rien. Et pourtant, l&#39;étape
franchie est capitale. Le TDD s&#39;appuie sur des boucles de rétroactions très courtes: RED-GREEN-REFACTOR, RED-GREEN-REFACTOR,… Cette étape m&#39;a permis de m&#39;assurer que
les outils mis en place supportent ce cycle, me donnent le bon feedback de façon non équivoque et
que je peux m&#39;y fier. Je n&#39;ose pas m&#39;imaginer le temps fou que j&#39;aurais pu
perdre si mon but avait été d&#39;isoler une anomalie d&#39;un code existant et que
j&#39;interprétais naïvement le mutisme apparent de l&#39;explorateur de tests de
Visual Studio comme un signe que les tests que je concevais étaient positifs !&lt;/div&gt;
&lt;div style=&quot;font-size: 11pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-size: 11pt; margin: 0in;&quot;&gt;
Une anecdote: j&#39;ai,
à quelques reprises, entendu mes collègues se plaindre de la qualité de leurs
projets et lorsqu&#39;on investigue la base de code on n&#39;y retrouve que des tests
du style &lt;code&gt;BasicTests&lt;/code&gt;. Ouch!&lt;/div&gt;
&lt;div style=&quot;font-size: 11pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-size: 11pt; margin: 0in;&quot;&gt;
Par ailleurs, en me
relisant je me
rends compte que, malgré mes bonnes intentions exprimées en début de ce billet,
j&#39;ai également commencé par un test unitaire. Marrant, non ? A ma décharge tout de même, ce n&#39;est pas
dans un but pédagogique et je n&#39;ai pas non plus tester aucun code de production.&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;font-size: 11pt; margin: 0in;&quot;&gt;
Ne manquez pas dans
le prochain billet : Le second &quot;premier test&quot;.&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/1828720729471201263/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/1828720729471201263' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/1828720729471201263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/1828720729471201263'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2015/04/developpement-aspnet-pilote-par-les_26.html' title='Développement ASP.NET piloté par les tests (partie 2)'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnWpFi_7hsg1Gx40lgkOFhAmM3RRxvypkrgHe5vJYRLQD2SSpZUH85uoTEctZXPpglMJOW2ghOVxSJHfJFkgJqpHXgDL-KEzVUT1YUTXBliD-2wkwVlc2WiHSQRb0J9ofP48iSHPQYgY0/s72-c/project+creation.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-2510513333307501111</id><published>2015-04-12T10:05:00.000+02:00</published><updated>2015-04-26T17:04:28.618+02:00</updated><title type='text'>Développement asp.net piloté par les tests (partie 1)</title><content type='html'>&lt;div style=&quot;margin: 0in;&quot;&gt;
&lt;div style=&quot;font-family: Calibri;&quot;&gt;
Ce billet fait partie de la série développement ASP.NET piloté par les tests.&lt;/div&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Calibri;&quot;&gt;Partir de la page blanche&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Calibri;&quot;&gt;&lt;a href=&quot;http://ernststhoughts.blogspot.fr/2015/04/developpement-aspnet-pilote-par-les_26.html&quot; target=&quot;_blank&quot;&gt;Le premier test&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Calibri;&quot;&gt;Le second &quot;premier test&quot; (à venir)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h2 style=&quot;color: #2e75b5; font-family: Calibri; font-size: 14pt;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Partir
de la page blanche…&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Le développement
piloté par les test (TDD) préconise des cycles de développement très courts
débutant par l&#39;écriture d&#39;un test automatisé avant le code de production.
Toutefois les environnements de développement modernes avec toute
l&#39;intelligence de leurs menus, leurs options et leurs fonctionnalités de génération
de code (scaffolding) ne sont pas toujours adaptés à ce mode de développement.
Je ne peux pas nier l&#39;avantage d&#39;avoir un solide point de départ, surtout pour&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;expérimenter&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: 14.6666669845581px;&quot;&gt;rapidement&lt;/span&gt;&lt;span style=&quot;font-size: 14.6666669845581px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: 11pt;&quot;&gt;avec une idée ou se familiariser avec des librairies ou cadres
applicatifs. Cependant, mon but est différent. Je veux développer de manière
maîtrisée une application métier de qualité. J&#39;ai également pour second
objectif de me familiariser avec les changements apportés avec la version 5.2
de Asp.NET MVC. Le développement piloté par les tests me semble approprié pour
cela. Je me propose donc de développer une application web MVC avec Visual Studio 2013 en me laissant entièrement guider par les tests afin voir si l&#39;environnement de développement proposé par Microsoft s&#39;y prête bien ou pas.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;color: #2e75b5; font-family: Calibri; font-size: 14.0pt; margin: 0in;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Avant de commencer
le développement en tant que tel, je me suis posé la question si cela vaut la
peine de tester une application aussi simple que celle que j&#39;ai en tête. J&#39;ai
toujours été un grand fan de la plateforme .NET qui offre une panoplie de technologies,
d&#39;outils et de librairies à la fois diversifiés et bien intégrés. Cela
contribue grandement à la productivité du développeur qui a moins à se soucier
de mettre en place un environnement fonctionnel et peut se concentrer sur
l&#39;application à développer. Visual Studio est un de ces outils de développement
qui offrent une multitude de fonctionnalités pour &quot;aider&quot; le
développeur. Je peux, en&lt;a href=&quot;http://www.asp.net/mvc/overview/older-versions-1/movie-database/create-a-movie-database-application-in-15-minutes-with-asp-net-mvc-cs&quot; target=&quot;_blank&quot;&gt; 7clics ou moin&lt;/a&gt;s, générer la base d&#39;une application web avec authentification et
gestion d&#39;utilisateurs, prise en charge des librairies Javascript (JQuery,
Boostrap, Modernizr, RespondJS) et du CSS,&amp;nbsp;
gestion transverse des erreurs inattendues avec un Filtre, et j&#39;en
passe… Et bien sûr, tout cela fonctionne! Un clic sur le bouton de lancement,
et je peux naviguer sur mon application web flambant neuve.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnzUTQCLfQIs4qazaTVd5heKUL1180G9sNh5Bj35-UxZmspjqOAyVenKer7k0M92-xVfCpEt204QXyFktGKbHXIxWf5VPiSK0rEnklh6-TvikS_6FRUijvnE_SLJWa2KIv0zRGUeggxY0/s1600/new+mvc+app.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnzUTQCLfQIs4qazaTVd5heKUL1180G9sNh5Bj35-UxZmspjqOAyVenKer7k0M92-xVfCpEt204QXyFktGKbHXIxWf5VPiSK0rEnklh6-TvikS_6FRUijvnE_SLJWa2KIv0zRGUeggxY0/s1600/new+mvc+app.png&quot; height=&quot;298&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Toutefois, un doute
m&#39;envahit lorsque je survole le code généré : 33 types pour un total de 384
lignes répartis dans 13 fichiers C#. Ces chiffres ne prennent pas en compte les
vues Razor (25 fichier .cshtml) et le Javascript des librairies utilisées (15 fichiers).
Ai-je besoin de tout cela ? Qu&#39;est-ce qui est vraiment nécessaire pour faire
rouler l&#39;application ? Difficile à dire du premier coup d&#39;œil.&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUdnY0As7v_N6FDk3DRn4I2UxPmn9espFfIeT2wAPgZqAgyqiD99Lu3aYjc3PApD4NXg6ulvTj0xGE7WeOXHq9eK9M4sJK_uUINwYbgY9vODa41oSfxxrYDF9-pOe7zdQG2KiK2VPUbRE/s1600/metrics+for+mvc+app.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUdnY0As7v_N6FDk3DRn4I2UxPmn9espFfIeT2wAPgZqAgyqiD99Lu3aYjc3PApD4NXg6ulvTj0xGE7WeOXHq9eK9M4sJK_uUINwYbgY9vODa41oSfxxrYDF9-pOe7zdQG2KiK2VPUbRE/s1600/metrics+for+mvc+app.png&quot; height=&quot;98&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Les métriques en
soit ne sont pas catastrophiques. Toutefois le faible taux de couverture de 2%
obtenu par les tests générés automatiquement avec la solution ne fait rien pour
me rassurer de la qualité du code. De plus, ceci implique qu&#39;en lisant les tests
je ne peux espérer comprendre que 2% du code du généré. Il me faut soit faire confiance à Microsoft ou parcourir les tutoriels et blogs sur le web pour m&#39;assurer de comprendre dans ces moindres détails ce qui a été généré. Je ne me sens pas en maîtrise…&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw0xd4xQXCKFMixJsuE2NZWQqK_An4obZJR4T8PN1VRO_ppS0P9xX3SIj3gBXQ3tzQrAuyq1f6tZN9GX_sXuPTefPplV5a_U1_a8Jso-iJz7l5WOmqn11MUP6DohP0luQNuQHrBReub6o/s1600/code+coverage+for+mvc+app.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw0xd4xQXCKFMixJsuE2NZWQqK_An4obZJR4T8PN1VRO_ppS0P9xX3SIj3gBXQ3tzQrAuyq1f6tZN9GX_sXuPTefPplV5a_U1_a8Jso-iJz7l5WOmqn11MUP6DohP0luQNuQHrBReub6o/s1600/code+coverage+for+mvc+app.png&quot; height=&quot;191&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Je décide donc de
partir d&#39;une solution vide à laquelle je rajouterai au fil de l&#39;eau les
éléments nécessaires à l&#39;application tout en les validant avec des tests. Avant
de me lancer dans le développement de ma nouvelle application, je vérifie que
j&#39;obtiendrai de meilleurs résultats avec cette approche en effectuant une expérimentation pour (ré-)apprendre (&lt;a href=&quot;http://agiledictionary.com/209/spike/&quot;&gt;Spike&lt;/a&gt;) les bases du cadre applicatif. Je crée une nouvelle solution web vide.&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfBYl8y7mNuDPIEe3Zt6w_6yb8k4WimKmhxagcHuZMqXrHKgwROudNPOSzLhh-KwVfhWcHwSJffftNAUtZEEl1lK6vckYLFoyYnkH_ZHQWhobv6ylkOTUPkg8S_ejgA9KSr9MBMy57_mk/s1600/new+empty+mvc+app.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfBYl8y7mNuDPIEe3Zt6w_6yb8k4WimKmhxagcHuZMqXrHKgwROudNPOSzLhh-KwVfhWcHwSJffftNAUtZEEl1lK6vckYLFoyYnkH_ZHQWhobv6ylkOTUPkg8S_ejgA9KSr9MBMy57_mk/s1600/new+empty+mvc+app.png&quot; height=&quot;297&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;background-color: #e2e2e2; font-family: Calibri; font-size: 11.0pt; margin: 0.2em; padding: 0.5em;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;J&#39;aurais pu opter pour introduire peu à peu des tests dans la solution. Cette option aurait l&#39;avantage de correspondre au contexte de la plupart des projets qui concernent des applications existantes. Ceci me permettrait également de mettre en pratique les techniques pour tester du code existant  que l&#39;on retrouve dans &lt;a href=&quot;http://www.amazon.fr/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052&quot; target=&quot;_blank&quot;&gt;Working with Legacy code&lt;/a&gt;, ou &lt;a href=&quot;http://www.amazon.fr/Brownfield-Application-Development-NET-Baley/dp/1933988711/ref=sr_1_1?s=english-books&amp;amp;ie=UTF8&amp;amp;qid=1428369693&amp;amp;sr=1-1&amp;amp;keywords=brownfield+application+development&quot; target=&quot;_blank&quot;&gt;Brownfield Application Development in .NET&lt;/a&gt;&lt;/span&gt;. Je réserve tout ceci pour une autre série.&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
La solution générée
est plus modeste. Seulement 2 classes totalisant 6 lignes de codes. Pas de vue
Razor, ni de javascript.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOUOB2OsMR9KizYYcKd2adFKIWzeOob-ffC7UR5KTY9QgcT_QxcATAlbaNOzAkPsvJ4jd3n53XVW-5wydWzkg9xbdqxuGknWRCQ1F__FAOLqkvWt-t-nWZ-96y9jA4TidxIoroOpBGteQ/s1600/metrics+for+empty+mvc+app.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOUOB2OsMR9KizYYcKd2adFKIWzeOob-ffC7UR5KTY9QgcT_QxcATAlbaNOzAkPsvJ4jd3n53XVW-5wydWzkg9xbdqxuGknWRCQ1F__FAOLqkvWt-t-nWZ-96y9jA4TidxIoroOpBGteQ/s1600/metrics+for+empty+mvc+app.png&quot; height=&quot;100&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
Cette fois-ci le
taux de couverture des tests est de 0%. Par contre, il n&#39;y a que 8 instructions
de code à tester. C&#39;est beaucoup plus encourageant…&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZHmEMec42KLw-0jXWELjtACyUBG1YUhak2EfmuqrpwaPyI02pem58GR0Kil9PuCEkgUefZ7cdrgjBuJ3zdh8Oj38E2PsvgZKKJjUVBh26LyJAmDUcGzQgDGlRbtniWI287tcvqi7E_RA/s1600/coverage+for+empty+mvc+app.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZHmEMec42KLw-0jXWELjtACyUBG1YUhak2EfmuqrpwaPyI02pem58GR0Kil9PuCEkgUefZ7cdrgjBuJ3zdh8Oj38E2PsvgZKKJjUVBh26LyJAmDUcGzQgDGlRbtniWI287tcvqi7E_RA/s1600/coverage+for+empty+mvc+app.png&quot; height=&quot;181&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
De plus,
l&#39;application ne fonctionne pas. Lorsque je la lance, j&#39;obtiens une page
d&#39;erreur m&#39;indiquant que la page d&#39;accueil n&#39;existe pas. Ça me semble être un
bon point de départ pour mon premier test…&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
La suite dans le prochain
billet…&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11.0pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/2510513333307501111/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/2510513333307501111' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/2510513333307501111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/2510513333307501111'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2015/04/developpement-aspnet-pilote-par-les.html' title='Développement asp.net piloté par les tests (partie 1)'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnzUTQCLfQIs4qazaTVd5heKUL1180G9sNh5Bj35-UxZmspjqOAyVenKer7k0M92-xVfCpEt204QXyFktGKbHXIxWf5VPiSK0rEnklh6-TvikS_6FRUijvnE_SLJWa2KIv0zRGUeggxY0/s72-c/new+mvc+app.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-3534967730188629655</id><published>2014-01-13T15:28:00.002+01:00</published><updated>2014-01-13T15:28:24.262+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="atelier"/><category scheme="http://www.blogger.com/atom/ns#" term="Communauté de pratique"/><category scheme="http://www.blogger.com/atom/ns#" term="principes agiles"/><title type='text'>Démarrer une communauté de pratique agile tout en jouant</title><content type='html'>J&#39;ai récemment eu la chance de participer au démarrage d&#39;une communauté de pratique agile pour l&#39;un de mes clients. J&#39;ai tout particulièrement apprécié l&#39;occasion qui m&#39;a été offerte d&#39;animer deux moments cruciaux de cette rencontre. Je me propose de partager dans ce billet un retour sur les jeux que nous avons utilisés pour faciliter les échanges et l&#39;engagement : &quot;&lt;a href=&quot;http://tastycupcakes.org/2010/01/pocket-sized-principles/&quot;&gt;Pocket-Sized Agile Principles&lt;/a&gt;&quot; et &quot;&lt;a href=&quot;http://innovationgames.com/circles-of-influence-2/&quot;&gt;Circle of Influences&lt;/a&gt;&quot;.&lt;br /&gt;
&lt;br /&gt;
Vue l&#39;émergence de plusieurs initiatives agiles au sein de son entreprise, mon client veut mettre en place une communauté qui permettra aux membres de partager les pratiques qui fonctionnent bien et ainsi augmenter globalement les compétences agiles au sein de l&#39;entreprise. L&#39;objectif du lancement de la communauté est d&#39;informer de la mise en place de ce moyen de communication et d&#39;impliquer ceux qui sont intéressés à son rayonnement.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Les enjeux&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Persuader les dirigeants du bien fondé et du retour sur investissement d&#39;entretenir une communauté de pratiques ;&lt;/li&gt;
&lt;li&gt;Impliquer de façon minimale et efficace les collaborateurs dans l&#39;organisation et la vie de la communauté ;&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Les défis&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Différents degrés de familiarité avec l&#39;agilité des participants ;&lt;/li&gt;
&lt;li&gt;Réticences envers l&#39;agilité de certains participants clés ;&lt;/li&gt;
&lt;li&gt;Démarrer les conversations dans une ambiance sereine ;&lt;/li&gt;
&lt;/ul&gt;
La question du format de la réunion de lancement s&#39;est vite posée. Un format forum ouvert (&quot;open space&quot;) ne nous a pas semblé approprié vu les objectifs spécifiques de lancement de communauté. Nous avons donc opté pour des sessions de travail en sous-groupes avec mise en commun par la suite. Ce format, bien que plus directif, a permis à tous les participants de s&#39;exprimer et de partager sur les sujets importants auxquels&amp;nbsp; la communauté devraient s&#39;atteler.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pocket-Sized Agile Principles&lt;/b&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFQb_uBxajN2ImwDBe6JASIBfOTvDtMryjmqH93MTw40IjxLYGPXDw0mgyZN9Cd7jjaT7vlelG8ekWThgCXACQL8D4nqD6qsI7NwJZH3peyBBA66MitDMd1V5opQV86kClcTQQJVsvPSo/s1600/WP_20131205_002.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFQb_uBxajN2ImwDBe6JASIBfOTvDtMryjmqH93MTw40IjxLYGPXDw0mgyZN9Cd7jjaT7vlelG8ekWThgCXACQL8D4nqD6qsI7NwJZH3peyBBA66MitDMd1V5opQV86kClcTQQJVsvPSo/s1600/WP_20131205_002.jpg&quot; height=&quot;179&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://tastycupcakes.org/about/don-mcgreal/&quot; target=&quot;_blank&quot;&gt;Don McGreal&lt;/a&gt; présente cet &lt;a href=&quot;http://tastycupcakes.org/2010/01/pocket-sized-principles/&quot; target=&quot;_blank&quot;&gt;atelier&lt;/a&gt;, comme un jeu permettant de communiquer les principes du manifeste agile. Les participants ont travaillé en sous-groupes de 5 à 8 personnes afin de résumer sur un post-it avec un maximum de trois mots chacun des &lt;a href=&quot;http://agilemanifesto.org/iso/fr/principles.html&quot; target=&quot;_blank&quot;&gt;12 principes&lt;/a&gt;. Pour faciliter la mise en commun, on retrouve sur chaque post-it un numéro référençant un principe et les trois mots qui le résument. Voulant favoriser les échanges, nous avons opté pour une boîte de temps d&#39;une heure pour cette étape.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3bntpfumMqErxBpHXWpStPxAsr8Y9D8EcjonFBuuiK-YIOrAqMfQbFWquDEz0iBaala7DY9GMzC48OB6ojHsbtcs25gaIY1_bo_HTX1soiuceFi4_D-IGHLAnH35TI_cuCxsrHU-U4xk/s1600/WP_20131205_001.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3bntpfumMqErxBpHXWpStPxAsr8Y9D8EcjonFBuuiK-YIOrAqMfQbFWquDEz0iBaala7DY9GMzC48OB6ojHsbtcs25gaIY1_bo_HTX1soiuceFi4_D-IGHLAnH35TI_cuCxsrHU-U4xk/s1600/WP_20131205_001.jpg&quot; height=&quot;320&quot; width=&quot;179&quot; /&gt;&lt;/a&gt;Cet atelier, malgré sa simplicité, fut très efficace pour focaliser les conversations et introduire les concepts de l&#39;agilité aux personnes qui y étaient moins familières. Le maximum de trois mots incite les sous-groupes à creuser les principes afin d&#39;en tirer l&#39;essence et de l&#39;exprimer dans des termes significatifs pour tous. En prime, certains principes ont donné lieu à des témoignages d&#39;expériences personnelles ce qui a augmenté la compréhension des enjeux de l&#39;agilité au sein de la compagnie.&lt;br /&gt;&lt;br /&gt;En bonus, nous avons demandé aux participants de voter avec la technique du &quot;dot voting&quot; les principes les plus importants. Nous avons ainsi obtenus d&#39;eux une vision partagée des éléments importants de l&#39;agilité qui pourra servir de base au processus d&#39;amélioration continue de la compagnie. Dans notre cas, les principes qui sont ressortis sont : 10 - Simplicité, 9 - Excellence technique, 1 - Priorisation de la valeur, 5 - Confiance en des personnes motivées, 3 - Livraisons fréquentes.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;b&gt;Circles of Influence&lt;/b&gt;&lt;br /&gt;Plus tard durant le lancement, après avoir dressé et ordonné une liste de sujets que la communauté devrait aborder, il nous fallait déterminer les contributions que chaque membre pouvait faire en vue d&#39;organiser les futures activités. Cette étape de la rencontre a tout naturellement créé une atmosphère d&#39;incertitude dans le groupe constitué d&#39;individus n&#39;ayant pas souvent collaborer ensembles. Il nous fallait rapidement trouver un objectif rassembleur et laisser émerger l&#39;auto-organisation du groupe. Nous avons, sur le tas, opté pour le jeu &quot;&lt;a href=&quot;http://innovationgames.com/circles-of-influence-2/&quot; target=&quot;_blank&quot;&gt;Circles of Influence&quot;&lt;/a&gt; de la série &quot;&lt;a href=&quot;http://innovationgames.com/&quot; target=&quot;_blank&quot;&gt;Innovation Games&lt;/a&gt;&quot;. Cette activité permet à un groupe de déterminer de manière collaborative les actions à accomplir et les moyens dont il dispose en vue d&#39;atteindre l&#39;objectif qu&#39;il s&#39;est fixé.&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLaovuBtl_7k2gcWDiHpuZpbdPrl-lURHLtcLP-DJLwIXezs5-6Cq8HCAUrLFKZZeZovInGehHl3e3HdHzxXyRLOsIiMpp3AW6sDDbThQO9hwANeeD-sGoPIMJ0dZPvrASNnJsMvQVY5A/s1600-h/WP_20131205_004%25255B2%25255D%25255B3%25255D.jpg&quot;&gt;&lt;img align=&quot;right&quot; alt=&quot;WP_20131205_004[2]&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAottEZFfz67DlT1aUdAX3UdUFQ4FzJhyphenhyphenXFgAQut3rXOvsJdqcrKMzcGuWysuRnZ2T7UCTYkGaA1qpyo8VA7nCkUNk4QrNjnHq9aaif2KwdU6O90NkJ6E9Tb8Rb9T-Vz-qg46Vmz86no0/?imgmax=800&quot; height=&quot;183&quot; style=&quot;background-image: none; border: 0px; display: inline; float: right; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;WP_20131205_004[2]&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;br /&gt;Après avoir réfléchi quelques instants, le groupe a défini son objectif: &quot;Faire vivre la communauté&quot;. Cette étape a été cruciale puisqu&#39;elle a permis aux participants de trouver un sens aux contributions et engagements qu&#39;ils s&#39;apprêtaient à faire. Tel que présentées sur l&#39;image, les actions sont indiquées sur des post-it collés à l&#39;intérieur du cercle &quot;Tâches&quot; (à gauche). Dans notre cas, ces actions étaient des contributions soit techniques comme par exemsur un post-itple la mise en place d&#39;une plateforme collaborative pour la communauté, ou des contributions de contenu sous forme de présentations ou animation d&#39;ateliers. Chaque contributeur a aussi pris le temps d&#39;indiquer son nom et le temps qu&#39;il peut consacrer à sa contribution. Par ailleurs, les moyens ont été identifiés sur des post-it accolés au cercle &quot;Comité/Support&quot; (à droite). On peut voir sur l&#39;image que les participants se sont peu concentrés sur le support dont ils avaient besoin et qu&#39;ils sont plutôt dans l&#39;action.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;En conclusion&lt;/b&gt;&lt;br /&gt;Voilà deux jeux simples et efficaces qui nous ont permis d&#39;établir un climat de collaboration peu probable au sein d&#39;un groupe d&#39;individus ayant un bagage et une expérience agile très diverses. Ce climat serein a permis aux participants de définir un objectif commun et d&#39;offrir leurs contributions à la communauté. Ce fut la première fois que j&#39;utilisais ces jeux dans un contexte hors formation ou coaching d&#39;équipe et, vu les résultats obtenus, ce ne sera sûrement pas la dernière. Et vous, comment organisez-vous le lancement d&#39;une communauté ?</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/3534967730188629655/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/3534967730188629655' title='2 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/3534967730188629655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/3534967730188629655'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2014/01/demarrer-une-communaute-de-pratique.html' title='Démarrer une communauté de pratique agile tout en jouant'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFQb_uBxajN2ImwDBe6JASIBfOTvDtMryjmqH93MTw40IjxLYGPXDw0mgyZN9Cd7jjaT7vlelG8ekWThgCXACQL8D4nqD6qsI7NwJZH3peyBBA66MitDMd1V5opQV86kClcTQQJVsvPSo/s72-c/WP_20131205_002.jpg" height="72" width="72"/><thr:total>2</thr:total><georss:featurename>France</georss:featurename><georss:point>46.227638 2.2137490000000071</georss:point><georss:box>34.9722085 -18.440547999999993 57.4830675 22.868046000000007</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-7599323651729238739</id><published>2010-06-03T22:36:00.001+02:00</published><updated>2010-06-03T23:15:12.699+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CQRS"/><category scheme="http://www.blogger.com/atom/ns#" term="DDD"/><category scheme="http://www.blogger.com/atom/ns#" term="training"/><title type='text'>3 days with Greg Young</title><content type='html'>&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnD1svN8psWsgdyxWqDZ9GiIsIqiR-zKf5QQrTbIuJ4vo6XIgqtCnxMMPMXoUw9EOc1NTKOIVHQWjzThdecmtaybabLGZaUdQDTeA6_HIRradoeqMb1JyeWlCpjWYUY-nnS6JTDY3SAC8/s1600-h/IMG_2720%5B5%5D.jpg&quot;&gt;&lt;img align=&quot;left&quot; alt=&quot;IMG_2720&quot; border=&quot;0&quot; height=&quot;184&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtVmHkL60FPND1Zt3Ezapj_b5X1znUvV0NEOnt_X_5d3nl0zFDuYGVVuWd1hZlZxESoX7b-W_D5QgrwUtGyHHZHtqV0sAlf0XhD0zvfuL1UZ0akFyZ3WQTO0F-vc1g4yZ0MtJzMfZrPBY/?imgmax=800&quot; style=&quot;border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; margin-left: 0px; margin-right: 0px;&quot; title=&quot;IMG_2720&quot; width=&quot;244&quot; /&gt;&lt;/a&gt; Last week &lt;a href=&quot;http://www.pyxis-tech.com/&quot;&gt;Pyxis&lt;/a&gt; hosted an intensive three days immersion into &lt;a href=&quot;http://codebetter.com/blogs/gregyoung/&quot;&gt;Greg Young&#39;s&lt;/a&gt; Applied DDD course. This course is amazingly packed with tips and tricks on how to come up with an architecture that delivers business value customers have come to expect from their investments in software systems. Powered by Greg’s energetic tone, this course challenged my assumptions of how software should be designed and I would recommend it to anyone interested in architecture innovations surrounding &lt;a href=&quot;http://domainlanguage.com/ddd/index.html&quot;&gt;Domain Driven Design&lt;/a&gt;. Following is an overview of the topics we’ve tackled during the training. &lt;br /&gt;
&lt;h4&gt;DDD recap&lt;/h4&gt;The first day was spent refreshing some of the fundamental but often misunderstood concepts of Domain Driven Design. We were reminded that Strategic Design is essential while embarking on a Domain Driven Design project as we must make sure that the value we get out from it is well worth the effort. Notions such as Bounded Contexts and Core Domain allow highly knowledgeable teams to focus on value added development work while leaving less crucial aspects of the software to others.&lt;br /&gt;
Another topic that stroke a chord with me was Greg’s presentation of Aggregates and the role the play in well crafted software systems. Aggregates exist to provide transaction boundaries around the behaviors of domain objects. Aggregate roots provide the sole entry point to this grouping of domain behaviors and encapsulate validation logic as well as invariant consistency inside the aggregate.&lt;br /&gt;
&lt;h4&gt;CQRS&lt;/h4&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh57Jz6vqDO8-QjadSBO5QKPGY1O-tkQiaWeJQJY5Ju8NlstBFvoqiF1RAClA_xU6kh3yKbCPs6z4HEuIf4DQtP3agi-USOsdPKXQs_4yKmf_aRSPmKUm3Kc7rR5orJANYpABkMuThFDGU/s1600-h/EventSourcing%5B5%5D.jpg&quot;&gt;&lt;img align=&quot;left&quot; alt=&quot;EventSourcing&quot; border=&quot;0&quot; height=&quot;196&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnBbKf0lK3WAZrOhimAbOjghPFo7RS_Bd4ucs-qWrYnFnlLArYpnxKw1bNZP8ffSOCEnakcHhT8ZFIDcpbLJ_ImVrOYN5_vifKOut5_CwT5F5w6z1vVSNebpuo2hyyfh0cL1vb0wbe0IU/?imgmax=800&quot; style=&quot;border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; margin-left: 0px; margin-right: 0px;&quot; title=&quot;EventSourcing&quot; width=&quot;272&quot; /&gt;&lt;/a&gt;We spent the second day learning about Command Query Responsibility Segregation and Event Sourcing. CQRS is different then Command Query Separation (Bertrand Meyer) which advocates that methods that change state should be separated from functions that return value. CQRS takes the same principle and applies it to the hole architecture. In this style of design some objects (write model) represents the commands the domain respond to and other objects (read model) handles the queries and their results. Having separate models for these concerns brings a lot of benefits that I will bring up in later posts. &lt;br /&gt;
&lt;h5&gt;The write model&lt;/h5&gt;It’s common OO knowledge that objects should be designed around behaviors in a domain. Having a dedicated write model consisting of aggregates that define transaction boundaries around the behaviors in the domain focuses work on the most valuable part of the system. This is the place to maximize the return on the work of your most skilled developers aided by domain experts.&lt;br /&gt;
&lt;h5&gt;The read model &lt;/h5&gt;The query side doesn’t have a domain as it’s mostly straightforward boilerplate code. The preferred implementation of a read model is having request DTOs going through a thin query layer that projects directly off of a data source. This is way simpler that using the domain model to do the same. This way pre-fetched paths and optimizing ORMs queries are avoided.&lt;br /&gt;
&lt;h5&gt;Event Sourcing &lt;/h5&gt;Event sourcing can be seen as a way to “standardize” thus reduce the cost of implementing separated read and write models. The basic idea is that all domain can be modeled as receiving commands that and producing associated events. These events can be stored as a log of what happened in the system and also be used to update the read model.&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3KeTTrzORC2PA9cfiIz014quvmKV0kxKCZ87wGvVpH43VsdFGmyRLiL87T28rM8HpWYBoUrA-7CetuaV-msYihp4zDGY3_au9kDY6pobQp8dHDRllE4iwW6Fv00M4QGsy2ikr95p7avc/s1600-h/IMG_2717%5B3%5D.jpg&quot;&gt;&lt;img align=&quot;left&quot; alt=&quot;IMG_2717&quot; border=&quot;0&quot; height=&quot;184&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1Q7tStuO_uUMwwAI7iTnAoUOT9u0n7F17P9cCRxIJMdUFZAS3maL27CyQlKi_swzIQbQoV5V8WMfQ1EQcGVlPqPzOKxC_dvT2IYzzRnYVnV4zxNbD6QqI3dJuvVMw4Qc7RJ2a78BxjDI/?imgmax=800&quot; style=&quot;border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; margin-left: 0px; margin-right: 0px;&quot; title=&quot;IMG_2717&quot; width=&quot;244&quot; /&gt;&lt;/a&gt; While exposing concurrency issues and ways to handle them Greg showed us a merging algorithm that’s quite simple and clever. Probably, the only piece of code Greg would ever write with a Goto statement as you can see in the picture.&lt;br /&gt;
&lt;h4&gt;Fine tuning the architecture&lt;/h4&gt;The third day was spent analyzing the properties of this architecture and how it could be fine tuned to produce low latency, high availability and high reliability systems. Most notably &lt;a href=&quot;http://codebetter.com/blogs/gregyoung/archive/2010/02/20/cqrs-and-cap-theorem.aspx&quot;&gt;CQRS architecture can used to get around&lt;/a&gt; &lt;a href=&quot;http://www.julianbrowne.com/article/viewer/brewers-cap-theorem&quot;&gt;CAP theorem&lt;/a&gt; issues which states that you can’t guarantee all three &lt;strong&gt;C&lt;/strong&gt;onsistency, &lt;strong&gt;A&lt;/strong&gt;vailability and &lt;strong&gt;P&lt;/strong&gt;artitionability in one system. Look &lt;a href=&quot;http://guysblogspot.blogspot.com/2008/09/cap-solution-proving-brewer-wrong.html&quot;&gt;here&lt;/a&gt; for another treatment on how to get around CAP.&lt;br /&gt;
All these architecture talks made me realize that using DDD and CQRS is a lot of work. And it’s no wonder that they should be applied to core domains. Now most companies I’ve worked with deal with multiple domains such as Sales, Security, Insurance, etc... And it would have been difficult to single out the one that constitutes their core domain. But every company must have a core domain otherwise it would not have a competitive advantage. Turns out a lot of companies derive their competitive advantage from their business process that integrate all of the domains they deal with. This is the place their core domain reside and that’s where &lt;a href=&quot;http://www.rgoarchitects.com/Files/SOAPatterns/Saga.pdf&quot;&gt;Sagas&lt;/a&gt; help.&lt;br /&gt;
&lt;h4&gt;Pyxis source of high quality technical learning&lt;/h4&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3IgCtczD4L6Lj9BxRuJVXAEzsM6OMIjr63kmvggLLP0E0_lhA6B2RMbu79a_Yqhmly7Ol8P8Uv6PwQEeRX9eiCHzGzuhM28xR3PNtNhPvFOTGTU14rcFZUcvvXgh_2z3Mdvxu5fOD5k4/s1600-h/IMG_2719%5B6%5D.jpg&quot;&gt;&lt;img align=&quot;right&quot; alt=&quot;IMG_2719&quot; border=&quot;0&quot; height=&quot;184&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHjGceYXQhaUyFktgwZrfIBxGqSvWlGOlM5jI6IxNqT9fBJCgyeVnhhp3Ra-9Z-6WUNMq3IvANUFnolR2g0MxMDGyJ-3DL77ctD7ksTO9QLoYgLH65QJag6rVpJRZKe2EUAzejEycb0Uc/?imgmax=800&quot; style=&quot;border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; margin-left: 0px; margin-right: 0px;&quot; title=&quot;IMG_2719&quot; width=&quot;244&quot; /&gt;&lt;/a&gt; All in all, these three days were packed with useful technical knowledge and eye opening discussions with an expert in his craft. The participants enjoyed the learning experience in Pyxis’ agile environment where they got a close up look at our facilities supporting agile teams. Pyxis is proud to have sponsored this event and is dedicated to bringing high quality technical training to the public.&lt;br /&gt;
Other technical trainings :&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://www.pyxis-tech.com/en/services/formation/liste-de-cours/scrum-developer-dotnet/&quot;&gt;Professional Scrum Developer (.NET)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pyxis-tech.com/en/services/formation/liste-de-cours/modelisation-agile/&quot;&gt;Agile Modeling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pyxis-tech.com/en/services/formation/liste-de-cours/ddd/&quot;&gt;Domain-Driven Design (DDD)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pyxis-tech.com/en/services/formation/liste-de-cours/tdd/&quot;&gt;Test-Driven Development (TDD)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pyxis-tech.com/en/services/formation/liste-de-cours/pratiques-dutilisabilite/&quot;&gt;Usability Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pyxis-tech.com/en/services/formation/liste-de-cours/specifications-executables/&quot;&gt;Executable Specifications with GreenPepper&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/7599323651729238739/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/7599323651729238739' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/7599323651729238739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/7599323651729238739'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2010/06/3-days-with-greg-young.html' title='3 days with Greg Young'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtVmHkL60FPND1Zt3Ezapj_b5X1znUvV0NEOnt_X_5d3nl0zFDuYGVVuWd1hZlZxESoX7b-W_D5QgrwUtGyHHZHtqV0sAlf0XhD0zvfuL1UZ0akFyZ3WQTO0F-vc1g4yZ0MtJzMfZrPBY/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-1396797453980384829</id><published>2010-05-04T06:15:00.001+02:00</published><updated>2010-05-04T06:15:48.518+02:00</updated><title type='text'>My presentation at the Toronto Code Camp 2010</title><content type='html'>&lt;p&gt;I had a blast meeting new people and sharing experiences writing software. I especially liked Barry Gervin’s keynote on successful product management and Todd Anglin’s talk on HTML5. &lt;/p&gt;  &lt;p&gt;As for me, I did and introductory talk on &lt;a href=&quot;http://www.slideshare.net/eperpignand/scrum-in-vs2010&quot;&gt;Scrum and Visual Studio 2010&lt;/a&gt; briefly touching on some of the content of the Professional Scrum Developer course. The training has already started in several countries around the globe: Brazil, Australia and US. I’ll be teaching the &lt;a href=&quot;http://pyxis-tech.com/en/services/formation/liste-de-cours/scrum-developer-dotnet/&quot;&gt;Montreal edition&lt;/a&gt; that’s coming in June 7th. It’s going to be awesome!&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h3&gt;About the Professional Scrum Developer Course&lt;/h3&gt;  &lt;p&gt;The Scrum Developer course is a unique and intensive five-day experience for software developers. The course guides teams on how to turn product requirements into potentially shippable increments of software using the Scrum framework, Visual Studio 2010, and modern software engineering practices. Attendees will work in self-organizing, self-managing teams using a common instance of Visual Studio Team Foundation Server 2010 to achieve this goal. &lt;/p&gt;  &lt;p&gt;Course attendees are prepared to take an assessment at course completion and then become Certified Professional Scrum Developers.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/1396797453980384829/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/1396797453980384829' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/1396797453980384829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/1396797453980384829'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2010/05/my-presentation-at-toronto-code-camp.html' title='My presentation at the Toronto Code Camp 2010'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-1281787189227569957</id><published>2010-03-25T16:51:00.000+01:00</published><updated>2010-03-25T16:51:16.988+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="PSD"/><category scheme="http://www.blogger.com/atom/ns#" term="scrum.org"/><category scheme="http://www.blogger.com/atom/ns#" term="training"/><title type='text'>Professional Scrum Developper Training</title><content type='html'>&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: Arial; font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: 13px;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Times New Roman&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: medium;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: Arial; font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: 13px;&quot;&gt;Dates are now open for the &lt;a href=&quot;http://courses.scrum.org/about/ernst-perpignand&quot;&gt;Professional Scrum Developper on the .Net&lt;/a&gt; platform training in the Montreal and Toronto areas. This training is fully packed with knowledge and hands-on exercices that are important for today&#39;s developers, architects and testers working in agile teams.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: Arial; font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: 13px;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Times New Roman&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: medium;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: Arial; font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: 13px;&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: Arial; font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: 13px;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Times New Roman&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: medium;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: Arial; font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: 13px;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #555555; font-family: &#39;Lucida Sans Unicode&#39;, &#39;Lucida Grande&#39;, Tahoma, sans-serif; font-size: 12px; line-height: 21px;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: Arial; font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Times New Roman&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: Arial; font-size: small;&quot;&gt;&lt;blockquote&gt;Scrum Developer course is a unique and intensive five-day experience for software developers. The course guides teams on how to turn product requirements into potentially shippable increments of software using the Scrum framework, Visual Studio 2010, and modern software engineering practices. Attendees will work in self-organizing, self-managing teams using a common instance of Visual Studio Team Foundation Server 2010 to achieve this goal.&lt;/blockquote&gt;&lt;blockquote&gt;Course attendees are prepared to take an assessment at course completion and then become Certified Professional Scrum Developers.&lt;/blockquote&gt;You can register via &lt;a href=&quot;http://courses.scrum.org/about/ernst-perpignand&quot;&gt;scrum.org&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Hope to see you there!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/1281787189227569957/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/1281787189227569957' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/1281787189227569957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/1281787189227569957'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2010/03/professional-scrum-developper-training.html' title='Professional Scrum Developper Training'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-913154292711998293</id><published>2010-03-21T19:15:00.000+01:00</published><updated>2010-03-21T19:15:27.493+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="agile testing"/><category scheme="http://www.blogger.com/atom/ns#" term="ATDD"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><title type='text'>Agile Testing</title><content type='html'>I&#39;ve just watch this &lt;a href=&quot;http://www.youtube.com/watch?v=bqrOnIECCSg&amp;amp;NR=1&quot;&gt;talk&lt;/a&gt; from &lt;a href=&quot;http://www.qualitytree.com/company/elisabeth/&quot;&gt;Elizabeth Hendrickson&lt;/a&gt;. Very interesting content on &lt;a href=&quot;http://testobsessed.com/wordpress/wp-content/uploads/2008/08/AgileTestingOverview.pdf&quot;&gt;Agile Testing&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/913154292711998293/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/913154292711998293' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/913154292711998293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/913154292711998293'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2010/03/agile-testing.html' title='Agile Testing'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-375716256987826882</id><published>2010-03-21T03:43:00.000+01:00</published><updated>2010-03-21T04:04:34.183+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="PSD"/><category scheme="http://www.blogger.com/atom/ns#" term="PSM"/><category scheme="http://www.blogger.com/atom/ns#" term="scrum.org"/><title type='text'>Professional Scrum Master Level II</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6ch2cMP9_wyEw2LrT0yxcNAT2Bar65P8NVBWni59RIze44PUP8lIOuj93Bhb50Bf3gIO85WrPEkFnjQjF-whIlqGbV_chNlz4MB6X7Qptvg1dH5vpvIk8oLqigemKR_HcWLRcboG9JAk/s1600-h/ScrumDeveloperTrainer_200px.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;66&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6ch2cMP9_wyEw2LrT0yxcNAT2Bar65P8NVBWni59RIze44PUP8lIOuj93Bhb50Bf3gIO85WrPEkFnjQjF-whIlqGbV_chNlz4MB6X7Qptvg1dH5vpvIk8oLqigemKR_HcWLRcboG9JAk/s200/ScrumDeveloperTrainer_200px.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;I&#39;ve just received confirmation from Ken Schwaber that I&#39;ve successfully completed the &lt;a href=&quot;http://www.scrum.org/scrummaster/&quot;&gt;Professional Scrum Master Level II assessment&lt;/a&gt; available on &lt;a href=&quot;http://scrum.org/&quot;&gt;Scrum.org&lt;/a&gt;. I&#39;m very proud of announcing that I&#39;m also a &lt;a href=&quot;http://www.scrum.org/scrumdeveloper/&quot;&gt;.Net &amp;nbsp;Professional Scrum Developper&lt;/a&gt; Trainer and that I will be delivering this &lt;a href=&quot;http://courses.scrum.org/classes/title/professional-scrum-developer-net&quot;&gt;course&lt;/a&gt; in Canada in May and June. Stay tuned for the official dates.</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/375716256987826882/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/375716256987826882' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/375716256987826882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/375716256987826882'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2010/03/professional-scrum-master-level-ii.html' title='Professional Scrum Master Level II'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6ch2cMP9_wyEw2LrT0yxcNAT2Bar65P8NVBWni59RIze44PUP8lIOuj93Bhb50Bf3gIO85WrPEkFnjQjF-whIlqGbV_chNlz4MB6X7Qptvg1dH5vpvIk8oLqigemKR_HcWLRcboG9JAk/s72-c/ScrumDeveloperTrainer_200px.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-7273345514926993818</id><published>2010-03-18T17:48:00.001+01:00</published><updated>2010-03-18T18:07:17.307+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="MSTest"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Unit Test"/><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio"/><title type='text'>Automated Unit Tests as Documentation</title><content type='html'>&lt;h2&gt;&lt;/h2&gt;&lt;h4&gt;Introduction&lt;/h4&gt;In our quest to produce quality software and our relentless use of automated unit tests in our development activities, we’ve come to realize they possess other virtues as well. One of those being they stand as a documentation of the system being developed. I’ve taught this idea in &lt;a href=&quot;http://pyxis-tech.com/en/services/formation/liste-de-cours/ddd/&quot;&gt;several&lt;/a&gt; &lt;a href=&quot;http://pyxis-tech.com/en/services/formation/liste-de-cours/modelisation-agile/&quot;&gt;agile&lt;/a&gt; and &lt;a href=&quot;http://pyxis-tech.com/en/services/formation/liste-de-cours/tdd/&quot;&gt;TDD&lt;/a&gt; courses. In this blog I want to give you an example of how that may be. I’m purposely not discussing &lt;a href=&quot;http://www.agilemodeling.com/essays/executableSpecifications.htm&quot;&gt;executable specifications&lt;/a&gt; and &lt;a href=&quot;http://behaviour-driven.org/Introduction&quot;&gt;Behaviour Driven Development&lt;/a&gt; as it would make this blog too long. My goal is to show how using some convention and Visual Studio 2010 can go a long way in cranking up your unit tests another notch.&lt;br /&gt;
&lt;h4&gt;Documentation of API usage&lt;/h4&gt;One clever use of unit tests is for learning a new API or even a new language. Writing several assertions to validate our understanding and assumptions about an API usage is very rewarding as the feedback is rapid and progress towards a goal is constantly measured. These learning tests may be kept around to document the assumptions made that constitute the basis of our solution. Here is an example of a learning test for the Character.IsWhiteSpace() method of the BCL.&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;[TestMethod]      &lt;br /&gt;
[Description(@&quot;White spaces are the following characters: &#39; &#39;, &#39;\t&#39;, &#39;\n&#39;, &#39;\r&#39;&quot;)]       &lt;br /&gt;
public void May_be_a_white_space()       &lt;br /&gt;
{       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsTrue(char.IsWhiteSpace(&#39; &#39;));       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsTrue(char.IsWhiteSpace(&#39;\n&#39;));       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsTrue(char.IsWhiteSpace(&#39;\t&#39;));       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsTrue(char.IsWhiteSpace(&#39;\r&#39;)); &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsFalse(char.IsWhiteSpace(&#39;A&#39;));      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsFalse(char.IsWhiteSpace(&#39;+&#39;));       &lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
A test can also document how to use the classes we create in our solutions. The following is an example of such a test. In our chess software, this unit test documents the way of obtaining a chess piece which is to call the NewPiece() factory method and passing it a color (either Color.White or Color.Black) and a Kind (such as Kind.Pawn) as arguments.&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;[TestMethod]      &lt;br /&gt;
[Description(&quot;A chess piece consists of a kind and a color that are specified when the piece is created&quot;)]       &lt;br /&gt;
public void Should_retain_its_color()       &lt;br /&gt;
{       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Piece pawn =       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Piece.NewPiece(Color.Black, Kind.Pawn);       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsTrue(pawn.IsBlack);       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsFalse(pawn.IsWhite); &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pawn = Piece.NewPiece(Color.White, Kind.Pawn);      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsTrue(pawn.IsWhite);       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsFalse(pawn.IsBlack);       &lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
&lt;h4&gt;Documentation of behaviours&lt;/h4&gt;Unit tests document behaviours of our code. &lt;span style=&quot;font-family: verd;&quot;&gt;Test classes should&amp;nbsp; be given names that provide context for all the test methods they contain.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;[TestClass]     &lt;br /&gt;
public class When_displaying_a_board      &lt;br /&gt;
{      &lt;br /&gt;
&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [TestMethod]     &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void A_black_queen_should_show_as_Q()      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; …&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;     &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;…&lt;/span&gt;      &lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
Test methods should also be named in such a way that the behaviour they validate is evident.&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;[TestMethod]      &lt;br /&gt;
[Description(&quot;The board is displayed on 8 lines with blacks pieces on line 8 and 7 and white pieces on lines 1 and 2&quot;)]       &lt;br /&gt;
public void It_should_show_all_pieces_in_their_initial_position()       &lt;br /&gt;
{       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.AreEqual(       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;RNBQKBNR&quot;.Line() +       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;PPPPPPPP&quot;.Line() +       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;........&quot;.Line() +       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;........&quot;.Line() +       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;........&quot;.Line() +       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;........&quot;.Line() +       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;pppppppp&quot;.Line() +       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;rnbqkbnr&quot;.Line(),       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; board.ToString()       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; );       &lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
Notice that, instead of writing comments, I’m using the Description attribute to tie the behaviour being tested with some requirement or specification of the system. Personally, I’m not doing anything fancy with these descriptions, but you can imagine using a pattern that would provide more traceability in your environment as in the following.&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;[TestMethod]     &lt;br /&gt;
[Description(&quot;US 234: Black pawns are shown as P, white pawns are shown as p&quot;)]       &lt;br /&gt;
public void A_white_pawn_should_show_as_p()       &lt;br /&gt;
{       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Piece whitePawn = Piece.NewPiece(       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Color.White,       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;Kind.Pawn);      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.AreEqual(&quot;p&quot;, whitePawn.ToString());       &lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
&lt;h4&gt;Documentation of design specifications&lt;/h4&gt;Now comes the fun part! Because of the thought we’ve put in selecting meaningful names when the tests are executed in Visual Studio we get a result screen that looks like this.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5Vlqr5UeDnXuIqjepCKRvZvXEoBFvzaQfZPgYv0eeYeFsWm9BEFpbPaFNmfT16l95cfzpLEqKhUcf5389QMUjajGnaFtjDnsCm5qgO2VumT-1qXUxY7k6PBP8JUYf1dQXK9zx_Agfs6Q/s1600-h/TADoc-naming.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;186&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5Vlqr5UeDnXuIqjepCKRvZvXEoBFvzaQfZPgYv0eeYeFsWm9BEFpbPaFNmfT16l95cfzpLEqKhUcf5389QMUjajGnaFtjDnsCm5qgO2VumT-1qXUxY7k6PBP8JUYf1dQXK9zx_Agfs6Q/s400/TADoc-naming.PNG&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Notice how combining our test class and method names reads like a phrase that documents the design of our software. If we group the results by Description, we get a list of all the requirements of our software.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9lj7YHidG6BoM3wbpP4eAiVJjw65wWnqaB03vAM5I1Tjant6x_WApNgdqoi9UoJyb7731kD0G5h0bpwzhQ4qoRoA4SS-yrYqscl8iZhBE7cEc5XCwvRYUTHVDzFGRPTjNMHg4aevX1xk/s1600-h/TADoc-specifications.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;257&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9lj7YHidG6BoM3wbpP4eAiVJjw65wWnqaB03vAM5I1Tjant6x_WApNgdqoi9UoJyb7731kD0G5h0bpwzhQ4qoRoA4SS-yrYqscl8iZhBE7cEc5XCwvRYUTHVDzFGRPTjNMHg4aevX1xk/s640/TADoc-specifications.PNG&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
If we expand one of the requirements, we see all the tests that validate it so we can trace back to the code that implements it.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo4pIA72NUzkot3mCv-oCGA1ECqH_7yktS5Z0-U8s9XAatBxec2Lnk7JTpbXpUaIuyV92_L8KTTjZydtll-tL4q-JqEWUP_7_Wtyn9sjuf97_rYwPmkCidyBYPazlChMPHHPkouygPBuo/s1600-h/TADoc-pawns.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;63&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo4pIA72NUzkot3mCv-oCGA1ECqH_7yktS5Z0-U8s9XAatBxec2Lnk7JTpbXpUaIuyV92_L8KTTjZydtll-tL4q-JqEWUP_7_Wtyn9sjuf97_rYwPmkCidyBYPazlChMPHHPkouygPBuo/s400/TADoc-pawns.PNG&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;I hope I’ve convinced you that tests can serve as documentation using simple tricks, conventions and tooling you may already have at your disposal. Because this documentation is embedded in code it has a lot more chance of being maintained as the code evolves. These techniques require agreement amongst team members but they foster good practices of choosing explicit names and tying development work with planning activities for traceability purposes.</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/7273345514926993818/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/7273345514926993818' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/7273345514926993818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/7273345514926993818'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2010/03/automated-unit-tests-as-documentation.html' title='Automated Unit Tests as Documentation'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5Vlqr5UeDnXuIqjepCKRvZvXEoBFvzaQfZPgYv0eeYeFsWm9BEFpbPaFNmfT16l95cfzpLEqKhUcf5389QMUjajGnaFtjDnsCm5qgO2VumT-1qXUxY7k6PBP8JUYf1dQXK9zx_Agfs6Q/s72-c/TADoc-naming.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-3011085340618748093</id><published>2010-03-12T01:44:00.001+01:00</published><updated>2010-03-12T01:47:14.197+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="IDE"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><title type='text'>Coding and Debugging in Bubbles</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilqGkKBqMShxCsvw-XXCrgMXumhNVzD_Hh6EALWzyuLNM7tYuQ61r2BZKDwNoBnR4DSUT2YjOtNsIheER8hRX7u7fu5onzo_PvT3zc1qInhBVBY-O_tazYERijNeFLZJ0bJItEAwkZddE/s1600-h/800px-Bubble_brokenchopstick.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilqGkKBqMShxCsvw-XXCrgMXumhNVzD_Hh6EALWzyuLNM7tYuQ61r2BZKDwNoBnR4DSUT2YjOtNsIheER8hRX7u7fu5onzo_PvT3zc1qInhBVBY-O_tazYERijNeFLZJ0bJItEAwkZddE/s320/800px-Bubble_brokenchopstick.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;A new concept for the modern IDE, &lt;a href=&quot;http://www.cs.brown.edu/people/acb/codebubbles_site.htm&quot;&gt;Code Bubbles&lt;/a&gt; allows developers to see and work different fragments of code as one unit. Debugging sessions can be associated with those units save and retrieved later for continued work. Quite impressive! It’s really a departure from the IDEs we’ve been using so far. Of course, this is not mainstream yet. Nevertheless,&amp;nbsp; I would like to try something like that and it would probably be interesting to have the equivalent in the .Net space.&lt;br /&gt;
I have to wonder though, what the impact will be on Object Oriented Programming and encapsulation if developers are lead to think of their code as fragments of functionality scattered in their code base…</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/3011085340618748093/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/3011085340618748093' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/3011085340618748093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/3011085340618748093'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2010/03/coding-and-debugging-in-bubbles.html' title='Coding and Debugging in Bubbles'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilqGkKBqMShxCsvw-XXCrgMXumhNVzD_Hh6EALWzyuLNM7tYuQ61r2BZKDwNoBnR4DSUT2YjOtNsIheER8hRX7u7fu5onzo_PvT3zc1qInhBVBY-O_tazYERijNeFLZJ0bJItEAwkZddE/s72-c/800px-Bubble_brokenchopstick.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-8250996073635140310</id><published>2010-02-13T23:54:00.000+01:00</published><updated>2010-03-18T18:12:32.405+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="coding dojo"/><category scheme="http://www.blogger.com/atom/ns#" term="kata"/><category scheme="http://www.blogger.com/atom/ns#" term="LINQ"/><category scheme="http://www.blogger.com/atom/ns#" term="refactoring"/><category scheme="http://www.blogger.com/atom/ns#" term="SOLID"/><title type='text'>FizzBuzz à la façon LINQ</title><content type='html'>Dernièrement mes collègues et moi exécutions le Kata &lt;a href=&quot;http://www.codingdojo.org/cgi-bin/wiki.pl?KataFizzBuzz&quot;&gt;FizzBuzz&lt;/a&gt; dans le cadre de notre Dojo &lt;a href=&quot;http://pyxis-tech.com/fr/expertises/pratiques-dingenierie/&quot;&gt;pratiques d’ingénierie&lt;/a&gt;. L’objectif était de pratiquer le développement piloté par les tests. Je dois avouer que ce fut fort amusant et la solution à laquelle nous sommes arrivés est tout à fait adéquate et présente un modèle objet élégant qui résoud le problème.&amp;nbsp; &lt;br /&gt;
La séquence FizzBuzz est générée par la méthode &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;CountTo&lt;/span&gt; de la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;FizzBuzz&lt;/span&gt;. Cette dernière utilise un ensemble de règles qui vérifient si elles s’appliquent et transforment, le cas échéant, l’entier question soit en “Fizz”, “Buzz” ou “FizzBuzzz”.&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;class FizzBuzz&amp;nbsp; &lt;br /&gt;
{&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IRule[] _rules = new IRule[] {&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new FizzBuzzRule(),&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new BuzzRule(),&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new FizzRule()&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }; &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IRule _defaultRule = new NumberRule(); &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string[] CountTo(int upperBound)&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var sequence = new List&amp;lt;string&amp;gt;(); &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var n in NumbersUpTo(upperBound))&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sequence.Add(Interpret(n));&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return RespondWith(sequence);&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static IEnumerable&amp;lt;int&amp;gt; NumbersUpTo(int n)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for ( int i = 1; i &amp;lt;= n; i++)       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return i;       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private string Interpret(int n)&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (var rule in _rules)&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (rule.Applies(n)) return rule.Apply(n);&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _defaultRule.Apply(n);&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private string[] RespondWith(List&amp;lt;string&amp;gt; result)&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result.ToArray();&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
La classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;FizzRule&lt;/span&gt; est un exemple d’implémentation d’une rèlge.&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;class FizzRule : IRule      &lt;br /&gt;
{       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool Applies(int number)       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ShouldSayFizz(number);       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static bool ShouldSayFizz(int n)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return IsDivisibleByThree(n) || ContainsThree(n);       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static bool IsDivisibleByThree(int number)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return number % 3 == 0;       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static bool ContainsThree(int n)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return n.ToString().Contains(&quot;3&quot;);       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Apply(int number)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return SayFizz();       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static string SayFizz()      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Fizz;       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private const string Fizz = &quot;fizz&quot;;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;
Plus tard, je me suis demandé de quoi aurait l’air la solution si j’utilisais les fonctionnalités du langage C# 3.0 telles que LINQ, les expressions lambda et les méthodes d’extension. Avec notre batterie de tests comme garde-fou je me suis lancé dans une session de refactorisation au bout de laquelle je suis arrivé à la solution que je présente plus loin.&lt;br /&gt;
Les premières pistes que je choisis d’explorer sont les méthodes que Resharper suggère de changer en méthodes statiques. En fait, les méthodes statiques me font toujours penser à des méthodes utilitaires qui en général sont très réutilisables. C’est le cas par exemple des méthodes &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;IsDivisibleByThree&lt;/span&gt; et &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;ContainsThree&lt;/span&gt; de la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;FizzRule&lt;/span&gt; plus haut. Je les rassemble donc dans la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;IntExtensions&lt;/span&gt; après avoir introduit un peu de généricité pour qu’elles soient utilisables également dans la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;BuzzRule&lt;/span&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;public static class IntExtensions      &lt;br /&gt;
{       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public static bool Contains(this int n, int number)       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return n.ToString().Contains(number.ToString());       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static bool IsDivisibleBy(this int number, int dividend)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return number % dividend == 0;       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br /&gt;
} &lt;/span&gt;&lt;br /&gt;
Avec ces modifications, la méthode &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;ShouldSayFizz&lt;/span&gt; se lit comme suit:&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;private static bool ShouldSayFizz(int n)    &lt;br /&gt;
{     &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return n.IsDivisibleBy(3) || n.Contains(3);     &lt;br /&gt;
} &lt;/span&gt;  &lt;br /&gt;
Je suis content car la lisibilité du code n’en souffre pas. Je m’attaque de la même façon à la méthode &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;NumbersUpTo&lt;/span&gt; de la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;FizzBuzz&lt;/span&gt;. J’en fais une méthode d’extension que je rajoute à la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;IntExtensions&lt;/span&gt;. Je prends le soin de renommer la méthode &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;FirstNumbers&lt;/span&gt; pour une meilleure lecture du code client qui se lira &lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;foreach(int number in n.FirstNumbers()) { … }&lt;/span&gt;&lt;br /&gt;
Cela me rappelle mon cours d’analyse et la série des n premiers nombres entiers… En fouillant un peu dans MSDN, je retrouve comment générer une suite d’entiers grâce à la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;Ennumerable&lt;/span&gt; et je modifie mon implémentation en conséquence. J’obtiens le résultat suivant&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;public static class IntExtensions      &lt;br /&gt;
{       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IEnumerable&amp;lt;int&amp;gt; FirstNumbers(this int n)       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Enumerable.Range(1, n);       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static bool Contains(this int n, int number)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return n.ToString().Contains(number.ToString());       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static bool IsDivisibleBy(this int number, int dividend)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return number % dividend == 0;       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
Avec ces méthodes utilitaires hors de la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;FizzRule&lt;/span&gt;, la responsabilité de celle-ci devient plus évidente et je la simplifie pour arriver au résultat suivant&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;class FizzRule : IRule      &lt;br /&gt;
{       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public const string Fizz = &quot;fizz&quot;;       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private const int Three = 3;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool AppliesTo(int number)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return number.IsDivisibleBy(Three) ||&amp;nbsp; number.Contains(Three);       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Apply(int number)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Fizz;       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
Une bonne chose de faite! Je tourne mon attention vers la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;FizzBuzz&lt;/span&gt;. Même si j’ai sorti la génération des nombres entiers hors de cette classe, elle a encore trop de responsabilités:&amp;nbsp; maintenir la liste des règles FizzBuzz, appliquer les règles qui conviennent, formater le résultat. C’est une violation évidente du principe de responsabilité unique (&lt;a href=&quot;http://en.wikipedia.org/wiki/Single_responsibility_principle&quot;&gt;Single Responsibility Principle&lt;/a&gt;) de l’oncle &lt;a href=&quot;http://objectmentor.com/omTeam/martin_r.html&quot;&gt;Bob&lt;/a&gt;. Je décide donc séparer tout ce qui touche à la transformation FizzBuzz dans une classe à part. Les règles et tranformations FizBuzz sont maintenant rendues dans la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;FizzzBuzzExtensions&lt;/span&gt;. J’ai changé l’implémentation pour utiliser LINQ étant donnée que le résultat est plus compacte et tout de même très lisible.&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;static class FizzBuzzExtensions      &lt;br /&gt;
{       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; internal static IEnumerable&amp;lt;string&amp;gt; AsFizzBuzzSequence      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;(this IEnumerable&amp;lt;int&amp;gt; sequence)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return sequence.Select(numeral =&amp;gt; Transform(numeral));       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static string Transform(int n)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return FirstRuleThatApliesTo(n).Apply(n);       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static IRule FirstRuleThatApliesTo(int n)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Rules.First(r =&amp;gt; r.AppliesTo(n));       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static readonly IRule[] Rules = new IRule[] {      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new FizzBuzzRule(),       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new BuzzRule(),       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new FizzRule(),       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new NumberRule()       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; };       &lt;br /&gt;
} &lt;/span&gt;&lt;br /&gt;
L’astuce d’encapsuler cette fonctionnalité en arrière d’une méthode d’extension facilite grandement la lecture de la classe &lt;span style=&quot;font-family: &#39;Courier New&#39;;&quot;&gt;FizzBuzz&lt;/span&gt; qui devient &lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;class FizzBuzz      &lt;br /&gt;
{       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; public string[] CountTo(int n)       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return RespondWith(n.FirstNumbers().AsFizzBuzzSequence());       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;; font-size: xx-small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal static string[] RespondWith(IEnumerable&amp;lt;string&amp;gt; result)      &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result.ToArray();       &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br /&gt;
}&lt;/span&gt;&lt;br /&gt;
Séparer ainsi les responsabilités dans différentes classes a grandement augmenté la clareté du design. De plus l’utilisation de LINQ et des méthodes d’extension fait en sorte que le code est très compacte quoique très expressif.</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/8250996073635140310/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/8250996073635140310' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/8250996073635140310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/8250996073635140310'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2010/02/fizzbuzz-la-facon-linq.html' title='FizzBuzz à la façon LINQ'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-5696951531110591996</id><published>2010-01-29T18:27:00.001+01:00</published><updated>2010-01-29T21:18:42.451+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="coaching"/><category scheme="http://www.blogger.com/atom/ns#" term="Scrum"/><title type='text'>A Coaching Session</title><content type='html'>Following is a conversation I had with a new Scum Master that had me thinking about how coaching works. It&#39;s not about telling people what to do but allowing them to figure out what needs to bo done. One powerful tool to do just that is changing perspectives. Reliving the facts as they happened but from a different angle may generate insights that open new opportunities for the coachee. Below is the conversation as I remember it. I hope it generates some insights for you as well.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;SM: &lt;/strong&gt;So what do you think about the sprint planning the other day ?&lt;br /&gt;
&lt;strong&gt;Coach: &lt;/strong&gt;Well one thing I noticed, and I did mention it on the spot, the team was about to bend some process improvement rules they agreed on implementing during the last retrospective. Your role as a Scrum Master is to make sure that the team follows its own process so that they may inspect and adapt it if need be. If the team partially implements the process in some cases and fully in some others, than interpretation of the results is more difficult and it will be harder to see what to improve next. You want to be careful when introducing changes to a process so that you know what you will be inspecting in the end.&lt;br /&gt;
&lt;strong&gt;SM: &lt;/strong&gt;Well you are right. Sticking to our decision not to include &lt;em&gt;big &lt;/em&gt;or&lt;em&gt; unclear stories &lt;/em&gt;in the sprint made us realise that we were accepting to tackle underspecified functionality. No wonder our estimates were off and we were not able to complete all the stories in the sprint.&lt;br /&gt;
&lt;strong&gt;Coach: &lt;/strong&gt;Good. But what about you ? What do you think about the sprint planning meeting ?&lt;br /&gt;
&lt;strong&gt;SM: &lt;/strong&gt;Well, one thing that bugs me is that team members don’t participate in the process.&lt;br /&gt;
&lt;strong&gt;Coach: &lt;/strong&gt;Oh? What do you mean ?&lt;br /&gt;
&lt;strong&gt;SM: &lt;/strong&gt;I mean they don’t seem to care or are not motivated. For instance, in our Scrum Masters group we thought it would be a good idea to let developers take turn at the Scrum Master’s role in the daily meeting so that they realize what we are dealing with. When I asked my team if one of them would like to take my place I had to wait for a long time before someone reluctantly offered to conduct the daily.&lt;br /&gt;
&lt;strong&gt;Coach: &lt;/strong&gt;So you want them to feel what it’s like to wear your shoes ?&lt;br /&gt;
&lt;strong&gt;SM: &lt;/strong&gt;It’s not that. It’s just that team members are not getting involved. You witnessed what happened at the sprint planning meeting. When I asked them if they were able to commit on delivering the sprint backlog, I didn’t get an answer.&lt;br /&gt;
&lt;strong&gt;Coach: &lt;/strong&gt;Well your organisation has a culture in which developers have been told what to do, when and how to do things. The change to self organisation is not going to happen overnight.&lt;br /&gt;
&lt;strong&gt;SM: &lt;/strong&gt;I know. That’s why I want them to get involved in the process but they don’t want to get onboard.&lt;br /&gt;
&lt;strong&gt;Coach: &lt;/strong&gt;And why do you think the don’t want to get onboard ?&lt;br /&gt;
&lt;strong&gt;SM: &lt;/strong&gt;I don’t know. And that’s why I’m asking you this because I’m running out of ideas.&lt;br /&gt;
&lt;strong&gt;Coach:&lt;/strong&gt; So… What are you doing that’s impeding them from getting involved in the process ?&lt;br /&gt;
&lt;strong&gt;SM: &lt;/strong&gt;I’m not sure I understand the question… What do you mean ?&lt;br /&gt;
&lt;strong&gt;Coach:&lt;/strong&gt; When you are not getting the response you’re expecting from others it’s often useful to consider that you are the one causing them to act the way they do. This empowers to make some changes instead of waiting for others to change their behaviour.&lt;br /&gt;
&lt;strong&gt;SM:&lt;/strong&gt; I’m not following you at all…&lt;br /&gt;
&lt;strong&gt;Coach: &lt;/strong&gt;Ok. So let’s go back to that sprint planning meeting. Remember how the room was laid out and where everyone was sitting. You remember ?&lt;br /&gt;
&lt;strong&gt;SM: &lt;/strong&gt;Yeah…&lt;br /&gt;
&lt;strong&gt;Coach: &lt;/strong&gt;Let’s say you take John’s place. What do you see ?&lt;br /&gt;
&lt;strong&gt;SM:&lt;/strong&gt; I’m really not sure where you want to go with this… But the only thing I see is that the monitor is too far away and its difficult to read.&lt;br /&gt;
&lt;strong&gt;Coach:&lt;/strong&gt; Well that’s something to consider. And what are you doing in the meantime ?&lt;br /&gt;
&lt;strong&gt;SM:&lt;/strong&gt; I’m updating the backlog and moving stuff around.&lt;br /&gt;
&lt;strong&gt;Coach: &lt;/strong&gt;And how do you think John is perceiving this given the organisational culture ?&lt;br /&gt;
&lt;strong&gt;SM: &lt;/strong&gt;I see… So we should probably use index cards that team members will be able to play with and update themselves.&lt;br /&gt;
&lt;strong&gt;Coach: &lt;/strong&gt;Good! That way you solve two problems. By giving the team access to the sprint backlog you allow them to grasp more fully and own its content. They’ll probably feel more comfortable committing to it at the end.&lt;br /&gt;
&lt;strong&gt;SM (not really listening anymore):&lt;/strong&gt; I can even update the backlog in the tool afterwards so that the flow is not interrupted. Thank you. That’s a great idea!&lt;br /&gt;
&lt;strong&gt;Coach:&lt;/strong&gt; Well you know it wasn’t my idea. It’s yours. You just had to change your perspective on things.&lt;br /&gt;
&lt;strong&gt;SM (already leaving): &lt;/strong&gt;Good. I’ll let you know how it turns out. Talk to you soon.&lt;br /&gt;
&lt;strong&gt;Coach (to himself): &lt;/strong&gt;I’m not really sure what he saw exactly, but changing his perspective really allowed him to find new ideas on how to tackle this issue. This coaching stuff really works… I should blog this…</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/5696951531110591996/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/5696951531110591996' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/5696951531110591996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/5696951531110591996'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2010/01/coaching-session.html' title='A Coaching Session'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-2089760106825326600</id><published>2009-12-31T20:27:00.001+01:00</published><updated>2009-12-31T20:40:45.165+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="général"/><title type='text'>De retour après un long mutisme…</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5y4bJyBHqhdk_sOv9DAHIaF1tkgRGtoSDowe8_7QUj-6tjfsxO1qvOA64lPKhniiN_UqImkqE7oNdmMtgbZvqh3weTGLID0H7_aVyMwvTjIo1JF100UXLmSqV600OZvxUcodz4rkY98M/s1600-h/lezard.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; ps=&quot;true&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5y4bJyBHqhdk_sOv9DAHIaF1tkgRGtoSDowe8_7QUj-6tjfsxO1qvOA64lPKhniiN_UqImkqE7oNdmMtgbZvqh3weTGLID0H7_aVyMwvTjIo1JF100UXLmSqV600OZvxUcodz4rkY98M/s320/lezard.jpg&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;Voilà deux ans que je m’adonne à d’autres choses intéressantes. Et comme&amp;nbsp;ce lézard, aujourd’hui je refais tranquillement surface pour partager les idées qui me trottent dans la tête. &lt;br /&gt;
Beaucoup de nouveautés depuis! De nos jours, je me consacre presqu’uniquement au développement logiciel sur la plateforme .Net et à l’accompagnement d’équipes qui effectuent une transition agile. La compagnie pour laquelle je bosse est en pleine croissance et de nouveaux défis se profilent à l’horizon. Je vais donc avoir plein de matières à réflexion à vous proposer: Windows 7, .Net 4.0, pratiques d’ingénierie agile... &lt;br /&gt;
&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;Je m’approprie, donc les nouveaux outils de blogue à ma disposition et je vous reviens bientôt.&lt;br /&gt;
&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;Joyeux temps des fêtes!&lt;br /&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/2089760106825326600/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/2089760106825326600' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/2089760106825326600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/2089760106825326600'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2009/12/de-retour-apres-un-long-mutisme.html' title='De retour après un long mutisme…'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5y4bJyBHqhdk_sOv9DAHIaF1tkgRGtoSDowe8_7QUj-6tjfsxO1qvOA64lPKhniiN_UqImkqE7oNdmMtgbZvqh3weTGLID0H7_aVyMwvTjIo1JF100UXLmSqV600OZvxUcodz4rkY98M/s72-c/lezard.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-515290613714092052</id><published>2007-06-30T03:49:00.000+02:00</published><updated>2007-06-30T04:00:45.024+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="NUnit"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><title type='text'>NUnit devient plus expressif</title><content type='html'>J&#39;ai téléchargé la dernière version de NUnit 2.4 et je suis content des améliorations apportées à l&#39;API. Le nouveau &lt;a href=&quot;http://nunit.com/index.php?p=constraintModel&amp;r=2.4.1&quot;&gt;modèle d&#39;assertion basé sur les contraintes&lt;/a&gt; rend les tests plus expressifs.&lt;br /&gt;Je n&#39;écrirai plus les assertions du type:&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;Assert.AreEqual(myString, &quot;Hello&quot;);&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Courier New;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span &gt;mais plutôt:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;Assert.That(myString, Is.Equal(&quot;Hello&quot;));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ou mieux encore si ma classe de test hérite de AssertionHelper, je pourrai écrire&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;Expect(myString, EqualTo(&quot;Hello&quot;));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Il me semble que cette syntaxe est plus lisible</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/515290613714092052/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/515290613714092052' title='3 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/515290613714092052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/515290613714092052'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2007/06/nunit-devient-plus-expressif.html' title='NUnit devient plus expressif'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-9114206902035642575</id><published>2007-06-30T03:24:00.000+02:00</published><updated>2007-06-30T03:48:34.005+02:00</updated><title type='text'>Classification des tests</title><content type='html'>&lt;a href=&quot;http://grabbagoft.blogspot.com/&quot;&gt;Jimmy Bogard&lt;/a&gt; a un excellent message sur la &lt;a href=&quot;http://grabbagoft.blogspot.com/2007/06/classifying-tests.html&quot;&gt;classification des tests&lt;/a&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Les tests unitaires vérifient le bon fonctionnement d&#39;une méthode/fonction en isolation du reste du système. Ils doivent s&#39;exécuter rapidement et n&#39;avoir qu&#39;une cause d&#39;échec. Pour ce genre de tests on évite d&#39;impliquer une base de données, un service web ou tout autre système externe. &lt;/li&gt;&lt;li&gt;Les tests d&#39;intégration vérifient le bon fonctionnement d&#39;un système lorsqu&#39;il est intégré avec les systèmes externes tels qu&#39;une base de données par exemple. En général, ces tests vérifient que les données sont bien mises à jours dans la base de données ou qu&#39;un courriel a bien été envoyé.&lt;/li&gt;&lt;li&gt;Les tests fonctionnels vérifient le bon fonctionnement de l&#39;application dans son ensemble du point de vue de l&#39;usager.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;À lire également le message de &lt;a href=&quot;http://codebetter.com/blogs/jeffrey.palermo/archive/2007/06/28/levels-of-automated-testing-within-a-single-application.aspx&quot;&gt;Jeffrey Palermo&lt;/a&gt; sur le sujet&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/9114206902035642575/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/9114206902035642575' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/9114206902035642575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/9114206902035642575'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2007/06/classification-des-tests.html' title='Classification des tests'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-2536387814890562428</id><published>2007-06-14T04:20:00.000+02:00</published><updated>2007-06-14T04:45:09.708+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DDD"/><title type='text'>Pourquoi introduire de nouveaux acronymes ?</title><content type='html'>J&#39;ai visioné une présentation de Dan Ver Johnsson sur les &lt;a href=&quot;http://www.bejug.org/confluenceBeJUG/display/PARLEYS/Get+Value+Objects+right+for+Domain+Driven+Design?showComments=true&quot;&gt;Domain Logical Value Objects&lt;/a&gt;. C&#39;est une présentation sur la manière d&#39;introduire le Domain Driven Design dans du code patrimonial. En gros, le présentateur propose de commencer à rendre explicite les valeurs significatives pour le domaine en question: numéro de téléphone, taux de change, etc. De cette manière on peut rapidement bénéficier des améliorations suivantes:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Clareté des API de Service&lt;/li&gt;&lt;li&gt;Validation et gestion d&#39;erreurs proches des données&lt;/li&gt;&lt;li&gt;Simplification du code de la logique de métier&lt;/li&gt;&lt;li&gt;Tests&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Même si je suis d&#39;accord avec les points présentés, je regrette toutefois que le présentateur aie ressenti le besoin de fournir un autre acronyme/terme technique: Domain Logical Value Object. Il me semble que tout ce dont il a parlé c&#39;est des Value Object tels que présentés par Eric Evans dans son livre sur le DDD. &lt;/p&gt;&lt;p&gt;Par ailleurs, à un moment donné il propose un exercice pour trouver les situations où l&#39;application du DDD est opportune. Selon moi, la réponse est que cela dépend toujours du contexte dans lequel ces projets sont entrepris. On ne peut répondre juste en se basant sur l&#39;énoncé du domaine. Il faut impliquer les experts afin de connaître où ils en tirent le plus de valeur.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/2536387814890562428/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/2536387814890562428' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/2536387814890562428'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/2536387814890562428'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2007/06/pourquoi-introduire-de-nouveaux.html' title='Pourquoi introduire de nouveaux acronymes ?'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-3462188988594193042</id><published>2007-06-13T05:20:00.000+02:00</published><updated>2007-06-30T04:01:49.612+02:00</updated><title type='text'>Domain Driven Design et Spécifications éxécutables</title><content type='html'>Dernièrement, je donnais un cours sur le &lt;a href=&quot;http://www.domainlanguage.com/ddd/index.html&quot;&gt;Domain Driven Design&lt;/a&gt;. Pour les exercices pratiques j&#39;ai utilisé &lt;a href=&quot;http://www.greenpeppersoftware.com/&quot;&gt;GreenPepper&lt;/a&gt; afin de pouvoir spécifier les fonctionnalités à accomplir sans pour autant imposer un design aux participants. Je dois avouer que je suis un peu perplexe quant au résultat de cette expérience. Les participants ont eu l&#39;air de s&#39;intéresser plus au produit qu&#39;aux techniques présentées dans le cours afin de mieux cerner le domaine. Sans compter que l&#39;apprentissage de l&#39;outil peut constituer une barrière importante à la bonne conduite de l&#39;exercice. Pourtant une approche basée sur des tests unitaires fournis ne me semble pas idéale car le design serait alors imposé. Les spécifications exécutables, par contre, se situent plus au niveau du modèle et du langage et de ce fait me paraissent encore plus appropriées...</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/3462188988594193042/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/3462188988594193042' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/3462188988594193042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/3462188988594193042'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2007/06/domain-driver-design-et-spcifications.html' title='Domain Driven Design et Spécifications éxécutables'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-3292219103215601039</id><published>2007-05-30T04:23:00.001+02:00</published><updated>2007-05-30T04:28:32.454+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="logiciel libre"/><category scheme="http://www.blogger.com/atom/ns#" term="moteur de recherche"/><title type='text'>Krugle - un moteur de recherche pour le logiciel libre</title><content type='html'>Aujourd&#39;hui j&#39;ai découvert &lt;a href=&quot;http://www.krugle.com&quot;&gt;krugle&lt;/a&gt; un moteur de recherche dédié au logiciel libre. Ce site permet d&#39;effectuer des recherches sur une multitudes de dépots de sources de projets du domaine public. Adieu les recherches sur Google...</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/3292219103215601039/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/3292219103215601039' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/3292219103215601039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/3292219103215601039'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2007/05/krugle-un-moteur-de-recherche-pour-le.html' title='Krugle - un moteur de recherche pour le logiciel libre'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5356363081772370386.post-5329812243075562015</id><published>2007-05-23T16:25:00.000+02:00</published><updated>2007-05-23T16:29:33.848+02:00</updated><title type='text'>My first walk in the blogosphere</title><content type='html'>Hey,&lt;br /&gt;&lt;br /&gt;I&#39;m new to this! In the following weeks, I&#39;ll try to share some of my ideas with you. Hope you find them interesting...&lt;br /&gt;&lt;br /&gt;Ernst</content><link rel='replies' type='application/atom+xml' href='http://ernststhoughts.blogspot.com/feeds/5329812243075562015/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5356363081772370386/5329812243075562015' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/5329812243075562015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5356363081772370386/posts/default/5329812243075562015'/><link rel='alternate' type='text/html' href='http://ernststhoughts.blogspot.com/2007/05/my-first-walk-in-blogosphere.html' title='My first walk in the blogosphere'/><author><name>Ernst Perpignand</name><uri>http://www.blogger.com/profile/16268268503536377997</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjprO8XagpZumgjWIXz5DklCTXI0MjB7El7nfh8NES_9kC0QGuHidxSVzlu2pMdjM9nz-h7OIRn7U7UZnSRb8tFx573Ruq_IK9I2-LQHuwgiTGW_e4eCQRsEQhFDpEdpg/s220/profil-400px.jpg'/></author><thr:total>0</thr:total></entry></feed>