<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Blog Excilys</title>
	
	<link>http://blog.excilys.com</link>
	<description>Langages, Architectures &amp; Méthodologies</description>
	<lastBuildDate>Sat, 04 Sep 2010 14:11:48 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/blogexcilyscom" /><feedburner:info uri="blogexcilyscom" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>La SCJP, c’est pas de la menthe à l’eau</title>
		<link>http://feedproxy.google.com/~r/blogexcilyscom/~3/ow4XoErRIj0/</link>
		<comments>http://blog.excilys.com/2010/08/24/la-scjp-cest-pas-de-la-menthe-a-leau/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 07:21:18 +0000</pubDate>
		<dc:creator>Pierre-Yves RICAU</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[certification]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jduchess]]></category>
		<category><![CDATA[scjp]]></category>
		<category><![CDATA[song]]></category>

		<guid isPermaLink="false">http://blog.excilys.com/?p=2627</guid>
		<description><![CDATA[Les JDuchess françaises ont récemment décidé d&#8217;organiser un groupe de travail pour les personnes souhaitant passer la certification SCJP.  Après avoir donné mon retour d&#8217;expérience sur la mailing list dédiée, je me suis dit qu&#8217;il serait intéressant d&#8217;en faire un article.

SCJP, mékeskidit ?
La SCJP est une certification Java sous la forme de QCM, délivrée par [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-2639" title="JDuchess" src="http://blog.excilys.com/wp-content/uploads/2010/08/duchess.jpg" alt="" width="150" height="150" />Les <a href="http://jduchess.org/duchess-france/">JDuchess</a> françaises ont récemment décidé d&#8217;organiser un <a href="http://groups.google.com/group/scjp-jduchess">groupe de travail</a> pour les personnes souhaitant passer la certification <a href="http://in.sun.com/training/certification/java/scjp.xml">SCJP</a>.  Après avoir donné mon retour d&#8217;expérience sur la mailing list dédiée, je me suis dit qu&#8217;il serait intéressant d&#8217;en faire un article.</p>
<p><span id="more-2627"></span></p>
<h3>SCJP, mékeskidit ?</h3>
<p>La SCJP est une certification Java sous la forme de QCM, délivrée par Sun.  Elle permet d&#8217;attester que le certifié possède une <strong>connaissance détaillée</strong> du langage Java. On dit souvent qu&#8217;elle demande au <strong>développeur </strong>de fonctionner comme un <strong>compilateur </strong>Java.</p>
<h4>Blah blah&#8230; certification, piège à *** ?</h4>
<p>Dans notre beau métier, les certifications ont souvent peu de valeur. Elles permettent aux SSII de vendre des consultants &#8220;juniors experts certifiés&#8221; (cherchez l&#8217;oxymore <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ), et aux éditeurs de gagner de l&#8217;argent sans trop d&#8217;effort. Plus la certification est facile à obtenir, moins les candidats hésitent à la passer, et plus l&#8217;éditeur y gagne financièrement. Ce qui n&#8217;arrange pas la réputation des dites certifications.</p>
<h4>La SCJP n&#8217;est pas <em>facile</em></h4>
<p>A l&#8217;inverse, la SCJP est <strong>difficile </strong>à obtenir, et demande une préparation spécifique. Je connais plusieurs personnes, pourtant très compétentes, qui  n&#8217;ont pas réussi cet examen. Vous pouvez avoir 5 ans d&#8217;expérience en développement Java et vous prendre une rouste.<img class="aligncenter size-full wp-image-2642" title="SCJP Path" src="http://blog.excilys.com/wp-content/uploads/2010/08/scjp_path1.gif" alt="" width="600" height="200" /></p>
<h4>Valeur intrinsèque de la SCJP</h4>
<p>La valeur de la SCJP n&#8217;est ni dans les 3h d&#8217;examen, ni dans le bout de papier obtenu à la fin, mais bien dans le <strong>travail</strong> réalisé <strong>en amont</strong>. Ce travail permet de maitriser en détail les subtilités du langage Java, ainsi qu&#8217;un bon nombre d&#8217;API. Il y a de grandes chances que votre façon d&#8217;écrire du code Java change significativement entre avant et après la certification.</p>
<p>Cette certification n&#8217;est certainement pas assez reconnue sur le marché du travail. Soyons honnête, ce n&#8217;est pas en la passant que vous doublerez du jour au lendemain votre taux de facturation, ou que les chasseurs de tête vous tomberont dessus.</p>
<p>Cependant, c&#8217;est pour <strong>vous même</strong> que cela fera toute la différence. Il faut le voir comme un investissement personnel, payant à long terme : votre maitrise du langage vous rendra <strong>plus productif</strong>, <strong>plus sûr</strong> de votre code. Au jour le jour, cela amènera nécessairement une <strong>reconnaissance </strong>de vos pairs.</p>
<h4>Non-Pub <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  : les consultants Excilys sont certifiés SCJP</h4>
<p><a href="http://www.excilys.com/"><img class="alignright size-full wp-image-2644" title="Logo Excilys" src="http://blog.excilys.com/wp-content/uploads/2010/08/logo_excilys.png" alt="" width="154" height="82" /></a>Permettez-moi une petite digression, non pas pour faire de la pub, mais plutôt pour souligner mon propos.</p>
<p>Le groupe Excilys recrute ses consultants en partie via des <a href="http://www.ebusinessinformation.fr/contactrecrutement/stages">stages ingénieur</a> de fin d&#8217;étude. Les stagiaires sont formés en interne, et le passage de la certification leur est offert. Dès lors, la réussite de la <strong>SCJP </strong>est un <strong>prérequis </strong>à l&#8217;embauche à la fin du stage.</p>
<p>Si ce mécanisme est en place, c&#8217;est qu&#8217;il a fait ses preuves : cela permet de s&#8217;assurer que les consultants ont une bonne maitrise du langage Java.</p>
<h3>Préparer la SCJP</h3>
<p>Les conseils suivants ne sont pas nécessairement LA seule façon de s&#8217;y prendre, mais si ça peut vous aider c&#8217;est cool.</p>
<h4>Plus de 800 pages : toutes à lire sans exception (sauf au chapitre 5 <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' />  )</h4>
<ul>
<li>Lisez l&#8217;intégralité du <a href="http://www.amazon.fr/SCJP-Sun-Certified-Programmer-Java/dp/0071591060">bouquin de référence</a> une première fois, en prenant le temps de comprendre. A la lecture, j&#8217;ai été souvent surpris, il y a de nombreuses subtilités Java qui sont inconnues des développeurs, surtout dans les premiers chapitres. Par la suite, relisez les chapitres sur lesquels vous ne vous sentez pas à l&#8217;aise.</li>
</ul>
<h4>Ayez toujours un NetClipse sous le coude</h4>
<ul>
<li>En parallèle de la lecture du livre, faites des mises en pratique. Pour moi, cela voulait dire avoir toujours un Eclipse à portée de la main quand je lisais la SCJP. Le moindre doute, ou la moindre nouveauté, et hop un bout de code qui met le principe en œuvre.</li>
</ul>
<h4>Testez votre compréhension</h4>
<ul>
<li>Répondez aux questions de fin de chapitre sérieusement, et notez vos  résultats. C&#8217;est un bon moyen pour voir si vous avez bien lu et compris  un chapitre. Si les réponses ne vous paraissent pas évidentes, il faut relire <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  .</li>
</ul>
<h4>Trouvez des compagnons de galère</h4>
<ul>
<li> Ne travaillez pas seul : émulation et challenge sont les meilleurs moyens de bien apprendre et de ne pas faire d&#8217;impasse. Trouvez-vous quelqu&#8217;un qui la prépare aussi, et partagez vos découvertes.</li>
</ul>
<h4>Fixez une deadline</h4>
<ul>
<li>Prenez un <a href="http://en.wikipedia.org/wiki/Voucher">voucher</a> et réservez une date. La SCJP demande un travail sur la longueur, et il est facile de reporter en disant &#8220;je réserverai quand je serai prêt&#8221;. En fixant une date, vous paniquerez et vous vous forcerez à travailler <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  .</li>
</ul>
<h4>&#8220;J&#8217;utilise des <code class="codecolorer java default"><span class="java"><span style="color: #003399;">List</span></span></code> tous les jours, je peux sauter le chapitre 7 !&#8221;</h4>
<ul>
<li>Ne faites pas d&#8217;impasse sur les API. Connaître les signatures et les contrats des différentes méthodes d&#8217;un <a href="http://download.oracle.com/javase/6/docs/api/java/util/NavigableSet.html">NavigableSet</a>, c&#8217;est au moins aussi important que maîtriser la syntaxe du &#8220;<a href="http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#78993">goto</a>&#8221; .</li>
</ul>
<h4>&#8220;J&#8217;ai masterisé JavaBlackBelt, je suis fin prêt !&#8221;</h4>
<ul>
<li><a href="http://www.blackbeltfactory.com">JavaBlackBelt</a> et consorts, c&#8217;est très bien, mais ce n&#8217;est pas la SCJP. Ce type de quiz est intéressant au départ, et il y a certainement des questions difficiles, mais on en a rapidement fait le tour. De plus, la forme n&#8217;a strictement rien à voir avec la SCJP, et bosser uniquement sur JavaBlackBelt est le meilleur moyen de se planter.</li>
</ul>
<h3>La dernière ligne droite</h3>
<p>C&#8217;est probablement mon conseil <strong>le plus important</strong> : à l&#8217;approche de la deadline, passez des examens blancs avec <a href="http://examlab.tk/">ExamLab for SCJP</a>. C&#8217;est <strong>gratuit</strong>, et c&#8217;est le <strong>meilleur </strong>outil pour s&#8217;entrainer. Ça ne tourne que sous Windows, ce qui n&#8217;est certainement pas une excuse pour faire l&#8217;impasse (débrouillez-vous, installez <a href="http://www.virtualbox.org/">virtualbox</a>).
<p style="text-align: center;"><img class="aligncenter size-full wp-image-2650" title="ExamLab" src="http://blog.excilys.com/wp-content/uploads/2010/08/examlab_screenshot.png" alt="" width="648" height="485" /></p>
<h4>ExamLab en résumé</h4>
<ul>
<li>Une interface &#8220;<strong>aussi pourrie</strong>&#8221; que celle de la vraie SCJP (très important, pour ne pas être déstabilisé par la forme).</li>
<li>Contient tous les types de questions présents dans la SCJP, y compris les &#8220;codes à trous&#8221;.</li>
<li>Des examens de <strong>3 heures</strong> sans interruption possible, fini les révisions en dilettantes à la &#8220;je répond à une petite question, je regarde la réponse, je prend un café&#8221;.</li>
<li>Un concentré des questions les <strong>plus dures</strong> qu&#8217;on puisse trouver dans la SCJP. Le premier exam est en général une <strong>bonne claque</strong>.</li>
<li>5 examens, ce qui n&#8217;est pas énorme, c&#8217;est pourquoi il est préférable de les garder pour la &#8220;dernière ligne droite&#8221;. Ceci dit, vous pouvez toujours tenter le premier examen pour vous donner une idée du principe.</li>
</ul>
<p>Je n&#8217;ai aucune action chez <a href="http://examlab.tk/">ExamLab</a> (ce n&#8217;est même pas une entreprise <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> ), mais c&#8217;est réellement le produit qui m&#8217;a fait le plus bosser et m&#8217;a permis de réussir ma SCJP.</p>
<h3>L&#8217;examen</h3>
<p>Le jour de l&#8217;examen, ne vous laissez pas déconcentrer, le temps passe vite. Je me suis retrouvé devant un écran <a href="http://www.google.com/images?hl=en&amp;source=imghp&amp;biw=1408&amp;bih=923&amp;q=crt&amp;gbv=2&amp;aq=f&amp;aqi=&amp;aql=&amp;oq=&amp;gs_rfai=">CRT</a> tout gros tout moche, une souris peu ragoutante, des reflets sur l&#8217;écran, un bonhomme à côté qui renifle&#8230; bref, il faut faire abstraction et garder à l&#8217;esprit qu&#8217;on est en exam.</p>
<p>Le temps imparti est largement supérieur à ce dont vous aurez besoin. Il y aura des questions où vous ne serez pas certain de la réponse, et en général y passer plus de temps ne sert à rien. Soit vous savez, soit vous faites un coup de poker <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  .</p>
<h4>Conclusion : qui aura le plus gros&#8230;</h4>
<p>&#8230;score ?</p>
<p>Allez, histoire de mettre un peu de compétition et de motivation, balancez vos scores en commentaires <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  . Et comme on n&#8217;est jamais si bien servi que par soi-même, je commence : 91% à la SCJP 6 <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  .<br />
<img class="aligncenter size-full wp-image-2635" title="SCJP" src="http://blog.excilys.com/wp-content/uploads/2010/08/scjp_card.jpg" alt="" width="300" height="191" /></p>
<p>Pour ceux d&#8217;entre vous qui aiment la difficulté, le blog d&#8217;<a href="http://thecodersbreakfast.net/">Olivier Croisier</a> fourmille de <a href="http://thecodersbreakfast.net/index.php?category/Java-JEE/Quizs-Techniques">quiz</a> plus tordus les uns que les autres. Pour approfondir vos connaissances, n&#8217;hésitez pas à lire également l&#8217;excellent <a href="http://java.sun.com/docs/books/effective/">Effective Java</a>, de <a href="http://twitter.com/joshbloch">Josh Blosh</a>.</p>
<p>Il ne me reste plus qu&#8217;à souhaiter bonne chance aux futurs candidats, et notamment aux motivés du <a href="http://groups.google.com/group/scjp-jduchess">groupe JDuchess</a> <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  .</p>
<p><strong>Edit 24/08/2010</strong> : Oracle vient visiblement d&#8217;annoncer que la SCJP serait désormais une <a href="http://www.certpal.com/blogs/2010/08/oracle-rebrands-sun-certification/">OCJP</a>. Le contenu ne change pas, celle-ci devrait donc garder la même valeur <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  .</p>
<h4>Bonus : le titre en chanson</h4>
<p>D&#8217;où vient le titre de cet article ? D&#8217;une joyeuse chanson des inconditionnels du <a href="http://fr.wikipedia.org/wiki/Java_%28groupe%29">rap-musette</a> :</p>
<blockquote><p>Java c&#8217;est pas de la menthe à l&#8217;eau, Java c&#8217;est du rock&#8217;n roll !</p></blockquote>
<p>Les auditeurs réguliers du <a href="http://www.javaposse.com/">Java Posse</a> doivent aussi connaître la <a href="http://www.modlost.net/home/blog/java-song.html">Java Song</a> <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  :</p>
<blockquote><p>Java, Java, Java Java jing-jing-jing</p>
<p>It’s not a cup of coffee but it’s hot as can be</p>
<p>Came pourin’ through the Gates on a “Big Mac” Nealy</p>
<p>Singin’, Java, Java, Java Java jing-jing-jing</p></blockquote>
<img src="http://feeds.feedburner.com/~r/blogexcilyscom/~4/ow4XoErRIj0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.excilys.com/2010/08/24/la-scjp-cest-pas-de-la-menthe-a-leau/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://blog.excilys.com/2010/08/24/la-scjp-cest-pas-de-la-menthe-a-leau/</feedburner:origLink></item>
		<item>
		<title>Refactoring par la pratique</title>
		<link>http://feedproxy.google.com/~r/blogexcilyscom/~3/7ZOMujiQB1w/</link>
		<comments>http://blog.excilys.com/2010/08/03/refactoring-par-la-pratique/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 12:48:47 +0000</pubDate>
		<dc:creator>Pierre-Yves RICAU</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[clean-code]]></category>
		<category><![CDATA[code propre]]></category>
		<category><![CDATA[eclEmma]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[tests unitaires]]></category>

		<guid isPermaLink="false">http://blog.excilys.com/?p=2322</guid>
		<description><![CDATA[Dans cet article, nous allons procéder à un refactoring sur un exemple concret, afin de mettre en exergue quelques bonnes pratiques.
Défi : comprendre du code inélégant*
*Edit : j&#8217;avais initialement écrit &#8220;imb*table&#8221;, mais il paraît que ça ne fait pas très sérieux  
 
Êtes-vous capable de comprendre ce que fait la méthode computeConvexHull&#40;&#41; en moins [...]]]></description>
			<content:encoded><![CDATA[<p>Dans cet article, nous allons procéder à un <a href="http://fr.wikipedia.org/wiki/Refactoring">refactoring</a> sur un exemple concret, afin de mettre en exergue quelques bonnes pratiques.</p>
<h3>Défi : comprendre du code inélégant*</h3>
<p><em>*Edit : j&#8217;avais initialement écrit &#8220;imb*table&#8221;, mais il paraît que ça ne fait pas très sérieux <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </em></p>
<address> </address>
<p>Êtes-vous capable de comprendre ce que fait la méthode <code class="codecolorer java default"><span class="java">computeConvexHull<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></span></code> en moins de 3 minutes ?</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> List<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> computeConvexHull<span style="color: #009900;">&#40;</span>Set<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> points<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Path list</span><br />
&nbsp; &nbsp; ArrayList<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> path <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ArrayList<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Pick the min longitude point as first</span><br />
&nbsp; &nbsp; GeoPoint first <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>GeoPoint point <span style="color: #339933;">:</span> points<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>first <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">||</span> point.<span style="color: #006633;">getLongitude</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> first.<span style="color: #006633;">getLongitude</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; first <span style="color: #339933;">=</span> point<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>first <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; path.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>first<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IllegalArgumentException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Can't retrieve the western point&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">boolean</span> right <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">boolean</span> loop <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>loop<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; GeoPoint current <span style="color: #339933;">=</span> path.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>path.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; GeoPoint next <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">double</span> nextLatitudeDiff <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">double</span> nextLongitudeDiff <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">boolean</span> recordNext <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>GeoPoint point <span style="color: #339933;">:</span> points<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>point.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>current<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">double</span> latitudeDiff <span style="color: #339933;">=</span> point.<span style="color: #006633;">getLatitude</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> current.<span style="color: #006633;">getLatitude</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">double</span> longitudeDiff <span style="color: #339933;">=</span> point.<span style="color: #006633;">getLongitude</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> current.<span style="color: #006633;">getLongitude</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>longitudeDiff <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span> <span style="color: #339933;">||</span> longitudeDiff <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #339933;">==</span> right<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>next <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; recordNext <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Compare the 'a' in the linear equation Y = a.X</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// that correspond to the line slope.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">boolean</span> negativeSlope <span style="color: #339933;">=</span> latitudeDiff <span style="color: #339933;">*</span> nextLongitudeDiff <span style="color: #339933;">-</span> nextLatitudeDiff <span style="color: #339933;">*</span> longitudeDiff <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>negativeSlope<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; recordNext <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>recordNext<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; recordNext <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; next <span style="color: #339933;">=</span> point<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nextLatitudeDiff <span style="color: #339933;">=</span> latitudeDiff<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nextLongitudeDiff <span style="color: #339933;">=</span> longitudeDiff<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>next <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Check abnormal case</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>path.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> points.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">RuntimeException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Convex hull computation failed&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; path.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>next<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">/*<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* If we are not back to the first point, let's continue finding<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* the path.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Otherwise, do nothing =&gt; going back from the stack, this is<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* actually the end point of the recursive algorithm.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>path.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> next<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loop <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// We have reached the point on the right, let's go back!</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; right <span style="color: #339933;">=</span> <span style="color: #339933;">!</span>right<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> path<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Alors ? <a href="http://checkstyle.sourceforge.net/">Checkstyle</a> lui donne une <a href="http://fr.wikipedia.org/wiki/Nombre_cyclomatique">complexité cyclomatique</a> de <strong>16</strong>. Plutôt difficile d&#8217;y voir clair. Moi en tout cas, je n&#8217;en suis pas capable.<br />
Et pourtant, j&#8217;en suis l&#8217;auteur <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Critique de code bien ordonnée commence par soi-même !<span id="more-2322"></span></p>
<h3>Le développeur, lecteur à temps plein</h3>
<p>On entend souvent dire que produire un code de qualité, c&#8217;est un coût à  court terme et un gain à long terme. <strong>C&#8217;est faux</strong>.</p>
<p>En tant que développeur, je passe l&#8217;<strong>essentiel </strong>de mon temps à <strong>lire du code</strong>, et proportionnellement <strong>peu à en écrire</strong>. En effet, avant chaque modification, je parcours le code pour en comprendre les tenants et les aboutissants, et décider des modifications que je vais réaliser.</p>
<p>Étudiez la manière dont vous développez, vous verrez c&#8217;est édifiant <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  .</p>
<p>Puisqu&#8217;un développeur passe l&#8217;essentiel de son temps à lire du code, le meilleur moyen de gagner en productivité, c&#8217;est avoir un code qui soit <strong>facile à </strong><strong>comprendre</strong>.</p>
<p><strong>Améliorer la qualité</strong> du code, c&#8217;est un <strong>gain immédiat</strong>, un point c&#8217;est tout.</p>
<h3>Pas de refactoring sans tests</h3>
<p>Il est <strong>impossible </strong>de produire un code de <strong>qualité </strong>dès le départ. Ne vous morfondez pas, <strong>ce n&#8217;est pas grave</strong>.</p>
<p>Pour améliorer le code, rien de tel que le <a href="http://en.wikipedia.org/wiki/Code_refactoring">refactoring</a>, qui consiste à transformer le code sans en modifier le fonctionnement extérieur. Des <a href="http://fr.wikipedia.org/wiki/Test_unitaire">tests unitaires</a><strong> </strong>sont alors nécessaires, car ils permettent d&#8217;exprimer le comportement du code et de garantir qu&#8217;il n&#8217;a pas varié. Les tests doivent être écrits <strong>avant tout refactoring</strong>.</p>
<p>En fait, idéalement, vous faites du <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> et votre code est déjà testé. Il n&#8217;est cependant pas rare de rejoindre une équipe où personne n&#8217;a &#8220;eu le temps&#8221; d&#8217;en écrire un seul.</p>
<p>Mais revenons à notre code incompréhensible&#8230;</p>
<h3>Enveloppe convexe, mékeskidit ?</h3>
<p>Comme son nom l&#8217;indique <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> , la méthode <code class="codecolorer java default"><span class="java">computeConvexHull<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></span></code> permet de calculer l&#8217;<a href="http://fr.wikipedia.org/wiki/Enveloppe_convexe">enveloppe convexe</a> (l&#8217;emballage) d&#8217;un ensemble de points géolocalisés.</p>
<div id="attachment_2536" class="wp-caption aligncenter" style="width: 268px"><a href="http://blog.excilys.com/wp-content/uploads/2010/07/ConvexHull.png"><img class="size-full wp-image-2536 " src="http://blog.excilys.com/wp-content/uploads/2010/07/ConvexHull.png" alt="" width="258" height="206" /></a><p class="wp-caption-text">Enveloppe convexe</p></div>
<p>Le principe de l&#8217;algorithme est de partir du point le plus à l&#8217;ouest, trouver le chemin de l&#8217;enveloppe dans le sens anti-horaire jusqu&#8217;au point le plus à l&#8217;est, puis faire de même dans l&#8217;autre sens.</p>
<p>Toutefois, nous ne connaissons toujours pas précisément son fonctionnement.</p>
<h3>Des tests pour comprendre et exprimer ce que fait le code</h3>
<p>Afin d&#8217;y parvenir, je vous propose d&#8217;écrire des tests. C&#8217;est un bon moyen pour comprendre et documenter le fonctionnement du code, et contrairement aux <a href="http://thecodersbreakfast.net/index.php?post/2010/05/23/Why-I-Don-t-Read-Your-Comments">commentaires</a>, les tests évoluent au même rythme que le code.</p>
<p>Pour ne pas alourdir l&#8217;article, je vous laisse consulter les <a href="http://code.google.com/p/excilys/source/browse/projects/PolygonRefactoring/tags/article_refactoring/test/com/excilys/blog/refactoring/initial/InitialHullHelperTest.java">tests en question</a>.</p>
<p>Quand cesser d&#8217;écrire des tests ? Quand vous êtes certains d&#8217;avoir couvert <strong>tous les comportements</strong> possibles du code. Vous pouvez par exemple utiliser <a href="http://www.eclemma.org/">EclEmma</a> pour obtenir le pourcentage de couverture des classes que vous testez. <strong>100%</strong> est un <strong>minimum</strong>, cela ne garantit pas que vous n&#8217;avez <a href="http://devlicio.us/blogs/tim_barcz/archive/2009/03/31/code-coverage-100-coverage-and-still-failing.aspx">rien oublié</a>.</p>
<p><a href="http://blog.excilys.com/wp-content/uploads/2010/07/couverture.png"><img class="aligncenter size-full wp-image-2550" src="http://blog.excilys.com/wp-content/uploads/2010/07/couverture.png" alt="" width="379" height="154" /></a></p>
<h3>Écrire des tests, c&#8217;est aussi découvrir des bugs</h3>
<p>Ceux d&#8217;entre vous qui ont lu les tests se sont certainement exclamé : &#8220;<em>Hey, c&#8217;est de la triche, il y a des tests en commentaire</em> !&#8221;.</p>
<p>Il s&#8217;avère qu&#8217;en tentant d&#8217;exprimer le comportement que j&#8217;attendais de ce code à travers mes tests unitaires, j&#8217;ai rencontré des bugs.</p>
<p>J&#8217;ai donc écris du code mettant en évidence ces comportements inattendus :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@Test<span style="color: #009900;">&#40;</span>expected <span style="color: #339933;">=</span> TimeoutException.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> onePointSetLoopEndlessly<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">final</span> Set<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> points <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HashSet<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; points.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> GeoPoint<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; timeoutAfterDelay<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">300</span>, <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Runnable</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hullHelper.<span style="color: #006633;">computeConvexHull</span><span style="color: #009900;">&#40;</span>points<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">fail</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;One point set should loop endlessly (timeout from tests after 300 ms)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> timeoutAfterDelay<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> delayInMs, <span style="color: #003399;">Runnable</span> codeToRun<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> TimeoutException, <span style="color: #003399;">InterruptedException</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; ExecutionException <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; ExecutorService executor <span style="color: #339933;">=</span> Executors.<span style="color: #006633;">newCachedThreadPool</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; FutureTask<span style="color: #339933;">&lt;?&gt;</span> future <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> FutureTask<span style="color: #339933;">&lt;</span>Object<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span>codeToRun, <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; executor.<span style="color: #006633;">submit</span><span style="color: #009900;">&#40;</span>future<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; future.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>delayInMs, TimeUnit.<span style="color: #006633;">MILLISECONDS</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@Test<span style="color: #009900;">&#40;</span>expected <span style="color: #339933;">=</span> <span style="color: #003399;">RuntimeException</span>.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> computationFail<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; Set<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> points <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HashSet<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; GeoPoint northWest <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GeoPoint<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; GeoPoint southWest <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GeoPoint<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; GeoPoint southEast <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GeoPoint<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">5</span>, <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; GeoPoint northEast <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GeoPoint<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">15</span>, <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; points.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>northWest<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; points.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>southWest<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; points.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>southEast<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; points.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>northEast<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; hullHelper.<span style="color: #006633;">computeConvexHull</span><span style="color: #009900;">&#40;</span>points<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">fail</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Should fail when there are two eastern points with same longitude&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@Test<span style="color: #009900;">&#40;</span>expected <span style="color: #339933;">=</span> <span style="color: #003399;">NullPointerException</span>.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> pointsNullThrowsNullPointerException<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; hullHelper.<span style="color: #006633;">computeConvexHull</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">Assert</span>.<span style="color: #006633;">fail</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Null set should throw a NullPointerException&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Avant de refactorer, il faut corriger les bugs :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Tout d'abord, en vérifiant les paramètres d'entrée.</span><br />
<span style="color: #000000; font-weight: bold;">public</span> List<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> computeConvexHull<span style="color: #009900;">&#40;</span>Set<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> points<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>points <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IllegalArgumentException</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>points.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">new</span> ArrayList<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span>points<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #666666; font-style: italic;">// [...]</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Par ailleurs, il s'avère que ce if n'était pas assez complexe...</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>longitudeDiff <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span> <span style="color: #339933;">||</span> longitudeDiff <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #339933;">==</span> right<span style="color: #009900;">&#41;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Il devient :</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>longitudeDiff <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span> <span style="color: #339933;">&amp;&amp;</span> latitudeDiff <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #339933;">==</span> right <span style="color: #339933;">||</span> longitudeDiff <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #339933;">==</span> right<span style="color: #009900;">&#41;</span><br />
<span style="color: #666666; font-style: italic;">// Beaucoup plus clair, isn't it ?</span></div></td></tr></tbody></table></div>
</pre>
<p>Je vous laisse parcourir la <a href="http://code.google.com/p/excilys/source/browse/projects/PolygonRefactoring/tags/article_refactoring/src/com/excilys/blog/refactoring/fixed/FixedInitialHullHelper.java">version corrigée</a>. De même pour les <a href="http://code.google.com/p/excilys/source/browse/projects/PolygonRefactoring/tags/article_refactoring/test/com/excilys/blog/refactoring/fixed/FixedInitialHullHelperTest.java">tests unitaires</a>, qui désormais passent tous.</p>
<h3>Refactoring : principe</h3>
<p>Un refactoring en bonne et due forme, c&#8217;est une suite de petites modifications avec exécution des tests entre chaque modification, pour s&#8217;assurer que l&#8217;on ne change pas le comportement.</p>
<p>Pour réaliser ce refactoring, j&#8217;ai mis en œuvre les principes suivants :</p>
<ul>
<li>Choisir des <strong>noms descriptifs</strong> pour les classes, méthodes et variables.</li>
<li><strong>Minimiser</strong> le nombre d&#8217;<strong>arguments</strong> des méthodes, <strong>maximum 3</strong> arguments. Si une méthode utilise les attributs d&#8217;un objet passé en paramètre, elle doit devenir une <strong>méthode d&#8217;instance</strong> sur cet objet. Lorsque des méthodes d&#8217;une même classe se passent le même argument les unes après les autres, il faut transformer cet argument en variable d&#8217;instance.</li>
<li><strong>Pas d&#8217;arguments de sortie</strong> : les méthodes ne modifient pas l&#8217;état des arguments qui leurs sont fournis.</li>
<li><strong>Pas de redondance</strong> : s&#8217;il y a de la redondance, il y a probablement une opportunité d&#8217;abstraction manquée.</li>
<li>Séparation verticale : les variables et les fonctions sont définies <strong>au plus près</strong> de leur <strong>utilisation</strong>. Les méthodes utilisées par une méthode du niveau d&#8217;abstraction supérieur doivent être placées immédiatement en dessous de celle-ci.</li>
<li>Variables explicatives : passer par des variables intermédiaires avec des <strong>noms explicites</strong>, plutôt qu&#8217;écrire des méthodes d&#8217;une seule ligne.</li>
<li>Limiter le nombre de <a href="http://blog.excilys.com/2010/06/25/de-switcher-nest-pas-jouer/">switch</a>.</li>
<li>Chaque méthode fait <strong>une seule chose</strong>, il est préférable d&#8217;écrire de nombreuses méthodes de quelques lignes avec des noms significatifs.</li>
</ul>
<p>Voici comment j&#8217;ai procédé :</p>
<ul>
<li>J&#8217;ai tout d&#8217;abord décomposé le code en plusieurs méthodes <strong>isolant </strong>les différentes <strong>étapes </strong>de l&#8217;algorithme.</li>
<li>Puis j&#8217;ai supprimé les <strong>arguments de sortie</strong>.</li>
<li>J&#8217;ai ensuite créé des classes encapsulant les différents traitements.</li>
<li>Et ainsi de suite :  j&#8217;ai transformé le code par <strong>itérations successives</strong>, en appliquant chacun des principes listés précédemment. Il ne faut pas tout faire d&#8217;un coup, mieux vaut réaliser une petite modification, exécuter les tests, commiter, et continuer.</li>
<li>Au fur et à mesure des transformations, je n&#8217;ai pas hésité à <strong>créer de nouvelles classes</strong>. Cela a temporairement augmenté la base de code, mais il s&#8217;avère qu&#8217;une fois les responsabilités bien séparées, de nombreuses <strong>simplifications </strong>apparaissent.</li>
</ul>
<p>Pour finir, j&#8217;ai réalisé une dernière transformation qui ne <a href="http://fr.wikipedia.org/wiki/On_ne_peut_pas_plaire_%C3%A0_tout_le_monde">plaira</a> pas forcément à tout le monde : créer des classes d&#8217;algorithme stateful, qui travaillent sur des variables d&#8217;instance plutôt que sur des paramètres.</p>
<p>Cela permet de limiter grandement le nombre de paramètre, et le code devient alors une succession d&#8217;appels de méthode. Il faut donc <strong>soigneusement </strong>choisir les <strong>noms </strong>de méthodes, et limiter au maximum la taille des classes afin de ne pas perdre le fil. De plus, par nature ces classes ne sont pas <a href="http://en.wikipedia.org/wiki/Thread_safety">threadsafe</a>.</p>
<p>Le refactoring n&#8217;est donc pas un &#8220;ravalement de façade&#8221;, mais bien une <strong>succession de transformations</strong> qu&#8217;on ne peut prévoir d&#8217;avance. Je n&#8217;avais pas la moindre idée du résultat auquel je souhaitai arriver quand j&#8217;ai commencé à réaliser ces modifications.</p>
<p>Enfin, il est important de se <strong>limiter dans le temps</strong>, car il est difficile de définir des objectifs mesurables pour un refactoring.</p>
<h3>Refactoring : résultat</h3>
<p>La méthode <code class="codecolorer java default"><span class="java">computeConvexHull<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></span></code> est désormais bien allégée :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> List<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> computeConvexHull<span style="color: #009900;">&#40;</span>Set<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> points<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; GeoPointSet geoPointSet <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GeoPointSet<span style="color: #009900;">&#40;</span>points<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; geoPointSet.<span style="color: #006633;">checkPreconditions</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>geoPointSet.<span style="color: #006633;">hasOnePoint</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> geoPointSet.<span style="color: #006633;">copyAsList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; HullFinder hullFinder <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HullFinder<span style="color: #009900;">&#40;</span>geoPointSet<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> hullFinder.<span style="color: #006633;">findAntiClockwiseHull</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>L&#8217;algorithme est compréhensible à travers quelques méthodes clés. Tout d&#8217;abord, dans la classe <code class="codecolorer java default"><span class="java">HullFinder</span></code> :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> List<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> findAntiClockwiseHull<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; findBounds<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; findEastPath<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; findWestPath<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> assembleHull<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> findBounds<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003399;">Bounds</span> bounds <span style="color: #339933;">=</span> geoPointSet.<span style="color: #006633;">findBounds</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; westernPoint <span style="color: #339933;">=</span> bounds.<span style="color: #006633;">getWesternPoint</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; easternPoint <span style="color: #339933;">=</span> bounds.<span style="color: #006633;">getEasternPoint</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> findEastPath<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; eastPath <span style="color: #339933;">=</span> eastPathFinder.<span style="color: #006633;">findPath</span><span style="color: #009900;">&#40;</span>westernPoint, easternPoint<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> findWestPath<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; westPath <span style="color: #339933;">=</span> westPathFinder.<span style="color: #006633;">findPath</span><span style="color: #009900;">&#40;</span>easternPoint, westernPoint<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">private</span> List<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> assembleHull<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; List<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> hull <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ArrayList<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;;</span><br />
&nbsp; &nbsp; hull.<span style="color: #006633;">addAll</span><span style="color: #009900;">&#40;</span>eastPath<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; hull.<span style="color: #006633;">addAll</span><span style="color: #009900;">&#40;</span>westPath<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; hull.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>westernPoint<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> hull<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Et pour finir, dans la classe <code class="codecolorer java default"><span class="java">PathFinder</span></code> :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> List<span style="color: #339933;">&lt;</span>GeoPoint<span style="color: #339933;">&gt;</span> findPath<span style="color: #009900;">&#40;</span>GeoPoint startPoint, GeoPoint endPoint<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; initPath<span style="color: #009900;">&#40;</span>startPoint<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; initLastFound<span style="color: #009900;">&#40;</span>startPoint<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; findNextPoint<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>endReached<span style="color: #009900;">&#40;</span>endPoint<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; addBestCandidateToPath<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; findNextPoint<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> path<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> findNextPoint<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; PositionDelta bestDelta <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; GeoPoint bestPoint <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>GeoPoint point <span style="color: #339933;">:</span> geoPointSet<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; PositionDelta delta <span style="color: #339933;">=</span> buildDelta<span style="color: #009900;">&#40;</span>lastFoundPoint, point<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>delta.<span style="color: #006633;">isBetterCandidate</span><span style="color: #009900;">&#40;</span>bestDelta<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bestPoint <span style="color: #339933;">=</span> point<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bestDelta <span style="color: #339933;">=</span> delta<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; lastFoundPoint <span style="color: #339933;">=</span> bestPoint<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> addBestCandidateToPath<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; path.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>lastFoundPoint<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Pour consulter l&#8217;intégralité du code, il faut aller lire les <a href="http://code.google.com/p/excilys/source/browse/projects/PolygonRefactoring/tags/article_refactoring/#article_refactoring/src/com/excilys/blog/refactoring/refactored">sources</a> <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>Remarquez l&#8217;absence de <strong>commentaires</strong>. Les <strong>noms </strong>de méthodes et de variables permettent d&#8217;<strong>exprimer</strong> ce que fait le code.</p>
<p>Le plus souvent, les commentaires au sein du code sont <strong>une  erreur</strong>. Ils n&#8217;évoluent jamais à la même vitesse que le code.</p>
<p>Quand  vous lisez un code complexe, plutôt que d&#8217;y insérer des<strong> commentaires</strong> qui expriment ce qu&#8217;il fait (et donc <strong>dupliquer l&#8217;information</strong>), il est préférable de le modifier pour rendre son fonctionnement <strong>explicite</strong>.</p>
<p>Par ailleurs, cet algorithme n&#8217;est certainement pas la meilleure manière de calculer une enveloppe convexe. J&#8217;ai souhaité en conserver le  principe général plutôt que de changer d&#8217;implémentation, pour que  l&#8217;exemple garde tout son sens. Si vous avez mieux, lâchez vos coms <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  !</p>
<h3>Conclusion</h3>
<p>À travers cette mise en pratique, j&#8217;espère vous avoir donné un aperçu des différents mécanismes à mettre en œuvre au cours d&#8217;un refactoring.</p>
<p>C&#8217;est loin d&#8217;être facile, et cela demande du <a href="http://agilesoftwaredevelopment.com/xp/values/courage">courage</a>. Il est bien plus aisé de laisser le code se délabrer.</p>
<p>Quand un collaborateur vous balance &#8220;<em>touche pas, ça marche</em>&#8220;, le code est probablement pourri. Mais ce n&#8217;est pas parce que c&#8217;est un projet <strong>poubelle</strong> qu&#8217;il ne faut rien faire, au contraire ! Pensez juste à prendre des <a href="http://www.touilleur-express.fr/2010/07/28/jouez-les-docteurs-love-apprenez-a-nettoyer-du-vieux-code/">radiographies</a> du patient <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  .</p>
<p>Je me suis largement inspiré de <a href="http://www.amazon.fr/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/">Clean Code</a> pour écrire cet article. Ce livre a remis en question mes habitudes de développement, j&#8217;ai pris une claque. À mettre entre toutes les mains !</p>
<img src="http://feeds.feedburner.com/~r/blogexcilyscom/~4/7ZOMujiQB1w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.excilys.com/2010/08/03/refactoring-par-la-pratique/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://blog.excilys.com/2010/08/03/refactoring-par-la-pratique/</feedburner:origLink></item>
		<item>
		<title>Oubliez les redéploiements grâce à JRebel</title>
		<link>http://feedproxy.google.com/~r/blogexcilyscom/~3/aSDOZsFqkys/</link>
		<comments>http://blog.excilys.com/2010/07/15/oubliez-les-redeploiements-grace-a-jrebel/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 21:10:39 +0000</pubDate>
		<dc:creator>Bastien JANSEN</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[classloader]]></category>
		<category><![CDATA[déploiement]]></category>
		<category><![CDATA[hotswapping]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jrebel]]></category>
		<category><![CDATA[JVM]]></category>
		<category><![CDATA[performances]]></category>

		<guid isPermaLink="false">http://blog.excilys.com/?p=2430</guid>
		<description><![CDATA[Introduction
Comme une grande partie des lecteurs de ce blog, vous avez certainement déjà travaillé sur des applications web Java EE de taille variable, sur lesquelles vous avez fait un nombre indécent de redéploiements à chaque fois que vous vouliez valider des modifications fraîchement apportées. Puis vous avez dû découvrir que depuis Java 1.4, la JVM [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>Comme une grande partie des lecteurs de ce blog, vous avez certainement déjà travaillé sur des applications web Java EE de taille variable, sur lesquelles vous avez fait un nombre indécent de redéploiements à chaque fois que vous vouliez valider des modifications fraîchement apportées. Puis vous avez dû découvrir que depuis Java 1.4, la JVM permet de faire du <a href="http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/guide/jpda/enhancements.html#hotswap"><em>Hotswap </em> en mode debug</a>, c&#8217;est-à-dire de remplacer du code à la volée au runtime.<br />
<span id="more-2430"></span><br />
C&#8217;est bien, mais il y a quand même des limitations : on ne peut que modifier le corps d&#8217;une méthode déjà existante, si l&#8217;on ajoute une méthode ou une classe elle ne sera pas prise en compte. Idem pour les membres statiques, les annotation ou encore les fichiers properties accédés via un ResourceBundle.</p>
<p>C&#8217;est pour pallier ces manques que la société Estonienne <a href="http://www.zeroturnaround.com/">ZeroTurnaround</a> a développé <a href="http://www.zeroturnaround.com/jrebel/">JRebel</a>, un outil destiné aux développeurs désirant <strong>gagner du temps</strong> dans leur cycle de développement.</p>
<h3>JRebel, c&#8217;est quoi ?</h3>
<p>Comme l&#8217;explique en anglais un <a href="http://www.zeroturnaround.com/blog/reloading_java_classes_401_hotswap_jrebel/">article du blog de ZeroTurnaround</a>, JRebel est principalement un agent à installer dans votre serveur d&#8217;applications, qui va réagir à des mises à jour de classes, ou plus généralement de ressources composant votre application. À l&#8217;aide d&#8217;un fichier de configuration rebel.xml, vous allez spécifier une liste de ressources à surveiller, par exemple des répertoires contenant des JAR et des fichiers properties. Lors du déploiement de votre application, l&#8217;agent va utiliser cette configuration pour scruter des changements dans ces répertoires (un timestamp plus récent).</p>
<p>Pour appliquer ces changements, JRebel introduit un <a href="http://en.wikipedia.org/wiki/Java_Classloader">classloader</a> qui va se charger de détecter le chargement des classes, pour ensuite générer des classes anonymes grâce la génération de bytecode <em>on-the-fly</em>. À chaque modification d&#8217;une classe dans votre IDE, une nouvelle classe anonyme sera générée pour modifier le comportement de la classe originale, grâce à un savant mélange de JIT et de magie noire (l&#8217;article ne rentre pas trop dans les détails du fonctionnement interne, secret de fabrication oblige puisque c&#8217;est un outil commercial).</p>
<div id="attachment_2431" class="wp-caption aligncenter" style="width: 560px"><a href="http://blog.excilys.com/wp-content/uploads/2010/07/jrebel-agent.png"><img class="size-full wp-image-2431" title="Fonctionnement de l'agent" src="http://blog.excilys.com/wp-content/uploads/2010/07/jrebel-agent.png" alt="" width="550" height="329" /></a><p class="wp-caption-text">Fonctionnement de l&#39;agent (image issue du site de ZeroTurnaround)</p></div>
<p>Au final, la perte de performances est minimisée comparé au gain de temps entrainé par le fait que l&#8217;on ne soit pas obligé de redéployer toutes les 5 minutes. Que vous utilisiez des JAR, des WAR, du Spring, Struts, Wicket ou autre Hibernate, sur des serveurs Glassfish, Websphere, JBoss, ou encore Weblogic, il y a de fortes chances que <a href="http://www.zeroturnaround.com/jrebel/comparison/">JRebel le supporte</a> de base ou via des plugins. Et si votre framework favori n&#8217;est pas dans la liste, une API vous permet de <a href="http://www.zeroturnaround.com/jrebel/plugins/">développer votre propre plugin</a>.</p>
<h3>Mise en pratique</h3>
<h4>Cas simple : modification d&#8217;une méthode</h4>
<p>Nous allons maintenant tester JRebel sur une application web type HelloWorld. Comme je l&#8217;ai déjà dit plus haut, c&#8217;est un outil commercial mais une version d&#8217;évaluation de 30 jours est <a href="http://www.zeroturnaround.com/jrebel/current/">disponible sur le site</a>. L&#8217;installation est très bien expliquée par un wizard prenant en compte votre IDE et votre serveur, donc je ne m&#8217;attarderai pas sur le sujet.</p>
<p>J&#8217;ai choisi d&#8217;utiliser Netbeans et Glassfish pour déployer une application toute simple : une calculatrice. Je dispose d&#8217;une servlet nommée Calculator, chargée de faire des additions et des soustractions :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Calculator <span style="color: #000000; font-weight: bold;">extends</span> HttpServlet <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> processRequest<span style="color: #009900;">&#40;</span>HttpServletRequest request, HttpServletResponse response<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throws</span> ServletException, <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; response.<span style="color: #006633;">setContentType</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;text/html;charset=UTF-8&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">String</span> operation <span style="color: #339933;">=</span> request.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;operation&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">Integer</span> result <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>operation <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">&amp;&amp;</span> request.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">&amp;&amp;</span> request.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;b&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">Integer</span> a <span style="color: #339933;">=</span> <span style="color: #003399;">Integer</span>.<span style="color: #006633;">valueOf</span><span style="color: #009900;">&#40;</span>request.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">Integer</span> b <span style="color: #339933;">=</span> <span style="color: #003399;">Integer</span>.<span style="color: #006633;">valueOf</span><span style="color: #009900;">&#40;</span>request.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;b&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>operation.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;add&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result <span style="color: #339933;">=</span> a <span style="color: #339933;">+</span> b<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>operation.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;sub&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result <span style="color: #339933;">=</span> a <span style="color: #339933;">-</span> b<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IllegalArgumentException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Don't fool me, use correct parameters: a, b and operation!!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">PrintWriter</span> out <span style="color: #339933;">=</span> response.<span style="color: #006633;">getWriter</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; out.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;The result is &quot;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>result <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #0000ff;">&quot;unpredictable&quot;</span> <span style="color: #339933;">:</span> result<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">finally</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; out.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Attention, Netbeans est malin et par défaut fait du <em>deploy-on-save</em>. Il faut donc désactiver l&#8217;option dans les propriétés du projet pour ne pas interférer avec JRebel.</p>
<p>La configuration du fichier rebel.xml, à placer dans WEB-INF/classes/, va ressembler à ceci :</p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;application</span></span><br />
<span style="color: #009900;"> &nbsp;<span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br />
<span style="color: #009900;"> &nbsp;<span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://www.zeroturnaround.com&quot;</span></span><br />
<span style="color: #009900;"> &nbsp;<span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://www.zeroturnaround.com http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classpath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dir</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;D:\NetBeansProjects\WebApplication1\build\web\WEB-INF\classes&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classpath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/application<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
</pre>
<p>On demande donc de prendre à chaud tout ce qui va changer dans le répertoire où sont placées les classes compilées.</p>
<p>Dans les logs du démarrage de glassfish, on peut ainsi voir :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">INFO: JRebel: Directory 'D:\NetBeansProjects\WebApplication1\build\web\WEB-INF\classes' will be monitored for changes.</div></td></tr></tbody></table></div>
<p>Procédons à une modification mineure du corps de la méthode <code class="codecolorer java default"><span class="java">processRequest<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></span></code> :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// On a changé le message affiché</span><br />
out.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Congratulations, the result is &quot;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>result <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #0000ff;">&quot;unpredictable&quot;</span> <span style="color: #339933;">:</span> result<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
</pre>
<p>Après compilation du fichier et rafraîchissement de la page dans le navigateur, on obtient immédiatement le changement :</p>
<div id="attachment_2435" class="wp-caption aligncenter" style="width: 655px"><a href="http://blog.excilys.com/wp-content/uploads/2010/07/hotswap.png"><img class="size-full wp-image-2435" title="hotswap" src="http://blog.excilys.com/wp-content/uploads/2010/07/hotswap.png" alt="" width="645" /></a><p class="wp-caption-text">Modification à chaud du corps d&#39;une méthode</p></div>
<p>Dans le cas présent, JRebel a fait l&#8217;équivalent du hotswapping standard de la JVM, mais sans avoir besoin d&#8217;être en mode debug.</p>
<h4>Un cran au-dessus : ajout de méthodes / classes</h4>
<p>Amusons-nous maintenant dans le domaine de l&#8217;inédit. Pour satisfaire notre envie de <a href="http://en.wikipedia.org/wiki/Separation_of_concerns"><em>separation of concerns</em></a>, on va externaliser le code métier dans une classe différente de la servlet :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Calc <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #003399;">Integer</span> add<span style="color: #009900;">&#40;</span><span style="color: #003399;">Integer</span> a, <span style="color: #003399;">Integer</span> b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> a <span style="color: #339933;">+</span> b<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #003399;">Integer</span> substract<span style="color: #009900;">&#40;</span><span style="color: #003399;">Integer</span> a, <span style="color: #003399;">Integer</span> b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> a <span style="color: #339933;">-</span> b <span style="color: #339933;">+</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// et dans la servlet :</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>operation.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;add&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; result <span style="color: #339933;">=</span> Calc.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>a, b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>operation.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;sub&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; result <span style="color: #339933;">=</span> Calc.<span style="color: #006633;">substract</span><span style="color: #009900;">&#40;</span>a, b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>On enregistre, on compile et on vérifie : la nouvelle classe (et indirectement de nouvelles méthodes) a été prise en compte automatiquement (pour en être sûr, on peut bidouiller l&#8217;addition pour qu&#8217;elle calcule a + b + 1 par exemple).</p>
<h4>Et les ressources ?</h4>
<p>Pour l&#8217;instant nous nous sommes contentés de modifier du code Java. Et si on essayait des fichiers properties ? Ca tombe bien, notre client vient justement de nous faire part de son vœu de pouvoir internationaliser le nom des opérations <em>add</em> et <em>sub</em> !</p>
<p>On va donc utiliser un <a href="http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/api/java/util/PropertyResourceBundle.html">ResourceBundle</a> :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>operation.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">ResourceBundle</span>.<span style="color: #006633;">getBundle</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;operations&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getString</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;add&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; result <span style="color: #339933;">=</span> Calc.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>a, b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>operation.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">ResourceBundle</span>.<span style="color: #006633;">getBundle</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;operations&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getString</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;sub&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; result <span style="color: #339933;">=</span> Calc.<span style="color: #006633;">substract</span><span style="color: #009900;">&#40;</span>a, b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<div class="codecolorer-container properties default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="properties codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;"># operations.properties</span><br />
<span style="color: #000080; font-weight:bold;">add</span> <span style="color: #000000;">=</span><span style="color: #008000; font-weight:bold;"> add</span><br />
<span style="color: #000080; font-weight:bold;">sub</span> <span style="color: #000000;">=</span><span style="color: #008000; font-weight:bold;"> sub</span></div></td></tr></tbody></table></div>
<p>On compile, on rafraîchit et là&#8230; c&#8217;est le drame !</p>
<pre>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">WARNING: StandardWrapperValve[Calculator]: PWC1406: Servlet.service() for servlet Calculator threw exception<br />
java.util.MissingResourceException: Can't find bundle for base name operations, locale en_GB<br />
&nbsp; &nbsp; &nbsp; &nbsp; at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:1521)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1260)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at java.util.ResourceBundle.getBundle(ResourceBundle.java:715)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at com.excilys.blog.jrebel.servlet.Calculator$$M$6334694c.processRequest(Calculator.java:38)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at com.excilys.blog.jrebel.servlet.Calculator$$A$6334694c.processRequest()&lt;generated&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; at com.excilys.blog.jrebel.servlet.Calculator.processRequest(Calculator.java:51)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at com.excilys.blog.jrebel.servlet.Calculator$$M$6334694c.doGet(Calculator.java:65)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at com.excilys.blog.jrebel.servlet.Calculator$$A$6334694c.doGet()&lt;generated&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; at com.excilys.blog.jrebel.servlet.Calculator.doGet(Calculator.java:65)</div></td></tr></tbody></table></div>
</pre>
<p>Et oui, les ressources sont cherchées dans le répertoire <code class="codecolorer text default"><span class="text">build\web\WEB-INF\classes\operations.properties</span></code>, hors comme on ne fait pas de build complet le fichier properties qu&#8217;on vient de créer ne s&#8217;y trouve pas encore <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Pas de souci, on le copie à la main (ou on fait un build complet, mais c&#8217;est plus long), et là ça marche ! Remarquez au passage que les classes mentionnées dans la stacktrace ont des noms un peu bizarres, certaines sont marquées <code class="codecolorer text default"><span class="text">&lt;generated&gt;</span></code> : cela correspond à ce que j&#8217;ai expliqué plus haut au sujet du fonctionnement interne de JRebel.</p>
<p>Zut, le client vient de décider qu&#8217;à présent, on aura des noms d&#8217;opérations en français. Pas de souci, on a juste à changer notre properties (celui dans le dossier <code class="codecolorer text default"><span class="text">build/</span></code>, sauf si vous décidez de monitorer également la version dans <code class="codecolorer text default"><span class="text">src/</span></code>), et les changements sont pris à chaud :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">INFO: JRebel: Reloading class 'com.excilys.blog.jrebel.servlet.Calculator'.<br />
INFO: JRebel: Reloaded bundle file:/D:/NetBeansProjects/WebApplication1/build/web/WEB-INF/classes/operations.properties</div></td></tr></tbody></table></div>
<h4>Encore une <em>killer-feature</em> : le plugin Spring</h4>
<p>Comme évoqué dans les principes de fonctionnement, JRebel supporte entre autres les changements à chaud de configuration du framework Spring grâce à un plugin dédié. Voyons un peu comment ça fonctionne. Après avoir supprimé le <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">static</span></span></code> des méthodes de la classe <code class="codecolorer java default"><span class="java">Calc</span></code>, j&#8217;ai décidé d&#8217;en faire un bean Spring :</p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;beans</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/beans&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br />
<br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; <span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/beans</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;calc&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.excilys.blog.jrebel.Calc&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.springframework.web.context.support.ServletContextAttributeExporter&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;attributes&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;map<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;entry</span> <span style="color: #000066;">key</span>=<span style="color: #ff0000;">&quot;calcBean&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">bean</span>=<span style="color: #ff0000;">&quot;calc&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/entry<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/map<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/beans<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
</pre>
<p>Ce bean est ensuite <a href="http://andykayley.blogspot.com/2007/11/how-to-inject-spring-beans-into.html">récupéré dans la servlet</a> de la manière suivante :</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Calc calc <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Calc<span style="color: #009900;">&#41;</span>getServletContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;calcBean&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #666666; font-style: italic;">//...</span><br />
result <span style="color: #339933;">=</span> calc.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>a, b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Je vous passe la configuration du <code class="codecolorer text default"><span class="text">web.xml</span></code>, elle est tout à fait standard. Cependant JRebel ne permet pas de prendre à chaud les changements dans <code class="codecolorer text default"><span class="text">web.xml</span></code>, on va donc être obligés de redéployer notre application (mais on le fera plus après, promis <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' /> ). Redéploiement et rafraîchissement de la page web, ouf, tout fonctionne normalement.</p>
<p>Pour tester le plugin Spring, on va introduire une modification mineure : renommer l&#8217;attribut du contexte permettant de récupérer bean.</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// dans applicationContext.xml, on change la balise &lt;entry&gt; en</span><br />
<span style="color: #666666; font-style: italic;">// &nbsp; &lt;entry key=&quot;myCalcBean&quot;&gt;</span><br />
<span style="color: #666666; font-style: italic;">// et dans le code Java, on a donc :</span><br />
Calc calc <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Calc<span style="color: #009900;">&#41;</span>getServletContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;myCalcBean&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Compilation, rafraîchissement (en ces temps de fortes chaleurs&#8230;), applaudissements. On vient de bénéficier d&#8217;une modification de la configuration de Spring sans avoir à redéployer !</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">INFO: JRebel: Reloading class 'com.excilys.blog.jrebel.servlet.Calculator'.<br />
INFO: JRebel-Spring: Reloading Spring bean definitions in 'file:/D:/NetBeansProjects/WebApplication1/build/web/WEB-INF/classes/applicationContext.xml'.<br />
INFO: Loading XML bean definitions from file [D:\NetBeansProjects\WebApplication1\build\web\WEB-INF\classes\applicationContext.xml]<br />
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4cea16: defining beans [org.springframework.web.context.support.ServletContextAttributeExporter#0,calc,org.springframework.web.context.support.ServletContextAttributeExporter#1]; root of factory hierarchy<br />
INFO: Exported ServletContext attribute with name 'myCalcBean'</div></td></tr></tbody></table></div>
<h3>Conclusion</h3>
<p>Résumons un peu. Avec un seul déploiement (parce que je m&#8217;y suis pris trop tard, avouons-le), on a réussi à prendre en compte immédiatement des modifications de méthodes, des ajouts des classes, des modifications des fichiers properties accédés par un ResourceBundle et surtout des fichiers de configuration de framework (Spring dans cet exemple). Ça en jette, non ? Tout ça pour pas un rond si vos développement durent moins de 30 jours, sinon il faudra débourser une <a href="http://sales.zeroturnaround.com/">somme relativement modeste</a> (189$ pour une licence annuelle standard).</p>
<p><div id="attachment_2495" class="wp-caption alignright" style="width: 210px"><a href="http://blog.excilys.com/wp-content/uploads/2010/08/lerebelle2.jpg"><img src="http://blog.excilys.com/wp-content/uploads/2010/08/lerebelle2.jpg" alt="" title="Le Rebelle" width="200" height="274" class="size-full wp-image-2495" /></a><p class="wp-caption-text">Le Rebelle aussi utilise JRebel.</p></div><br />
Sachez que je n&#8217;ai couvert qu&#8217;une petite partie de tout ce que JRebel sait faire, histoire de garder un article d&#8217;une taille raisonnable. Je vous laisse le soin d&#8217;explorer et de tester à fond cette petite merveille pour développeurs !</p>
<p>Petit plus pour les décideurs, à chaque démarrage du serveur, JRebel affiche des estimations sur le précieux temps qu&#8217;il vous a fait gagner, de manière à mesurer les gains qu&#8217;apportent de tels outils :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Over the last 3 days JRebel prevented<br />
at least 18 redeploys/restarts saving you about 0.7 hours.</div></td></tr></tbody></table></div>
<h3>Pour aller plus loin</h3>
<ul>
<li><a href="http://www.zeroturnaround.com/jrebel/">Site de JRebel</a></li>
<li><a href="http://jetoile.blogspot.com/2010/02/jrebel-ou-comment-accelerer-le_24.html">JRebel ou comment accélérer le développement</a></li>
<li><a href="http://javaposse.com/java_posse_306_j_rebel_interview">Java Posse #306 &#8211; JRebel Interview</a></li>
<li><a href="http://www.zeroturnaround.com/jrebel/configuration/maven/">Youpi ! Ca marche aussi avec Maven</a></li>
<li><a href="http://www.zeroturnaround.com/scala-license/">Enfin une bonne raison de se mettre à Scala</a> <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
</ul>
<img src="http://feeds.feedburner.com/~r/blogexcilyscom/~4/aSDOZsFqkys" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.excilys.com/2010/07/15/oubliez-les-redeploiements-grace-a-jrebel/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.excilys.com/2010/07/15/oubliez-les-redeploiements-grace-a-jrebel/</feedburner:origLink></item>
		<item>
		<title>Illuminez vos logs dans Eclipse</title>
		<link>http://feedproxy.google.com/~r/blogexcilyscom/~3/y0heob9aTfU/</link>
		<comments>http://blog.excilys.com/2010/06/30/illuminez-vos-logs-dans-eclipse/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 08:30:15 +0000</pubDate>
		<dc:creator>Bastien JANSEN</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[coloration]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[outils]]></category>
		<category><![CDATA[performances]]></category>

		<guid isPermaLink="false">http://blog.excilys.com/?p=2405</guid>
		<description><![CDATA[Introduction
Comme beaucoup de lecteurs de ce blog, j&#8217;utilise un IDE au quotidien. Sur mon projet actuel, c&#8217;est Eclipse combiné à un serveur Websphere. Pour des raisons pratiques, je fais un tail -f des logs du serveur dans la console d&#8217;Eclipse, et qui dit serveur d&#8217;applications Java + logs en niveau DEBUG dit énormément d&#8217;informations à [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>Comme beaucoup de lecteurs de ce blog, j&#8217;utilise un IDE au quotidien. Sur mon projet actuel, c&#8217;est Eclipse combiné à un serveur Websphere. Pour des raisons pratiques, je fais un <code class="codecolorer text default"><span class="text">tail -f</span></code> des logs du serveur dans la console d&#8217;Eclipse, et qui dit serveur d&#8217;applications Java + logs en niveau <code class="codecolorer text default"><span class="text">DEBUG</span></code> dit énormément d&#8217;informations à scanner pour trouver ce qui m&#8217;intéresse réellement (quelques Mo de logs par jour !).<span id="more-2405"></span></p>
<h3>Colore tes logs !</h3>
<p>La solution que j&#8217;ai retenue pour facilement m&#8217;y retrouver, c&#8217;est <a href="http://marian.musgit.com/projects_grepconsole.php">Grep Console</a>. Ce plugin pour Eclipse permet de colorier dans une console certaines parties de texte qui matchent une ou plusieurs expressions régulières. Par exemple, les <code class="codecolorer text default"><span class="text">WARN</span></code> en orange et les <code class="codecolorer text default"><span class="text">ERROR</span></code> en blanc sur fond rouge.</p>
<div id="attachment_2408" class="wp-caption aligncenter" style="width: 615px"><a href="http://blog.excilys.com/wp-content/uploads/2010/08/screenshot.png"><img class="size-full wp-image-2408 " title="Configuration de Grep Console" src="http://blog.excilys.com/wp-content/uploads/2010/08/screenshot.png" alt="Configuration de Grep Console" width="605" height="386" /></a><p class="wp-caption-text">Les boites de dialogues ultra-simples de configuration de Grep Console</p></div>
<p>On voit dans la fenêtre de gauche toutes les expressions régulières que j&#8217;ai choisies de matcher et dans celle de droite la configuration de l&#8217;une d&#8217;entre elles : définition de la regexp, choix des couleurs d&#8217;arrière-plan ou d&#8217;avant-plan pour la ligne entière ou pour les <em>groupes</em> capturés par des parenthèses (cependant on ne peut pas imbriquer les parenthèses).</p>
<p>Voici le résultat dans la console d&#8217;Eclipse :</p>
<p style="text-align: center;"><a href="http://blog.excilys.com/wp-content/uploads/2010/08/screenshot2.png"><img class="aligncenter size-full wp-image-2410" title="Aperçu de la coloration des logs" src="http://blog.excilys.com/wp-content/uploads/2010/08/screenshot2.png" alt="Aperçu de la coloration des logs" width="880" height="302" /></a></p>
<h3>Conclusion</h3>
<p>Simple mais efficace, je vous conseille vivement d&#8217;installer ce plugin qui permet de gagner du temps si vous avez des logs sous les yeux à longueur de journée ! Rendez-vous sur l&#8217;<em>update site </em><a href="http://eclipse.musgit.com">http://eclipse.musgit.com</a>. Seul bémol, je n&#8217;ai pas encore trouvé d&#8217;astuce pour colorier d&#8217;anciens logs dans d&#8217;autres fichiers (une sorte de <code class="codecolorer text default"><span class="text">less</span></code> coloré). Si vous avez un outil qui fait ce genre de choses, je suis preneur <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p style="text-align: center;">
<img src="http://feeds.feedburner.com/~r/blogexcilyscom/~4/y0heob9aTfU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.excilys.com/2010/06/30/illuminez-vos-logs-dans-eclipse/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.excilys.com/2010/06/30/illuminez-vos-logs-dans-eclipse/</feedburner:origLink></item>
		<item>
		<title>Dé-switcher n’est pas jouer</title>
		<link>http://feedproxy.google.com/~r/blogexcilyscom/~3/aw_n_vwndYM/</link>
		<comments>http://blog.excilys.com/2010/06/25/de-switcher-nest-pas-jouer/#comments</comments>
		<pubDate>Thu, 24 Jun 2010 22:20:38 +0000</pubDate>
		<dc:creator>Pierre-Yves RICAU</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[bonnes pratiques]]></category>
		<category><![CDATA[clean-code]]></category>
		<category><![CDATA[code propre]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[switch]]></category>

		<guid isPermaLink="false">http://blog.excilys.com/?p=2375</guid>
		<description><![CDATA[Amis utilisateurs de Checkstyle, avez-vous remarqué que les switch sont des sources inépuisables de complexité cyclomatique ? Sans parler de leur équivalent pour les objets, les if &#40;&#41; &#123;&#125; else if &#40;&#41;&#123;&#125; else if &#40;&#41;&#123;&#125; else if &#40;&#41;&#123;&#125; à répétition.
Parmi les reproches récurrents faits aux switch, il y a le fait qu&#8217;ils ne respectent pas [...]]]></description>
			<content:encoded><![CDATA[<p>Amis utilisateurs de <a href="http://checkstyle.sourceforge.net/">Checkstyle</a>, avez-vous remarqué que les <a href="http://java.sun.com/docs/books/tutorial/java/nutsandbolts/switch.html">switch</a> sont des sources inépuisables de <a href="http://fr.wikipedia.org/wiki/Nombre_cyclomatique">complexité cyclomatique</a> ? Sans parler de leur équivalent pour les objets, les <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span></span></code> à répétition.</p>
<p>Parmi les reproches récurrents faits aux <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">switch</span></span></code>, il y a le fait qu&#8217;ils ne respectent pas le principe <a href="http://fr.wikipedia.org/wiki/Principe_ouvert/ferm%C3%A9">Ouvert/Fermé</a>. A chaque ajout de nouvelles valeurs, il faut modifier tous les <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">switch</span></span></code> qui les manipulent.</p>
<p><span id="more-2375"></span><br />
Il est toujours possible de se passer d&#8217;un switch. Un moyen simple est d&#8217;utiliser une <a href="http://java.sun.com/javase/6/docs/api/java/util/Map.html">Map</a>. Ainsi, le code suivant :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getMessage<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> messageCode<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003399;">String</span> message<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">switch</span> <span style="color: #009900;">&#40;</span>messageCode<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #cc66cc;">42</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; message <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;the Answer to the Ultimate Question of Life, the Universe, and Everything.&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #cc66cc;">13</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; message <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Good luck!&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// [...]</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">default</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IllegalArgumentException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Unknown code&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> message<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>devient :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> Map<span style="color: #339933;">&lt;</span>Integer, String<span style="color: #339933;">&gt;</span> &nbsp;messagesByCode <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HashMap<span style="color: #339933;">&lt;</span>Integer, String<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> initMessagesByCode<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; messagesByCode.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span>, <span style="color: #0000ff;">&quot;the Answer to the Ultimate Question of Life, the Universe, and Everything.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; messagesByCode.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">13</span>, <span style="color: #0000ff;">&quot;Good luck!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// [...]</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getMessage<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> messageCode<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003399;">String</span> message <span style="color: #339933;">=</span> messagesByCode.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>messageCode<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>message <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IllegalArgumentException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Unknown code&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> message<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Cela fonctionne aussi si le <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">switch</span></span></code> (ou les if/else) contient du code à exécuter qui varie suivant les cas. Ainsi :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doAction<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> action<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;syso&quot;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>action<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Yeah&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;syserr&quot;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>action<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">System</span>.<span style="color: #006633;">err</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Yahoo&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #666666; font-style: italic;">// [...]</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IllegalArgumentException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Unknown action&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #666666; font-style: italic;">// [...]</span><br />
doAction<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;syso&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
</pre>
<p>devient (j&#8217;en conviens, des <a href="http://en.wikipedia.org/wiki/First-class_function">first-class functions</a> simplifieraient le code) :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> Map<span style="color: #339933;">&lt;</span>String, Runnable<span style="color: #339933;">&gt;</span> actionsByName <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HashMap<span style="color: #339933;">&lt;</span>String, Runnable<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> initActionsByName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; actionsByName.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;syso&quot;</span>, <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Runnable</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Yeah&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; actionsByName.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;syserr&quot;</span>, <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Runnable</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">System</span>.<span style="color: #006633;">err</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Yahoo&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doAction<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> action<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003399;">Runnable</span> runnable <span style="color: #339933;">=</span> actionsByName.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>action<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>runnable <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IllegalArgumentException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Unknown action&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; runnable.<span style="color: #006633;">run</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #666666; font-style: italic;">// [...]</span><br />
doAction<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;syso&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
</pre>
<p>Clairement, si ce type de modification permet de se passer de <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">switch</span></span></code> sans modifier la signature des méthodes, elle n&#8217;est pas idéale. Une bien meilleure option ici serait de se souvenir que Java est un langage <a href="http://java.sun.com/docs/books/tutorial/java/concepts/object.html">orienté Objet</a>, et utiliser le polymorphisme pour implémenter le <a href="http://en.wikipedia.org/wiki/Strategy_pattern">pattern strategy</a> <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> <span style="color: #003399;">Action</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">void</span> doAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #666666; font-style: italic;">// [...]</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doAction<span style="color: #009900;">&#40;</span><span style="color: #003399;">Action</span> action<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; action.<span style="color: #006633;">doAction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #666666; font-style: italic;">// [...]</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Syso <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #003399;">Action</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Yeah&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #666666; font-style: italic;">// [...]</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Syserr <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #003399;">Action</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">System</span>.<span style="color: #006633;">err</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Yahoo&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #666666; font-style: italic;">// [...]</span><br />
doAction<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Syso<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
</pre>
<p>On pourrait enfin utiliser les possibilités offertes par les <a href="http://weblogs.java.net/blog/2005/01/31/implementing-state-design-pattern-using-enums">enum Java</a> :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">enum</span> ActionEnum <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #003399;">Action</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; SYSO <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Yeah&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span>,<br />
&nbsp; &nbsp; SYSERR <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">System</span>.<span style="color: #006633;">err</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Yahoo&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #666666; font-style: italic;">// [...]</span><br />
doAction<span style="color: #009900;">&#40;</span>ActionEnum.<span style="color: #006633;">SYSO</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
</pre>
<p>J&#8217;espère que ce court article vous aura convaincu qu&#8217;il est tout à fait possible de se passer des <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">switch</span></span></code>. Un code comprenant des <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">switch</span></span></code> et autres <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span></span></code> est en général tout sauf simple et maintenable.<br />
Dans <a href="http://www.amazon.fr/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/">Clean Code</a>, <a href="http://www.objectmentor.com/omTeam/martin_r.html">Uncle Bob Martin</a> conseille d&#8217;ailleurs d&#8217;encapsuler le code lié aux <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">switch</span></span></code> dans des <a href="http://fr.wikipedia.org/wiki/Fabrique_abstraite_%28patron_de_conception%29">fabriques abstraites</a>, afin de ne pas les laisser polluer le reste du code.</p>
<p><strong>Edit</strong> (03/08/2010) : dans le même domaine, vous pouvez lire cet article sur le <a href="http://blog.excilys.com/2010/08/03/refactoring-par-la-pratique/">Refactoring par la pratique</a>.</p>
<img src="http://feeds.feedburner.com/~r/blogexcilyscom/~4/aw_n_vwndYM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.excilys.com/2010/06/25/de-switcher-nest-pas-jouer/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		<feedburner:origLink>http://blog.excilys.com/2010/06/25/de-switcher-nest-pas-jouer/</feedburner:origLink></item>
		<item>
		<title>De l’audit avec hibernate</title>
		<link>http://feedproxy.google.com/~r/blogexcilyscom/~3/M3CCpUE0jYk/</link>
		<comments>http://blog.excilys.com/2010/06/16/de-laudit-avec-hibernate/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 14:10:06 +0000</pubDate>
		<dc:creator>Laurent STEMMER</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[audit]]></category>
		<category><![CDATA[back-dynamite]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.excilys.com/?p=2159</guid>
		<description><![CDATA[Nous allons parler de l’interface Interceptor et de son utilisation dans le but d’auditer du code.]]></description>
			<content:encoded><![CDATA[<p>Hello my dear students*,</p>
<blockquote><p>Pouvez-vous me faire un rapport sur tous les ajouts et les modifications qui ont été faits sur la table des factures en production depuis 5 ans ? </p></blockquote>
<p>Hibernate a vraiment pensé à tout, aujourd’hui nous allons parler de l’interface Interceptor et de son utilisation dans le but de faciliter <a href="http://en.wikipedia.org/wiki/Information_technology_audit">l&#8217;audit du système d&#8217;information</a> (ici la base de données).</p>
<div><span id="more-2159"></span></div>
<h3>L&#8217;interceptor hibernate</h3>
<p>Cette interface fournit des méthodes qui interceptent différents événements de la session comme la suppression, l&#8217;ajout ou la modification de données.</p>
<p>Vous pouvez implémenter <a href="http://docs.jboss.org/hibernate/stable/core/api/org/hibernate/Interceptor.html">Interceptor </a>directement, ou mieux : étendre <a href="http://docs.jboss.org/hibernate/stable/core/api/org/hibernate/EmptyInterceptor.html">EmptyInterceptor </a>et n&#8217;en surcharger que les méthodes qui vous intéressent. Voici un exemple :</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000; font-style: italic; font-weight: bold;">/**<br />
&nbsp;* Audite l'insertion et la mise à jour des entités implémentant l'interface {@link ExcilysAuditable}.<br />
&nbsp;* &lt;p&gt;<br />
&nbsp;*<br />
&nbsp;* Le choix de la méthode d'audit est laissé à la discretion du codeur.<br />
&nbsp;*<br />
&nbsp;*/</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ExcilysAuditLogInterceptor <span style="color: #000000; font-weight: bold;">extends</span> EmptyInterceptor <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> onSave<span style="color: #009900;">&#40;</span><span style="color: #003399;">Object</span> entity,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #003399;">Serializable</span> id,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #003399;">Object</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> state,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> propertyNames,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Type<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> types<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throws</span> CallbackException <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>entity <span style="color: #000000; font-weight: bold;">instanceof</span> ExcilysAuditable<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// loguez de la manière qui vous plaira que l'entité à été insérée</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// parce que l'on a pas modifié l'entité impliquée dans le callback</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> onFlushDirty<span style="color: #009900;">&#40;</span><span style="color: #003399;">Object</span> entity,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">Serializable</span> id,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">Object</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> currentState,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">Object</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> previousState,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> propertyNames,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Type<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> types<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throws</span> CallbackException <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>entity <span style="color: #000000; font-weight: bold;">instanceof</span> ExcilysAuditable<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// loguez de la manière qui vous plaira que l'entité à été modifiée</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// parce que l'on a pas modifié l'entité impliquée dans le callback</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Attention cependant, auditer les insertions et les mises à jour peut ralentir votre application !</p>
<p>Pour rendre effective l&#8217;utilisation par Hibernate de votre Interceptor, passez-le en paramètre lors de la  création de la session (sf correspond à la SessionFactory) :</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Session session <span style="color: #339933;">=</span> sf.<span style="color: #006633;">openSession</span><span style="color: #009900;">&#40;</span> <span style="color: #000000; font-weight: bold;">new</span> ExcilysAuditLogInterceptor<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<h3>Interceptors versus Triggers</h3>
<p>Pour se rappeler de ce qu&#8217;est un Trigger SGBD, lire <a href="http://sqlpro.developpez.com/cours/sqlaz/techniques/#L3">cet article</a> !</p>
<p>Les triggers</p>
<div>
<ul>
<li>sont rapides</li>
<li>seront aussi appelés si vous faites des insert en base directement (on est donc sûr d&#8217;auditer tout changement)</li>
</ul>
</div>
<p>Les Interceptors</p>
<div>
<ul>
<li>ne dépendent pas du type de base de données (par exemple <a href="http://access.developpez.com/faq/?page=General#Triggers">Access ne gère pas les triggers</a>)</li>
<li>permettent de récupérer des données système comme la locale ou l&#8217;utilisateur de la session</li>
</ul>
</div>
<h3>Conclusion</h3>
<p>Voilà, encore une façon supplémentaire de tracer ce que font vos utilisateurs. N&#8217;oubliez pas que les erreurs sont plus faciles à mettre sur le dos d&#8217;un autre quand <a href="http://fr.wikipedia.org/wiki/Pr%C3%A9somption_d'innocence">il existe des preuves</a> qui vont dans votre sens <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<blockquote><p>Pouvez-vous me faire un rapport sur tous les ajouts et les modifications qui ont été faits sur la table des factures en production depuis 5 ans ? </p></blockquote>
<blockquote><p>Mais bien sûr je n&#8217;ai qu&#8217;à faire <strong>haut haut bas bas gauche droite gauche droite b a</strong>, et le tour est joué ! Et en plus, je vous ai fait un café !</p></blockquote>
<blockquote><p>Bravo, j&#8217;ai pu démasquer des centaines de fraudes grâce à vous ! Vous êtes trop puissant Black Dynamite !</p></blockquote>
<div id="attachment_2232" class="wp-caption aligncenter" style="width: 212px"><a href="http://blog.excilys.com/wp-content/uploads/2010/06/black_dynamite_ver3.jpg"><img src="http://blog.excilys.com/wp-content/uploads/2010/06/black_dynamite_ver3-202x300.jpg" alt="" width="202" height="300" class="size-medium wp-image-2232" /></a><p class="wp-caption-text">Cuz there aint no hope for dudes who deal dope!</p></div>
<p>* référence à <a href="http://en.wikipedia.org/wiki/Marina_Orlova">Marina Orlova</a>, qui m&#8217;a appris que l&#8217;etymologie pouvait être sexy.</p>
<img src="http://feeds.feedburner.com/~r/blogexcilyscom/~4/M3CCpUE0jYk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.excilys.com/2010/06/16/de-laudit-avec-hibernate/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.excilys.com/2010/06/16/de-laudit-avec-hibernate/</feedburner:origLink></item>
		<item>
		<title>Un peu de LOLcode…</title>
		<link>http://feedproxy.google.com/~r/blogexcilyscom/~3/4dQl3q60IJw/</link>
		<comments>http://blog.excilys.com/2010/06/14/un-peu-de-lolcode/#comments</comments>
		<pubDate>Mon, 14 Jun 2010 16:05:34 +0000</pubDate>
		<dc:creator>Bastien JANSEN</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[entreprise]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[lol]]></category>

		<guid isPermaLink="false">http://blog.excilys.com/?p=1997</guid>
		<description><![CDATA[Introduction
Dans cet article, je vous propose quelque chose d&#8217;assez différent des sujets abordés habituellement. En lisant du code écrit par d&#8217;autres développeurs, je suis resté perplexe sur quelques méthodes. Après les avoir relues quelques fois, la façon d&#8217;écrire m&#8217;a fait sourire, comme quoi d&#8217;un développeur à l&#8217;autre les méthodes de réflexion et d&#8217;écriture de code [...]]]></description>
			<content:encoded><![CDATA[<h4>Introduction</h4>
<p>Dans cet article, je vous propose quelque chose d&#8217;assez différent des sujets abordés habituellement. En lisant du code écrit par d&#8217;autres développeurs, je suis resté perplexe sur quelques méthodes. Après les avoir relues quelques fois, la façon d&#8217;écrire m&#8217;a fait sourire, comme quoi d&#8217;un développeur à l&#8217;autre les méthodes de réflexion et d&#8217;écriture de code varient fortement.</p>
<p>Je vous propose donc quelques extraits de code méritant le détour, ça donne des snippets assez drôles, cherchez l&#8217;erreur !<br />
<span id="more-1997"></span></p>
<h4>Continue comme ça</h4>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Object</span> i <span style="color: #339933;">:</span> list<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>condition<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; doSomeStuff<span style="color: #009900;">&#40;</span>someArguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">continue</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; doSomeStuff<span style="color: #009900;">&#40;</span>someOtherArguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p><code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">continue</span></span></code>, what <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">else</span></span></code>? <em>(ce jeu de mots est © <a href="http://blog.excilys.com/author/pyricau/">Pierre-Yves Ricau</a>)</em></p>
<h4>Tu peux pas test</h4>
<p>Contexte : imaginez une méthode <code class="codecolorer java default"><span class="java">initialize<span style="color: #009900;">&#40;</span>java.<span style="color: #006633;">util</span>.<span style="color: #003399;">Properties</span><span style="color: #009900;">&#41;</span></span></code> qui s&#8217;attend à la présence d&#8217;une propriété <code class="codecolorer java default"><span class="java">MY_PROPERTY</span></code> pour l&#8217;utiliser lors de l&#8217;initialisation d&#8217;un objet :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> initialize<span style="color: #009900;">&#40;</span><span style="color: #003399;">Properties</span> props<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>props.<span style="color: #006633;">getProperty</span><span style="color: #009900;">&#40;</span>MY_PROPERTY<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// ici on utilise cette propriété...</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Le test unitaire est tout naturellement :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> testNullProperty<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003399;">Properties</span> properties <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Properties</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; assertNotNull<span style="color: #009900;">&#40;</span>properties<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; assertNull<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;property must be null&quot;</span>, properties.<span style="color: #006633;">getProperty</span><span style="color: #009900;">&#40;</span>MY_PROPERTY<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; myClassInstance.<span style="color: #006633;">initialize</span><span style="color: #009900;">&#40;</span>properties<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Pour résumer, on teste si une instance fraichement créée est non-nulle, tout en vérifiant qu&#8217;elle ne contient pas encore la propriété&#8230; Quant à la méthode <code class="codecolorer java default"><span class="java">initialize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></span></code> qui est censée faire l&#8217;objet du test, certes on l&#8217;appelle mais on ne fait aucune vérification dessus. Bon, après tout le test passe, c&#8217;est le principal non ?<br />
Ce test n&#8217;est d&#8217;ailleurs pas isolé, plusieurs autres tests vérifient de la même façon la non-présence dans <code class="codecolorer java default"><span class="java">properties</span></code> d&#8217;autres propriétés utilisées dans <code class="codecolorer java default"><span class="java">initialize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></span></code> <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' /> .</p>
<h4>Double fail inversé</h4>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">myVar <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>myMap <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #0000ff;">&quot;&quot;</span> <span style="color: #339933;">:</span> myMap.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>myField<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
</pre>
<p>Non seulement on n&#8217;a pas la valeur attendue, mais en plus on aura forcément une NullPointerException si <code class="codecolorer java default"><span class="java">myMap</span></code> vaut null <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> .</p>
<h4>True or false?</h4>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> superComplexLogic<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">boolean</span> value<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">boolean</span> ret<span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>getValue2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> value<span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>getValue2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>value<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> ret<span style="color: #339933;">=</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> ret<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Pourquoi faire simple ? Un <code class="codecolorer java default"><span class="java"><span style="color: #000000; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span>getValue2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></span></code> aurait été tellement banal !</p>
<h4>TODO != Tout doux</h4>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// TODO en lot 8</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;TODO&quot;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;TODO1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// ...</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Sympathique cette façon d&#8217;éviter que du code soit executé, non ? <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </p>
<h4>100% de couverture de tests !</h4>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">enum</span> MyEnum <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; MY_CONSTANT<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;O&quot;</span><span style="color: #009900;">&#41;</span>,<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//...</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Et le test associé :</span><br />
@Test<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> testMyConstant<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; assertEquals<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;O&quot;</span>, MyEnum.<span style="color: #006633;">MY_CONSTANT</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Au moins, si on fait une faute de frappe en écrivant l&#8217;enum, ce test le verra tout de suite <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h4>L&#8217;opération a échoué avec succès !</h4>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">//succes - Recuperer la liste à réemettre.</span><br />
logger.<span style="color: #006633;">logError</span><span style="color: #009900;">&#40;</span>ServiceLogKeys.<span style="color: #006633;">SUCCESS_CODE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
</pre>
<h4>Conclusion</h4>
<p>J&#8217;espère que ce petit moment de détente vous a plus, si c&#8217;est le cas nous allons essayer de motiver les troupes d&#8217;Excilys pour publier des articles collaboratifs de ce genre de temps en temps. Si vous avez aussi des exemples de LOLcode, n&#8217;hésitez pas à vous lacher dans les comms (attention aux clauses de non divulgation tout de même) <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<img src="http://feeds.feedburner.com/~r/blogexcilyscom/~4/4dQl3q60IJw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.excilys.com/2010/06/14/un-peu-de-lolcode/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.excilys.com/2010/06/14/un-peu-de-lolcode/</feedburner:origLink></item>
		<item>
		<title>Il y a toujours de la lumière chez Liferay Portal</title>
		<link>http://feedproxy.google.com/~r/blogexcilyscom/~3/zE6t5DcI3EA/</link>
		<comments>http://blog.excilys.com/2010/05/31/il-y-a-toujours-de-la-lumiere-chez-liferay-portal/#comments</comments>
		<pubDate>Mon, 31 May 2010 21:59:15 +0000</pubDate>
		<dc:creator>Alexis THOMAS</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[Actualité]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[Liferay]]></category>
		<category><![CDATA[Liferay IDE]]></category>
		<category><![CDATA[Liferay Portal]]></category>
		<category><![CDATA[Portal]]></category>

		<guid isPermaLink="false">http://blog.excilys.com/?p=1924</guid>
		<description><![CDATA[Ce billet va s&#8217;attacher à reprendre les actualités récentes et importantes liées au portail Liferay qui ont marqué le début de l&#8217;année 2010. Mon constat étant que ces dernières sont passées assez inaperçues pour nombre d&#8217;entre nous et ont été peu ou pas commentées, en français notamment.
Par ordre chronologique :

février 2010 : version 6 de [...]]]></description>
			<content:encoded><![CDATA[<p>Ce billet va s&#8217;attacher à reprendre les actualités récentes et importantes liées au portail <a href="http://www.liferay.com/" target="_blank"><strong>Liferay</strong></a> qui ont marqué le début de l&#8217;année 2010. Mon constat étant que ces dernières sont passées assez inaperçues pour nombre d&#8217;entre nous et ont été peu ou pas commentées, en français notamment.</p>
<p>Par ordre chronologique :</p>
<ul>
<li>février 2010 : version 6 de Liferay Portal en approche</li>
<li>avril 2010 : Liferay Portal fête ses 10 ans</li>
<li>mai 2010 : sortie théorique de Liferay IDE 1.0</li>
</ul>
<div id="attachment_1933" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.excilys.com/wp-content/uploads/2010/05/Liferay_logo-large.png"><img class="size-medium wp-image-1933" src="http://blog.excilys.com/wp-content/uploads/2010/05/Liferay_logo-large-300x86.png" alt="Logo Liferay large" width="300" height="86" /></a><p class="wp-caption-text">Liferay pour la vie</p></div>
<p><span id="more-1924"></span></p>
<h3>Liferay Portal 6 annoncé</h3>
<p>En février dernier, Paul Hinz a dévoilé l&#8217;information que la prochaine version serait numérotée 6 et non pas 5.3 comme nous avions pu le penser. En effet, depuis quelques temps déjà, Liferay Portal 5.2 (plus précisément 5.2.3) est la dernière version officielle. La numérotation en 5.3 était par exemple utilisée dans le <a href="http://issues.liferay.com/secure/Dashboard.jspa" target="_blank">Jira de Liferay</a> pour désigner la version suivante corrigeant une anomalie. Depuis la numérotation dans Jira a bien sûr été corrigée <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Ce choix vient du fait qu&#8217;après avoir revu l&#8217;ensemble des fonctionnalités et améliorations futures prévues dans la stratégie de développement du portail, il a été décidé que la <em>release</em> suivante profiterait d&#8217;un changement de numéro de version majeur.</p>
<p>Cette version avait pour nom de code <em>Bunyan</em> en interne et sera donc officiellement <strong>Liferay Portal 6</strong>.</p>
<p>L&#8217;annonce officielle postée sur le blog de Liferay mentionnait les éléments suivants comme étant majeurs et à surveiller :</p>
<table style="margin-left: 12%; width: 75%;">
<tbody>
<tr>
<td>Gestion des contenus et connaissances</p>
<ul>
<li>Partage de contenu</li>
<li>Tags et catégories</li>
<li>Attributs <em>customs</em></li>
<li>Rapports d&#8217;utilisation</li>
<li>Vue de différences</li>
<li>Gestion des droits</li>
<li>Plugin de Base de connaissance</li>
<li>Workflow intégré</li>
</ul>
</td>
<td>Gestion de la plateforme</p>
<ul>
<li>Monitoring de performance des portlets</li>
<li>Audit</li>
<li>Analyse et suivi</li>
<li>Liaison de <em>clusters</em></li>
<li>Partitionnement horizontal (<a href="http://en.wikipedia.org/wiki/Shard_%28database_architecture%29" target="_blank"><em>sharding</em></a>)</li>
</ul>
</td>
</tr>
<tr>
<td>Extensions et intégration</p>
<ul>
<li>Framework de gestion des droits</li>
<li>Framework <a href="http://alloy.liferay.com/" target="_blank">Alloy UI</a></li>
<li>Moteur de règles de personnalisation</li>
<li>Framework de scripting</li>
<li>Accès aux services Liferay depuis les portlets</li>
<li>Intégration avec des systèmes externes</li>
</ul>
</td>
<td>UI et utilisation</p>
<ul>
<li>Navigation simplifiée</li>
<li>UI améliorée pour la gestion de documents</li>
<li>Création de page en 1 clic</li>
<li>Création de communauté en 1 clic</li>
<li>Édition de contenu simple</li>
</ul>
</td>
</tr>
</tbody>
</table>
<p>Parmi ces éléments, on peut noter l&#8217;amélioration de l&#8217;intégration des <em>workflows</em> et pour ce faire nous devrions bénéficier du support de <a href="http://www.jboss.org/jbpm/" target="_blank">jBPM</a>. Concernant la bibliothèque de documents, celle-ci devrait pouvoir s&#8217;intégrer avec <a href="http://www.emc.com/domains/documentum/index.htm" target="_blank">Documentum</a>, <a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=cmis" target="_blank">CMIS</a> et <a href="http://sharepoint.microsoft.com" target="_blank">Sharepoint</a> par exemple.</p>
<p><strong>Liferay Portal 6</strong> va se baser sur des technologies JEE courantes et chercher à ajouter ou simplement améliorer leur prise en charge, au cœur du portail ou/et pour l&#8217;ouvrir aux systèmes externes :</p>
<ul>
<li><a href="http://fr.wikipedia.org/wiki/Java_Persistence_API" target="_blank">JPA</a> et <a href="http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/" target="_blank">JMX</a> seront intégrés, <a href="http://oauth.net/" target="_blank">OAuth</a> sera amélioré, le support de <a href="http://maven.apache.org/" target="_blank">Maven</a> devrait être presque natif</li>
<li>les plugins pourront exposer des web services en <a href="http://www.json.org/" target="_blank">JSON</a> et <a href="http://www.w3.org/TR/soap/" target="_blank">SOAP</a></li>
<li>intégration avec <a href="http://fr.openoffice.org/" target="_blank">OpenOffice</a>, <a href="http://www.google.com/apps/" target="_blank">Google Apps</a>, <a href="http://jasperreports.sourceforge.net/" target="_blank">Jasper</a>, <a href="http://www.eclipse.org/birt/" target="_blank">BIRT</a></li>
<li>possibilité de changer de moteur de BPM (utiliser <a href="http://www.intalio.com/" target="_blank">Intalio</a> à la place de jBPM par exemple)</li>
<li>intégration avec <a href="http://www.netvibes.com/" target="_blank">NetVibes</a>, <a href="http://www.opensocial.org/" target="_blank">OpenSocial</a>, SEO, <a href="http://caldav.calconnect.org/" target="_blank">CalDAV</a>, <a href="http://www.salesforce.com/fr/" target="_blank">SalesForce</a>, <a href="http://vaadin.com/" target="_blank">Vaadin</a></li>
<li>formulaires et listes dynamiques</li>
<li>gestionnaires de tâches et de contacts</li>
</ul>
<h4>Premiers retours sur Liferay Portal 6 <em>preview</em> / RC</h4>
<p>Dans un premier temps, cette version 6 n&#8217;a été mise à disposition que par l&#8217;intermédiaire d&#8217;une <em>preview</em>. Le site officiel n&#8217;en faisait pas mention, mais SouceForge et les <em>Nightly Builds</em> commençaient à diffuser ces premières ébauches à tester.</p>
<p>Deux mois plus tard, en avril, c&#8217;est au tour de la <em>Release Candidate</em> d&#8217;avoir été officialisée. Elle incluait de nombreux correctifs et la plupart des portlets finales qui manquaient dans la <em>preview</em>, dont la traditionnelle application de démarrage <em>7Cogs</em>.</p>
<p>Depuis la sortie de la version RC de Liferay Portal 6, la page de téléchargement habituelle prépare les utilisateurs au changement à venir. En effet, vous pouvez toujours choisir de récupérer un <em>bundle</em> basé sur Liferay Portal 5.2.3 CE, mais vous pouvez également vous essayer à la RC. Une liste déroulante proposant les <em>bundles</em> mis à jour pointe ainsi sur la dernière version officielle de Liferay Portal 6.</p>
<p>La première version RC numérotée 6.0.1 semble souffrir d&#8217;un nombre important de retours d&#8217;anomalies. Ceci explique surement en partie le retard qui commence à grandir pour la <em>release</em> finale et aussi la longue durée depuis laquelle nous attendons la sortie de la RC2. Cette deuxième RC devrait débloquer la situation, espérons-le.</p>
<p>Notons quand même que la <em>roadmap</em> initiale prévoyait une sortie finale de Liferay Portal 6 entre février et avril 2010 pour respectivement les versions Community Edition et Enterprise Edition. Il est maintenant souhaitable que toutes ces corrections de bugs qui se sont ajoutées permettent d&#8217;obtenir un portail avec une meilleure finition comparé aux versions précédentes <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<h3>Liferay Portal a 10 ans</h3>
<p>Le 23 avril dernier, Liferay nous a fait cadeau d&#8217;une belle newsletter intitulée  &#8216;10 Years of Open Source: Liferay in 2010&#8242;. En effet, la société s&#8217;est construite sur son portail et a su évoluer en trouvant les partenaires de poids nécessaires. Maintenant elle continue son chemin en profitant de son expérience.</p>
<p>Je vous retranscris ici le contenu de leur message :</p>
<blockquote><p>Cette année marque le 10ème anniversaire de Liferay Portal. Brian Chan a démarré le développement en 2000 et Liferay est très rapidement devenu la plateforme de premier choix pour construire des applications d&#8217;entreprises dynamiques et efficaces. Avec 3 millions de téléchargements, 250 000 déploiements et une communauté active d&#8217;environ 30 000 personnes, Liferay a connu une croissance explosive dans sa 11ème année.</p>
<div id="attachment_1932" class="wp-caption alignright" style="width: 140px"><a href="http://blog.excilys.com/wp-content/uploads/2010/05/Liferay_logo.png"><img class="size-full wp-image-1932" src="http://blog.excilys.com/wp-content/uploads/2010/05/Liferay_logo.png" alt="Logo Liferay" width="130" height="131" /></a><p class="wp-caption-text">Un éclat éternel ?</p></div>
<p>Cette année marque aussi le 6ème anniversaire de la société, basée sur l&#8217;open source, et Liferay célèbre plusieurs jalons :</p>
<ul>
<li>Des centaines de sociétés clientes comme Cisco Systems, Electronic Arts et Société Générale</li>
<li>Plus de 60 partenaires dans le réseau international</li>
<li>Reconnu deux ans de suite comme Visionnaire dans le Gartner’s Magic Quadrant</li>
<li>Forte croissance des revenus et du support présent dans les bureaux d&#8217;Amérique du nord, d&#8217;Europe, du Brésil, d&#8217;Inde et de Chine.</li>
</ul>
<p>Merci pour votre soutien et au plaisir de travailler à vos côtés en 2010 !</p></blockquote>
<p>Si nous reprenons un peu l&#8217;historique, voici ce qu&#8217;on pourrait obtenir :</p>
<ul>
<li>2000 : premiers développements par Brian Chan, pour proposer un portail d&#8217;entreprise pour les organismes à but non lucratif</li>
<li>2006 : création de la société Liferay Inc., et de la filiale Liferay GmbH en Allemagne</li>
<li>2007 : ouverture de nouveaux bureaux en Asie et en Espagne</li>
<li>2009 : création d&#8217;un bureau en Inde</li>
</ul>
<p>La croissance de Liferay s&#8217;est faite aussi grâce à des partenariats :</p>
<ul>
<li>ICEsoft Technologies, en juillet 2007, pour incorporer la technologie <a href="http://fr.wikipedia.org/wiki/Asynchronous_JavaScript_and_XML" target="_blank">Ajax</a></li>
<li>janvier 2008 : recrutement du <em>lead engineer</em> de <a href="http://jqueryui.com/" target="_blank">jQuery UI</a></li>
<li>Sun Microsystems, en mai 2008, pour un accord d&#8217;échange technologique</li>
<li>2009 : Liferay intègre le comité de spécification de <a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=cmis" target="_blank">Oasis  CMIS</a></li>
<li>IT Mill Ltd., en octobre 2009, pour travailler autour de leur librairie de UI nommée <a href="http://vaadin.com/home" target="_blank">Vaadin</a></li>
</ul>
<h3>Liferay IDE 1.0 en vue</h3>
<p>Gregory Amerson a rejoint l&#8217;équipe Liferay à Los Angeles en février 2010. Son expérience de <em>senior developer</em> sur MyEclipse l&#8217;a propulsé au poste de <em>software engineer</em> en charge du développement de l&#8217;outillage autour du portail et plus spécifiquement basé sur Eclipse. La première release de Liferay IDE devait se faire suivant un plan de 2 mois aboutissant sur la publication de la version 1.0.</p>
<div id="attachment_2063" class="wp-caption alignright" style="width: 154px"><a href="http://blog.excilys.com/wp-content/uploads/2010/05/eclipse_pos_logo_fc_sm.jpg"><img class="size-full wp-image-2063" src="http://blog.excilys.com/wp-content/uploads/2010/05/eclipse_pos_logo_fc_sm.jpg" alt="Logo Eclipse" width="144" height="144" /></a><p class="wp-caption-text">Le jour et la nuit</p></div>
<p>Depuis avril, le développement suit son court et les premiers <em>builds</em> sont testables pour les plus motivés. Six vidéos de démonstration ont été publiées et présentent certaines des fonctionnalités qui seront présentes de façon certaine dans la version finale :</p>
<ol>
<li><a href="http://www.liferay.com/c/document_library/get_file?p_l_id=4616001&amp;groupId=4615837&amp;folderId=4933105&amp;name=DLFE-40604.swf">Create new plug-in project</a></li>
<li><a href="http://www.liferay.com/c/document_library/get_file?p_l_id=4616001&amp;groupId=4615837&amp;folderId=4933105&amp;name=DLFE-40609.swf">Portlet Project Deployment</a></li>
<li><a href="http://www.liferay.com/c/document_library/get_file?p_l_id=4616001&amp;groupId=4615837&amp;folderId=4933105&amp;name=DLFE-40608.swf">New Portlet Wizard</a></li>
<li><a href="http://www.liferay.com/c/document_library/get_file?p_l_id=4616001&amp;groupId=4615837&amp;folderId=4933105&amp;name=DLFE-40607.swf">New Hook Wizard</a></li>
<li><a href="http://www.liferay.com/c/document_library/get_file?p_l_id=4616001&amp;groupId=4615837&amp;folderId=4933105&amp;name=DLFE-40605.swf">More Hook Wizard</a></li>
<li><a href="http://www.liferay.com/c/document_library/get_file?p_l_id=4616001&amp;groupId=4615837&amp;folderId=4933105&amp;name=DLFE-40606.swf">Plug-in Package Editor</a></li>
</ol>
<p>La date du 12 mai avait été donnée pour la sortie de la version 1.0 finale. Plus de 2 semaines plus tard, force est de constater que nous devons encore patienter un peu.</p>
<h4>Dans les cartons de Liferay IDE</h4>
<p>Liferay IDE 1.0 proposera la gestion du serveur Liferay Portal, la création d&#8217;un projet, des éditeurs pour les descripteurs spécifiques et des <em>wizards</em> de création d&#8217;artefact de portail, le tout conforme à l&#8217;état de l&#8217;art des pratiques que chaque développeur utilisant Liferay doit répéter sans cesse dans son environnement de développement personnel.</p>
<p>La page du wiki officiel qui présente Liferay IDE nous donne quelques éléments de détails :</p>
<blockquote><p>Le but de Liferay IDE est de fournir l&#8217;outillage basé sur Eclipse le plus abouti qui soit pour l&#8217;environnement de développement de Liferay Portal à destination des <span style="text-decoration: underline;">versions 6.0 et supérieur</span>.</p>
<p>Liferay IDE viendra complémenter l&#8217;existant d&#8217;une façon très similaire à ce que fait SpringSource Tool Suite pour la plateforme Spring.</p>
<p>Livrables produits sans aucune différence de fonctionnalité :</p>
<ol>
<li>Liferay IDE All-in-one bundle (incluant par exemple un JRE, un pack Liferay, la JavaDoc, des packages complémentaires de sources du portail, etc.)</li>
<li>Liferay IDE plugins bundle pour Eclipse Galileo JEE (3.5.x)</li>
<li>Update site pour Eclipse Galileo</li>
</ol>
<p>Priorités :</p>
<ol>
<li>Pouvoir démarrer facilement sur la plateforme Liferay</li>
<li>Simplifier ou automatiser les tâches fréquentes et ennuyeuses</li>
<li>Intégrer le Liferay Plugins SDK</li>
<li>Développer, déployer et débugger les plugins Liferay facilement</li>
</ol>
<p>Disponible entre autres pour la version 1.0 :</p>
<ul>
<li>Importer, créer et travailler sur des projets Eclipse de plugins Liferay directement</li>
<li>Prendre en charge le Liferay Portal depuis l&#8217;IDE</li>
<li>Nouveaux wizards pour automatiser les créations répétitives de contenus</li>
<li>Assistance à la saisie</li>
<li>Templates personnalisés</li>
</ul>
<p>Prévu pour les versions suivantes notamment :</p>
<ul>
<li>Gestion avancée du Plugins SDK et du bundle Liferay Portal utilisés</li>
<li>Projets pour les Theme et Layout Template</li>
<li>Éditeurs améliorés et validation des structures saisies</li>
<li>Gestion automatique des dépendances</li>
<li>Log d&#8217;activité du serveur</li>
</ul>
</blockquote>
<h4>Premiers retours sur Liferay IDE 1.0 preview</h4>
<p>La communauté a fait part de son intérêt pour cet IDE qui était très attendu. Pour la version 1.0, Eclipse est la priorité absolue et donc seul ciblé. Par la suite, les autres IDE devraient pouvoir recevoir une prise en charge par le biais de plugins officiels. Un travail notable d&#8217;intégration pour NetBeans ayant déjà été entrepris (cf. <a href="http://contrib.netbeans.org/portalpack/" target="_blank">Portal Pack</a>), ce dernier devrait être géré rapidement. Quant à IntelliJ IDEA, il sera aussi supporté à l&#8217;avenir.</p>
<p>L&#8217;équipe reste à l&#8217;écoute des besoins des utilisateurs et par exemple, se montre intéressée lorsqu&#8217;est évoqué le &#8220;besoin&#8221; de gérer la prise en compte native de JSF 2.0 pour les portlets directement depuis l&#8217;IDE. D&#8217;autres idées émises concernent par exemple la gestion directe par l&#8217;IDE d&#8217;artefacts Maven spécifiques à Liferay pour donner suite au <a href="http://www.liferay.com/web/mika.koivisto/blog/-/blogs/liferay-maven-sdk" target="_blank">Liferay Maven SDK</a>.</p>
<p>Pour tester la version de preview, Gregory Amerson a mis en place un <em>update site</em> à ajouter dans votre Eclipse :</p>
<p style="text-align: center;"><span style="text-decoration: underline;">http://gregamerson.com/liferay-ide/updates/latest/</span></p>
<p>Fin mai, seule la version 6.0.1 du portail (Liferay Portal 6 RC 1) est officiellement disponible au téléchargement depuis <a href="http://sourceforge.net/projects/lportal/" target="_blank">SourceForge</a>. Ceci pose problème si vous tentez d&#8217;utiliser la version <em>preview</em> de Liferay IDE qui demande que votre portail soit au minimum en version 6.0.2. La seule solution semble donc être de se tourner vers les <em>Nightly Builds</em> du portail en attendant que la RC 2 soit publiée officiellement. L&#8217;url pour récupérer ces builds est :</p>
<p style="text-align: center;"><span style="text-decoration: underline;">http://releases.liferay.com/portal/nightly/</span></p>
<p>D&#8217;après Gregory Amerson, le <em>build</em> Liferay Portal 6 RC 2 sera publié d&#8217;ici peu et Liferay IDE 1.0 devrait suivre de près. Plus que quelques jours à attendre donc !? <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Conclusion</h3>
<p>Voici donc quelques actualités majeures dans le &#8220;petit&#8221; monde de <strong>Liferay</strong> qui méritaient qu&#8217;on s&#8217;y attarde un peu. Et puisque les sujets sont encore bien chauds, nous devrions voir arriver très rapidement les annonces des <em>releases</em> finales. Et encore d&#8217;autres surprises peut être ? <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Pour terminer et ne faire que les mentionner, <a href="http://www.jboss.org/gatein" target="_blank">GateIn</a> et <a href="http://www.exoplatform.com/" target="_blank">eXo Platform</a> sont les premiers à faire beaucoup parler d&#8217;eux ces derniers temps parmi les éditeurs de portails, donc <a href="http://www.liferay.com/" target="_blank"><strong>Liferay</strong></a> a tout intérêt à se montrer entreprenant pour ne pas se faire distancer !</p>
<h3>Références</h3>
<ul>
<li>Billets de Paul Hinz : <a href="http://www.liferay.com/web/paul.hinz/blog" target="_blank">http://www.liferay.com/web/paul.hinz/blog</a></li>
<li>Billets de Brian Chan : <a href="http://www.liferay.com/web/brian.chan/blog" target="_blank">http://www.liferay.com/web/brian.chan/blog</a></li>
<li>Wiki Liferay : <a href="http://www.liferay.com/community/wiki/" target="_blank">http://www.liferay.com/community/wiki/</a></li>
<li>Billets de Gregory Amerson : <a href="http://www.liferay.com/web/gregory.amerson/blog" target="_blank">http://www.liferay.com/web/gregory.amerson/blog</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/blogexcilyscom/~4/zE6t5DcI3EA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.excilys.com/2010/05/31/il-y-a-toujours-de-la-lumiere-chez-liferay-portal/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.excilys.com/2010/05/31/il-y-a-toujours-de-la-lumiere-chez-liferay-portal/</feedburner:origLink></item>
		<item>
		<title>Blazé du remoting ? Utilisez Spring-flex !</title>
		<link>http://feedproxy.google.com/~r/blogexcilyscom/~3/a8fLHyENToU/</link>
		<comments>http://blog.excilys.com/2010/05/19/blaze-du-remoting-utilisez-spring-flex/#comments</comments>
		<pubDate>Wed, 19 May 2010 08:00:20 +0000</pubDate>
		<dc:creator>Bastien JANSEN</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[blazeds]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[remoting]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://blog.excilys.com/?p=1110</guid>
		<description><![CDATA[Introduction

Suite à la mise en place d&#8217;un environnement de développement Flex en Open Source, je vous propose aujourd&#8217;hui de simplifier l&#8217;utilisation de BlazeDS grâce à Spring BlazeDS Integration (Spring-flex).
La description suivante, traduite de l&#8217;introduction faite sur le site officiel, résume bien les buts recherchés :
 
Spring BlazeDS Integration est une réponse à une demande de [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p><a href="http://www.springsource.org"><img class="size-full wp-image-1989 alignright" title="Spring" src="http://blog.excilys.com/wp-content/uploads/2010/01/spring1.png" alt="Logo Spring" width="118" height="52" /></a></p>
<p>Suite à la mise en place d&#8217;un <a href="http://blog.excilys.com/2010/01/20/open-source-flex-development-stack/">environnement de développement Flex</a> en Open Source, je vous propose aujourd&#8217;hui de simplifier l&#8217;utilisation de <a href="http://opensource.adobe.com/wiki/display/blazeds/BlazeDS/">BlazeDS</a> grâce à <a href="http://www.springsource.org/spring-flex">Spring BlazeDS Integration</a> (Spring-flex).</p>
<p>La description suivante, traduite de l&#8217;introduction faite sur le site officiel, résume bien les buts recherchés :</p>
<blockquote><p><em> </em></p>
<p>Spring BlazeDS Integration est une réponse à une demande de la communauté qui souhaitait avoir une solution pour construire des <strong>RIA propulsées par Spring</strong>, utilisant Adobe <strong>Flex </strong>pour la technologie client. [...] Bien qu&#8217;il était possible d&#8217;utiliser BlazeDS pour se connecter à des services gérés par Spring, ce n&#8217;était pas réalisable de manière &#8220;naturelle&#8221; pour un développeur Spring, nécessitant d&#8217;avoir à maintenir une <strong>configuration XML BlazeDS séparée</strong>. Spring BlazeDS Integration change tout cela en transformant le <strong>MessageBroker</strong> de BlazeDS en un objet géré par Spring, ouvrant des perspectives vers une <strong>intégration plus complète</strong> qui suit le &#8220;Spring way&#8221;.</p></blockquote>
<p><em> </em></p>
<p>Dans cet article, nous allons voir les principes de base de Spring BlazeDS Integration : <strong>configuration</strong>, <strong>exposition </strong>des services et <strong>consommation </strong>par un client Flex. Un projet est réalisé en parallèle pour illustrer la théorie ; les exemples de code suivant en sont tirés. Le <a href="http://blog.excilys.com/wp-content/uploads/2010/01/Spring-BlazeDS-integration.zip">code source final</a> est disponible à la fin de cet article.  Si vous n&#8217;avez pas encore lu le <a href="http://blog.excilys.com/2010/01/20/open-source-flex-development-stack/">précédent article</a>, je vous invite à le faire car il explique de nombreuses notions qui seront réutilisées ici.<span id="more-1110"></span></p>
<h3>Mise en place de la webapp</h3>
<h4>C&#8217;est bien Mave(i)n(e)&#8230;</h4>
<p>Une fois n&#8217;est pas coutume, nous allons utiliser Maven 2 pour créer le squelette d&#8217;application web qui sera utilisée par le client Flex :</p>
<pre>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mvn archetype:create -DgroupId=com.excilys.java -DartifactId=SimpleSpringFlex -DarchetypeArtifactId=maven-archetype-webapp</div></td></tr></tbody></table></div>
</pre>
<h4>Retour aux sources</h4>
<p>Ajoutons tout de suite les bonnes dépendances vers Spring-Flex :</p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.springframework.flex<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>spring-flex<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0.1.RELEASE<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
</pre>
<p>Commençons par adapter le descripteur de déploiement <strong>web.xml <span style="font-weight: normal;">:</span></strong></p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;web-app</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;3.0&quot;</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://java.sun.com/xml/ns/javaee&quot;</span> <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span> <span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;display-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Simple Flex Remoting with Spring-Flex<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/display-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>dispatcher<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.springframework.web.servlet.DispatcherServlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;load-on-startup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/load-on-startup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/messagebroker/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>dispatcher<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/web-app<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
</pre>
<p>Comme dans l&#8217;article précédent, nous mappons le pattern <strong>/messagebroker/*</strong> sur une servlet, sauf que maintenant ce n&#8217;est plus une <strong>MessageBrokerServlet</strong>, mais une <strong>DispatcherServlet </strong>Spring. Le travail de Spring va donc commencer ici. Profitons de la convention du framework qui ira chercher par défaut la configuration du conteneur Spring associée à cette servlet dans le fichier <strong>WEB-INF/dispatcher-servlet.xml</strong> :</p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;beans</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/beans&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">xmlns:flex</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/flex&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;http://www.springframework.org/schema/beans</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;http://www.springframework.org/schema/beans/spring-beans-2.5.xsd</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;http://www.springframework.org/schema/flex</span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;http://www.springframework.org/schema/flex/spring-flex-1.0.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;flex:messagebroker</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/beans<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
</pre>
<p>Par rapport à une configuration classique, notez l&#8217;inclusion de l&#8217;espace de nommage <strong>&#8220;flex&#8221;</strong>, qui va rendre disponible la balise <strong>messagebroker</strong>. Celle-ci va nous permettre de créer un <em>managed bean</em> de type <strong>MessageBroker</strong>, qui va gérer les flux AMF (là aussi on profite de la configuration par défaut du bean, notamment pour le nom du fichier de configuration <strong>services-config.xml</strong>).</p>
<div id="attachment_1990" class="wp-caption aligncenter" style="width: 220px"><img class="size-medium wp-image-1990  " title="Mr Bean" src="http://blog.excilys.com/wp-content/uploads/2010/01/bean-210x300.jpg" alt="" width="210" height="300" /><p class="wp-caption-text">Exemple de Bean non managé par Spring</p></div>
<h3>Création des services</h3>
<p>Dans cette partie, nous allons faire du Java &#8220;classique&#8221;. Le but de la webapp créée au tout début de l&#8217;article est d&#8217;exposer des services à notre client Flex. Créons donc notre service, qui va permettre d&#8217;additioner deux nombres (calcul nécessitant de grosses ressources type cluster <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ) :</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.excilys.java.springflex.service</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> MathService <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> add<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> a, <span style="color: #000066; font-weight: bold;">int</span> b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">double</span><span style="color: #009900;">&#41;</span>a<span style="color: #339933;">/</span>b<span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">double</span><span style="color: #009900;">&#41;</span>b<span style="color: #339933;">/</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span><span style="color: #009900;">&#41;</span><span style="color: #003399;">Math</span>.<span style="color: #006633;">sqrt</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>b <span style="color: #339933;">&lt;&lt;</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Addition standard.</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<h4><strong>Exposition (gratuite) de services</strong></h4>
<p>Il nous reste maintenant à rendre ce service accessible à notre application Flex. En utilisant BlazeDS directement, il faudrait ajouter chaque service dans le fichier <strong>WEB-INF/flex/services-config.xml</strong>. Avec Spring-flex, nous allons pouvoir minimiser cette configuration :</p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;services-config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;services<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;default-channels<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;channel</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;my-amf&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/default-channels<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/services<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;channels<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;channel-definition</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;my-amf&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;endpoint</span> <span style="color: #000066;">url</span>=<span style="color: #ff0000;">&quot;http://{server.name}:{server.port}/{context.root}/messagebroker/amf&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/channel-definition<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/channels<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/services-config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
</pre>
<p>On se contente de dire que les services utiliseront par défaut le channel <strong>&#8220;my-amf&#8221;</strong>, avec l&#8217;<em>endpoint<strong> </strong></em><strong>/mesagebroker/amf</strong>. Pour exposer notre service, nous pouvons utiliser l&#8217;annotation <strong>@RemotingDestination <span style="font-weight: normal;">:</span></strong></p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">//...</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.flex.remoting.RemotingDestination</span><span style="color: #339933;">;</span><br />
<br />
@RemotingDestination<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> MathService <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">//...</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
</pre>
<p>Pour que ces annotations soient prises en compte, il faut bien évidemment utiliser la balise <strong>component-scan</strong> dans <strong>dispatcher-servlet.xml</strong> :</p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">xmlns:context</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/context&quot;</span> ...<span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;context:component-scan</span> <span style="color: #000066;">base-package</span>=<span style="color: #ff0000;">&quot;com.excilys.java.springflex&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
</pre>
<h3>Appels depuis le frontend Flex</h3>
<p>Nos services sont exposés, nous pouvons maintenant les consommer depuis du code Flex. Pour cela, nous utiliserons un RemoteObject de la même manière que dans l&#8217;<a href="http://blog.excilys.com/2010/01/20/open-source-flex-development-stack/">article précédent</a>. Le channel &#8220;my-blazeds&#8221; utilisera l&#8217;URL du DispatcherServlet :</p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;channel-definition</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;my-blazeds&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;endpoint</span> <span style="color: #000066;">uri</span>=<span style="color: #ff0000;">&quot;http://localhost:8080/SimpleSpringFlex/messagebroker/amf&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp;<span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;flex.messaging.endpoints.AMFEndpoint&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/channel-definition<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
</pre>
<p><span style="color: #ff0000;"> </span></p>
<div id="attachment_1995" class="wp-caption aligncenter" style="width: 826px"><img class="size-full wp-image-1995 " title="Spring-Flex en action" src="http://blog.excilys.com/wp-content/uploads/2010/01/difficult-operation.png" alt="" width="816" height="276" /><p class="wp-caption-text">Spring-Flex en action</p></div>
<h3>Et après ?</h3>
<p>Ajouter d&#8217;autres services (soustraction, multiplication, &#8230;) consiste à ajouter des méthodes dans MathService. Pour exposer d&#8217;autres classes de services, il suffit de les annoter avec un <code class="codecolorer java default"><span class="java">@RemotingDestination</span></code>.</p>
<p>Si vos services  nécessitent une authentification préalable, il est possible de <a href="http://static.springsource.org/spring-flex/docs/1.0.x/reference/html/ch04.html">sécuriser les destinations avec Spring Security</a>.</p>
<p>Enfin, pour la partie <em>messaging</em>, Spring BlazeDS Integration facilite <a href="http://static.springsource.org/spring-flex/docs/1.0.x/reference/html/ch05.html">l&#8217;envoi de messages</a> entre clients Flex et/ou POJOs. Il est ainsi possible d&#8217;utiliser AMF ou JMS de manière similaire, grâce à une couche d&#8217;abstraction.</p>
<p>Nous venons de voir qu&#8217;une fois de plus, Spring nous propose un module assez simple d&#8217;utilisation qui permet de gagner en clarté de configuration et en rapidité d&#8217;exposition de services. La configuration XML est minimisée, les annotations font le reste. Et comme c&#8217;est bien pensé, ça s&#8217;intègre sans problème avec d&#8217;autres briques Spring liées par exemple à la sécurité. C&#8217;est-y pas beau çà ?</p>
<h3>Code source</h3>
<p>Pour bidouiller vous-même Spring-Flex, vous pouvez télécharger le <a href="http://blog.excilys.com/wp-content/uploads/2010/01/Spring-BlazeDS-integration.zip">code source du projet</a> réalisé dans cet article.</p>
<img src="http://feeds.feedburner.com/~r/blogexcilyscom/~4/a8fLHyENToU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.excilys.com/2010/05/19/blaze-du-remoting-utilisez-spring-flex/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.excilys.com/2010/05/19/blaze-du-remoting-utilisez-spring-flex/</feedburner:origLink></item>
		<item>
		<title>Compte-rendu du Paris JUG : soirée Build, Share &amp; Deploy</title>
		<link>http://feedproxy.google.com/~r/blogexcilyscom/~3/9W2x5lyQDLc/</link>
		<comments>http://blog.excilys.com/2010/05/14/compte-rendu-du-paris-jug-soiree-build-share-deploy/#comments</comments>
		<pubDate>Fri, 14 May 2010 13:41:03 +0000</pubDate>
		<dc:creator>Bastien JANSEN</dc:creator>
				<category><![CDATA[J'y étais !]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[déploiement]]></category>
		<category><![CDATA[dvcs]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[maven 3]]></category>
		<category><![CDATA[paris jug]]></category>
		<category><![CDATA[w3]]></category>
		<category><![CDATA[w3c]]></category>

		<guid isPermaLink="false">http://blog.excilys.com/?p=1935</guid>
		<description><![CDATA[Aujourd&#8217;hui, nous tentons une expérience : écrire un article à plusieurs. Mais plutôt que de s&#8217;abriter derrière un &#8220;nous&#8221; anonyme et sécurisant, nous (sic !) avons décidé de continuer à employer la première personne, en précisant qui est le locuteur lorsque c&#8217;était nécessaire. A vous de nous dire si vous appréciez le format   [...]]]></description>
			<content:encoded><![CDATA[<div class="note">Aujourd&#8217;hui, nous tentons une expérience : écrire un article à plusieurs. Mais plutôt que de s&#8217;abriter derrière un &#8220;nous&#8221; anonyme et sécurisant, nous (sic !) avons décidé de continuer à employer la première personne, en précisant qui est le locuteur lorsque c&#8217;était nécessaire. A vous de nous dire si vous appréciez le format <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  !</div>
<p>Une fois n&#8217;est pas coutume, ce deuxième mardi du mois a été l&#8217;occasion pour les Javaïstes parisiens d&#8217;assister au <a href="http://www.parisjug.org/">Paris JUG</a>, consacré cette fois aux processus de <em>build</em>, <em>share</em> et <em>deployment</em>. Pas de chance, la salle était déjà bien pleine quand je <em>(Bastien)</em> suis arrivé&#8230; vite, une chaise tout devant !</p>
<p>De mon côté <em>(Pierre-Yves)</em>, ayant posé ma tente devant la salle la veille au soir, j&#8217;ai eu accès aux premiers rangs. Allez, je vous livre un petit secret : pour avoir un placement correct au Paris Jug, il faut arriver à 19h <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  (ou être une <a href="http://jduchess.org/duchess-france/">JDuchess</a> <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> ). Je <em>(Pierre-Yves)</em> vais donc vous parler des trois premières présentations, et je <em>(Bastien)</em> continuerai avec les deux dernières.</p>
<p><span id="more-1935"></span></p>
<h3><a href="http://www.w3.org"><img class="alignright size-medium wp-image-1948" title="W3C" src="http://blog.excilys.com/wp-content/uploads/2010/05/w3c_logo-300x145.png" alt="" width="300" height="145" /></a>Les secrets de fabrication du W3C</h3>
<h4>Par <em>Alexandre Bertails</em></h4>
<p>Qui connaît réellement le <a href="http://www.w3.org/">W3C</a> ? En dehors des outils de validation et des spécifications HTML 5, peu d&#8217;entre nous en savent plus sur cet acteur historique du Web. Alexandre Bertails nous en dit plus, dans un temps imparti relativement court.</p>
<p>Saviez-vous que le site web du W3C vient d&#8217;être refait à neuf, après <strong>un an et demi</strong> de travail ? Ce n&#8217;est pas juste une CSS, le contenu et l&#8217;arborescence ont été revus, <strong>sans cependant casser aucun lien</strong>. Allez-y, <a href="http://www.w3.org/">visitez-le</a> (bien plus joli qu&#8217;en <a href="http://web.archive.org/web/20080102062931/http://www.w3.org/">2008</a>, <a href="http://web.archive.org/web/20011217200741/www.w3.org/">2002</a> et même <a href="http://web.archive.org/web/19961227091242/http://www19.w3.org/">1996</a>).</p>
<p>J&#8217;ai aussi découvert que le W3C est composé à 40% de français. Que les outils avec lesquels travaillaient les salariés n&#8217;étaient pas forcément orientés Web, mais que les choses ont bien évolué récemment.</p>
<p>On regrettera le flux permanent des retardataires (ça va, je (<em>Bastien</em>) le saurai pour la prochaine fois !), qui ont quelque peu perturbé notre attention à tous, sans toutefois départir Alexandre de ses moyens (et c&#8217;est tout à son honneur !).</p>
<h3>DVCS</h3>
<h4>Par <em>Sébastien Douche</em></h4>
<p>Speaker hors pair, <a href="http://twitter.com/sdouche">Sébastien Douche</a> nous a donné envie de nous jeter à l&#8217;eau (pardon&#8230; facile celle-là) et de nous mettre immédiatement aux <a href="http://en.wikipedia.org/wiki/Distributed_Version_Control_System">DVCS</a> (Distributed Version Control System, système de gestion de versions distribué).</p>
<p>Auparavant, lorsqu&#8217;il intégrait un nouveau groupe de travail, Sébastien avait l&#8217;habitude d&#8217;y déployer sa boîte à outil habituelle : SVN, et <a href="http://trac.edgewall.org/">Trac</a>. Jusqu&#8217;au jour où il s&#8217;est retrouvé chef de projet sur un projet from scratch.</p>
<p style="text-align: center;"><img class="size-full wp-image-1953 aligncenter" title="Hors Piste" src="http://blog.excilys.com/wp-content/uploads/2010/05/hors_piste.jpg" alt="" width="341" height="454" /></p>
<p>J&#8217;aime beaucoup la métaphore qu&#8217;il nous a donné : la <strong>maintenance</strong> d&#8217;une application, c&#8217;est du <strong>ski sur pistes</strong>, il y a des dizaines de développeurs qui sont passés avant toi et qui ont tracé la piste. Le développement <strong>à partir de zéro</strong>, c&#8217;est du <strong>ski hors piste</strong>, tu sais la direction que tu veux prendre, mais tu es en haut de la montagne, ya du brouillard, il faut se lancer, et tu n&#8217;as pas de repères immédiats.</p>
<p>Avec le temps, le projet, pourtant &#8220;agile&#8221;, a eu de plus en plus de mal à livrer dans les temps, et la qualité de travail s&#8217;est progressivement dégradée. Pourquoi ? Parce que les développeurs passaient leur temps à faire des micro-commit/micro-merge et à intégrer le travail des autres, au lieu de pouvoir se consacrer au développement des fonctionnalités.</p>
<p>C&#8217;est une sale habitude que nous donne SVN : <strong>merger</strong> le code est vécu comme une <strong>expérience difficile</strong>. On préfère donc commiter le plus vite possible pour que ce soient les autres développeurs qui aient à merger. Les micro-commit sont aussi bien moins difficiles à merger. Quand aux branches SVN, elles sont aussi faciles à créer que complexes à merger&#8230;</p>
<p><strong>SVN</strong> ne sert plus au final qu&#8217;à faire de l&#8217;<strong>historisation</strong>, c&#8217;est un super &#8220;Annuler / Répéter&#8221;.</p>
<p>Les DVCS récents permettent à chaque développeur de travailler en local (fonctions d&#8217;historisation) et en isolation, et de pousser le code sur un repository central uniquement lorsque la fonctionnalité est terminée. Leur grande force est la flexibilité qu&#8217;ils introduisent, permettant à chacun de bosser comme il l&#8217;entend tout en respectant les règles d&#8217;organisation du groupe.</p>
<p>Il est aujourd&#8217;hui possible de passer à un DVCS en douceur, sur son poste de travail, en important un repository SVN qui peut rester le repository principal, mais en disposant des avantages d&#8217;un Git ou d&#8217;un Mercurial en local.</p>
<p><strong>Sébastien</strong> en a aussi profité pour nous présenter la manière dont travaille son équipe : le repository central comporte <strong>uniquement du code &#8220;livrable&#8221;</strong> (au sens livraison de fin de Sprint). Chaque fois qu&#8217;une <strong>fonctionnalité</strong> a été <strong>codée</strong> par un développeur, une <strong>revue de code</strong> est réalisée par un autre développeur, une <strong>démo</strong> est réalisée, et si tout va bien alors seulement les<strong> modifications </strong>sont<strong> poussées</strong> sur le repository central.</p>
<p>Sa <strong>conclusion</strong> : si vous ne devez apprendre qu&#8217;une techno en 2010, ce n&#8217;est pas <span style="text-decoration: line-through;">Scala</span>, <span style="text-decoration: line-through;">JEE 6</span>, <span style="text-decoration: line-through;">Maven 3</span>&#8230; <strong>apprenez à utiliser un DVCS</strong> !</p>
<h3>Git</h3>
<h4>Par <em>David Gageot</em></h4>
<p>Plutôt que de faire de sa présentation un énième tutoriel sur Git et tous les concepts associés, <a href="http://twitter.com/dgageot">David Gageot</a> a préféré nous montrer la puissance de Git en quelques exemple pratiques.</p>
<p>Tout d&#8217;abord, <code class="codecolorer bash default"><span class="bash"><span style="color: #c20cb9; font-weight: bold;">git</span> bisect</span></code>. Cette fonctionnalité permet d&#8217;automatiser la recherche du commit qui a créé une régression. Le fonctionnement est simple : on fournit à Git un script permettant de déterminer, pour une version donnée, si le bug est présent ou non. <code class="codecolorer bash default"><span class="bash"><span style="color: #c20cb9; font-weight: bold;">git</span> bisect</span></code> va ensuite réaliser une recherche <a href="http://fr.wikipedia.org/wiki/Dichotomie">dichotomique</a> entre deux numéros de versions, et identifier très rapidement le commit coupable.</p>
<p>Cette fonctionnalité n&#8217;a pas grand chose à voir avec le fait que Git soit un <strong>D</strong>VCS (distribué), mais reste un argument de poids pour adopter cet outil. C&#8217;est aussi possible grâce à la rapidité avec laquelle un Git ou un Mercurial peuvent réaliser un checkout ou changer de version sur une copie locale.</p>
<p>David nous a ensuite montré un script qu&#8217;il a réalisé, qui permet de conditionner automatiquement le push vers le repository au fait que le build et les tests passent. Il peut donc tranquillement bosser et commiter pendant qu&#8217;en tâche de fond le build et les tests sont exécutés, et ainsi se passer d&#8217;un <a href="http://blog.excilys.com/2010/04/21/hudson-retour-dexperience-et-conseils-pratiques/">Hudson</a>.</p>
<p>La présentation s&#8217;est terminée par des démonstration sur l&#8217;évolution de dépôts Git à l&#8217;aide de <a href="http://code.google.com/p/gource/">Gource</a>, qui permet de représenter dans le temps les modifications effectuées sur un dépôt de sources, et le travail de chacun.</p>
<div id="attachment_1965" class="wp-caption aligncenter" style="width: 490px"><a href="http://code.google.com/p/gource/wiki/Screenshots"><img class="size-full wp-image-1965" title="Le Gource du projet Linux" src="http://blog.excilys.com/wp-content/uploads/2010/05/gource-linux-small.jpg" alt="" width="480" height="360" /></a><p class="wp-caption-text">Le Gource du projet Linux</p></div>
<p>En conclusion, quelques conseils :</p>
<ul>
<li>testez Git le plus vite possible,</li>
<li>n&#8217;essayez pas de faire du SVN avec Git, il faut oublier comment SVN fonctionne, désapprendre les mauvais réflexes,</li>
<li>un bon moyen pour démarrer, c&#8217;est de jouer avec <a href="http://github.com/">github</a>,</li>
<li>n&#8217;hésitez pas à utiliser Git dans le cadre de vos projets, au moins en local, il vous apportera une forte plus value même si votre équipe continue d&#8217;utiliser SVN.</li>
</ul>
<h3>Pause Buffet</h3>
<p>Le buffet était gracieusement offert par <a href="http://twitter.com/nmartignole">Nicolas Martignole</a>, suite à <a href="http://www.touilleur-express.fr/2010/05/07/lexpress-board-offre-le-buffet-au-paris-jug-mardi-11-mai/">un défi</a> lancé sur Twitter. Il en a profité pour faire de la pub pour l&#8217;<a href="http://www.express-board.fr/">eXpress Board</a>, un job board pour les passionés. J&#8217;ai <em>(Pierre-Yves)</em> aussi pu croiser <a href="http://twitter.com/emmanuelbernard">Emmanuel Bernard</a>, apprenant ainsi que si l&#8217;équipe Hibernate n&#8217;utilise pas de DVCS pour le moment, ils songent à y passer, notamment pour faciliter l&#8217;intégration de contributions externes.</p>
<h3>Build it with Maven 3!</h3>
<h4>Par <em>Nicolas de Loof</em> &amp; <em>Arnaud Héritier</em></h4>
<p>Invités surprise, <a href="http://twitter.com/ndeloof">Fred</a> et <a href="http://twitter.com/aheritier">Jamy</a> nous ont montré que Maven, c&#8217;est pas sorcier ! Certains se souviennent encore des migrations longues et périlleuses des Makefile vers Ant, puis vers Maven 1 et Maven 2. Cette fois, les développeurs du célèbre gestionnaire de build ont voulu éviter cela : la compatibilité de Maven 3 avec des projets en version 2 est en théorie de 99.99% (hormis maven site qui n&#8217;est pas encore au point).</p>
<div id="attachment_1970" class="wp-caption alignleft" style="width: 360px"><a href="http://oreilly.com/catalog/9780596517335"><img class="size-full wp-image-1970" title="Maven 3" src="http://blog.excilys.com/wp-content/uploads/2010/05/maven3.jpg" alt="" width="350" height="256" /></a><p class="wp-caption-text">Première rencontre avec Maven 3</p></div>
<p>Les mots-clé de la première release stable seront donc les suivants :</p>
<ul>
<li><strong>compatibilité</strong> : en prenant n&#8217;importe quel projet Maven 2, sans aucune modification on pourra le builder avec Maven 3,</li>
<li><strong>modularité/extensibilité</strong> : le socle de l&#8217;application a été entièrement repensé (en évitant les problèmes de rigidité et de complexité de la version 2). Au menu, utilisation de Java 5, apparition d&#8217;APIs simples et intuitives, de la doc&#8230; Bref, de quoi faire des plugins sans se prendre la tête,</li>
<li><strong><a href="http://maven.apache.org/mercury/index.html">Mercury</a></strong> : ce système voué à remplacer le mécanisme d&#8217;artifacts&#8230; a finalement été abandonné <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> .</li>
</ul>
<p>Maven 3 introduit la notion de <strong><em>build plan</em><span style="font-weight: normal;">, qui permet de savoir à l&#8217;avance toutes les actions qui vont être effectuées dans un build (une sorte de contexte d&#8217;exécution). Ainsi, un plugin sera au courant de ce que feront les autres, donnant la possibilité d&#8217;avoir des builds intelligents (où les tests ne seront pas lancés deux fois par deux plugins différents par exemple).</span></strong></p>
<p><strong><span style="font-weight: normal;">Au niveau des descripteurs de build, la structure des pom.xml a été améliorée et Maven 3 devient polyglotte. On peut à présent écrire des descripteurs en <a href="http://www.wakaleo.com/blog/236-writing-your-pom-files-in-groovy-a-sneek-preview-of-maven-3s-polyglot-features">groovy</a> ou en python par exemple. Les exclusions globales de dépendances sont maintenant possibles (on va enfin pouvoir se débarrasser de cette *$#~ de dépendance sur un logger qui plante toujours&#8230; <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> ). </span></strong></p>
<p><strong><span style="font-weight: normal;">Toujours dans les descripteurs, la notion de </span><span style="font-weight: normal;"><em>mixins</em><span style="font-weight: normal;"> est apparue :</span></span></strong></p>
<blockquote><p><strong><span style="font-weight: normal;"><span style="font-weight: normal;">Essentially it will be a POM consisting of plugins and configurations that can be externally parameterized. These mixins will be deployed to a repository and be referenced with a standard coordinate. Basically it will be an intelligent import with validation which will allow composition in your POMs.</span></span></strong></p></blockquote>
<p>On va pouvoir décomposer notre POM en différents morceaux, un peu à la manière des <a href="http://blogs.sun.com/swchan/entry/servlet_3_0_web_fragment">web-fragments</a>.</p>
<p><strong><span style="font-weight: normal;"><span style="font-weight: normal;">Les </span>builds parallèles<span style="font-weight: normal;"> vont bientôt faire leur apparition, pour ne pas que vos 7 autres cores s&#8217;ennuient <em>(edit: Mathieu nous signale en commentaire que les builds parallèles sont déjà disponibles depuis la version 3.0-beta-1)</em>. Cette fonctionnalité sera très intéressante sur les serveurs d&#8217;intégration continue utilisant un modèle maitre/esclave (<a href="http://blog.excilys.com/2010/04/21/hudson-retour-dexperience-et-conseils-pratiques/">Hudson</a>, pour ne citer que lui). Techniquement, le processus de build sera découpé en différentes phases qui se rejoindront en des points de synchronisation.</span></span></strong></p>
<p>Mais au final, qu&#8217;apporte Maven 3 par rapport à Maven 2 à l&#8217;heure actuelle ? Rien, enfin presque :</p>
<ul>
<li>un shell (avec des jolies couleurs !) permet de faciliter les builds (notamment sous Windows),</li>
<li>un gain de rapidité lors des builds.</li>
</ul>
<p>Comme la migration de M2 vers M3 est très simple et rapide, nos deux speakers encouragent vivement les développeurs à tester Maven 3 chez eux, ne serait-ce que pour les gains en terme de rapidité de build. A vos pom, donc !</p>
<h3>Deploy it with&#8230; DeployIt!</h3>
<h4>Par <em>Guillaume Bodet</em> &amp; <em>Benoit Moussaud</em></h4>
<p><img class="alignright size-full wp-image-1963" title="DeployIt" src="http://blog.excilys.com/wp-content/uploads/2010/05/deployit-logo-small.png" alt="" width="206" height="36" /><a href="http://blog.xebia.fr/author/gbodet/">Guillaume</a> et <a href="http://www.twitter.com/bmoussaud">Benoit</a> nous ont présenté les fondamentaux du bébé développé par XebiaLabs, <strong><a href="http://www.xebialabs.com/deployit-automated-deployment-java-applications">DeployIt</a></strong>. Cet outil part du constat qu&#8217;un déploiement ne consiste pas en une simple copie d&#8217;EAR/WAR. Il y a généralement d&#8217;autres éléments à configurer (DataSources, JMS), des scripts SQL à lancer, des batches à mettre en place, etc.</p>
<p>DeployIt permet de gérer toutes ces étapes de manière intelligente et de faciliter l&#8217;installation d&#8217;une application. Il est repose sur <a href="http://www.xebialabs.com/architecture">trois briques principales</a> :</p>
<ul>
<li>le cœur,</li>
<li>des interfaces (Flex, console, Maven, Eclipse, dashboards&#8230;),</li>
<li>des plugins permettant le support de JBoss, Apache, .NET etc.</li>
</ul>
<p>La préparation d&#8217;une installation se fait en deux étapes. Dans un premier temps, on configure le <em>Configuration Item Repository</em> (CIR), qui est un référentiel d&#8217;informations sur les différents environnements de déploiement (test, performances, etc.). Ensuite, l&#8217;ensemble des opérations à effectuer est décrite dans des <em>runbooks</em> : déploiement d&#8217;un EAR, configuration d&#8217;une DataSource, installation d&#8217;un script SQL&#8230;</p>
<p>A partir de ces deux sources d&#8217;information, l&#8217;<em>Intelligent Runbook Resolution Engine</em> va se charger d&#8217;interroger les différents runbooks pour constituer un scénario de déploiement, en se basant sur les caractéristiques de l&#8217;environnement décrites dans le CIR.</p>
<p>Un des aspects intéressants dans DeployIt est sa faible intrusion :</p>
<ul>
<li>Il est <em>agent-less</em>, et va utiliser les moyens existants tels que ssh, sftp, scp.</li>
<li>Il utilise les interfaces natives lorsqu&#8217;elles sont disponibles (wsadmin, JDBC&#8230;).</li>
<li>Un plugin Maven permet de lancer les déploiements au sein d&#8217;un processus de build (au sens Maven) déjà existant dans le projet.</li>
</ul>
<p>Seul bémol : DeployIt est un outil commercial, il existe une <a href="http://www.xebialabs.com/deployit-personal-edition-request">version gratuite</a> mais qui n&#8217;intègre aucune notion de sécurité&#8230; XebiaLabs a ainsi la volonté de permettre aux gens de tester ce produit chez eux, tout en empêchant la possibilité de l&#8217;utiliser pour faire de vrais déploiements en production (sauf si vous êtes kamikaze).</p>
<p>Cependant, XebiaLabs songe à relâcher son outil en Open-Source. La majorité absolue des personnes présentes dans la salle a d&#8217;ailleurs voté positivement pour une telle action, en réponse à un sondage improvisé d&#8217;<a href="http://www.parisjug.org/xwiki/bin/view/Speaker/GoncalvesAntonio">Antonio</a> <img src='http://blog.excilys.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> .</p>
<h3>Conclusion</h3>
<p>Ce Paris JUG fût riche en enseignements et en conférences de qualité. D&#8217;autres compte rendus ont été publiés sur le web : sur le blog du <a href="http://www.touilleur-express.fr/2010/05/12/la-soiree-du-11-mai-2010-au-paris-jug-git-dvcs-et-lexpress-board/">Touilleur Express</a>, et sur le blog des <a href="http://jduchess.org/duchess-france/paris-jug-de-mai-build-share-deploy-jusquau-bout-de-la-nuit-1/">JDuchess</a>.</p>
<p>Le prochain Paris JUG aura lieu le 8 juin, avec une invitée à l&#8217;honneur : <a href="http://www.parisjug.org/xwiki/bin/view/Meeting/20100608">Holly Cummins</a>.</p>
<img src="http://feeds.feedburner.com/~r/blogexcilyscom/~4/9W2x5lyQDLc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.excilys.com/2010/05/14/compte-rendu-du-paris-jug-soiree-build-share-deploy/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://blog.excilys.com/2010/05/14/compte-rendu-du-paris-jug-soiree-build-share-deploy/</feedburner:origLink></item>
	</channel>
</rss>
