<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Tom&#8217;s Quest</title>
  <link href="http://www.tomsquest.com/atom.xml" rel="self"/>
  <link href="http://www.tomsquest.com/"/>
  <updated>2011-10-06T16:26:37+02:00</updated>
  <id>http://www.tomsquest.com/</id>
  <author>
    <name>Thomas Queste</name>
    
  </author>

  
  <entry>
    <title>Review : Play Framework Cookbook</title>
    <link href="http://www.tomsquest.com/blog/2011/10/review-play-framework-cookbook/"/>
    <updated>2011-10-06T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2011/10/review-play-framework-cookbook</id>
    <content type="html">&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/play_framework_cookbook.jpg&#8217; width=&#8217;128&#8217; height=&#8217;160&#8217; alt=&#8221; title=&#8221;&gt;&lt;/p&gt;

&lt;p&gt;Play!, the framework for the bored Java developers ! Very interesting and opinated framework.
I didn&amp;#8217;t play with it a lot in the previous months, but the new book &lt;a href=&quot;http://www.packtpub.com/play-framework-cookbook/book&quot;&gt;&amp;#8220;Play Framework Cookbook&amp;#8221;&lt;/a&gt; by Packt Publishing,
released this summer was a good way to dig into the framework.
The ebook was offered for free to people who wants to review it. No excuse.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Contents&lt;/h2&gt;

&lt;p&gt;The chapters are :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basics of the Play Framework&lt;/li&gt;
&lt;li&gt;Using Controllers&lt;/li&gt;
&lt;li&gt;Leveraging Modules&lt;/li&gt;
&lt;li&gt;Creating and Using APIs&lt;/li&gt;
&lt;li&gt;Introduction to Writing Modules&lt;/li&gt;
&lt;li&gt;Practical Module Examples&lt;/li&gt;
&lt;li&gt;Running Into Production&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Each subsection is divided in parts: &amp;#8220;Getting ready&amp;#8221;, &amp;#8220;How to do it&amp;#8221;, &amp;#8220;How it works&amp;#8221;, &amp;#8220;There&amp;#8217;s more&amp;#8221;, &amp;#8220;See also&amp;#8221;.
The most interesting part for me is the explanation of the internals, not the &amp;#8220;tutorial&amp;#8221; part.
I have found practical information in nearly each of these.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;&amp;#8220;There&amp;#8217;s more&amp;#8221;&lt;/em&gt; parts are cools because it shows additionnal/alternate/better ways to think about what you read before.
For example, here is an excerpt from this part from the chapter &amp;#8220;Understanding bytecode enhancement&amp;#8221;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;Overriding toString() via annotation&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Peter Hilton has written a very good article on how one can configure the output of the
toString() method of an entity with the help of an annotation by using bytecode
enhancement. You can check it out at http://www.lunatech-research.com/archives/2011/01/11/declarative-model-class-enhancement-play&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;A lot of content is about modules (dependencies, events&amp;#8230;) with some examples (Solr, cache&amp;#8230;).
The idea is to complete what you may find online or in the official documentation.&lt;/p&gt;

&lt;h2&gt;Review&lt;/h2&gt;

&lt;p&gt;I give a &amp;#8220;B&amp;#8221; to the book, as it is 1) easy to read and well written, 2) entertaining, 3) actionnable.
The author, Alexander Reelsen, has done a very good work.
I learnt a lot, even as a beginner on the framework. Many of my questions were answered.
The main benefit of the book is to complete the online documentation and going further on many topics.
I really liked the given explanations, the additionnal references and that the framework&amp;#8217;s code was referenced (in the form: &amp;#8220;See this class for more info&amp;#8221;).&lt;/p&gt;

&lt;p&gt;What&amp;#8217;s missing ? Maybe a Scala chapter, but as the author wrote:
&amp;#8220;When I started writing this book, my Scala knowledge was far from competitive (and still is in many areas)&amp;#8221;.&lt;/p&gt;

&lt;h2&gt;Links&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.fr/gp/product/1849515522?ie=UTF8&amp;tag=tosqu-21&quot;&gt;Book (Amazon)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.packtpub.com/play-framework-cookbook/book&quot;&gt;Book (Packt Publishing)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.lunatech-research.com/archives/2011/09/19/playframework-cookbook-review&quot;&gt;Additional review from Lunartech-research&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Better autocompletes with Fuzzy Matching</title>
    <link href="http://www.tomsquest.com/blog/2011/05/better-autocompletes-with-fuzzy-matching/"/>
    <updated>2011-05-13T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2011/05/better-autocompletes-with-fuzzy-matching</id>
    <content type="html">&lt;p&gt;This article is an introduction to Fuzzy Matching and how it can improve an Autocomplete widget. Fuzzy Matching is used to find the most appropriate strings into a set of strings, like finding &amp;#8220;Sinatra&amp;#8221; when you mispelled it &amp;#8220;Senatra&amp;#8221;.&lt;/p&gt;

&lt;p&gt;We will setup a Sinatra application displaying an Ajax autocomplete widget, which call the backend to have the best matching results, even if the match is not strictly equal.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Fuzzy Matching ?&lt;/h2&gt;

&lt;p&gt;Fuzzy Matching, aka &lt;a title=&quot;Wikipedia article on Approximate String Matching&quot; href=&quot;https://secure.wikimedia.org/wikipedia/en/wiki/Approximate_string_matching&quot;&gt;Approximate String matching&lt;/a&gt; on Wikipedia, is used mainly in spell checkers and in biology to measure the variation between DNA.&lt;/p&gt;

&lt;p&gt;In this article, we will use the &lt;a title=&quot;Wikipedia article on the Levenshtein distance algorithm&quot; href=&quot;https://secure.wikimedia.org/wikipedia/en/wiki/Levenshtein_distance&quot;&gt;Levenshtein distance algorithm&lt;/a&gt; to fetch results when there would be none using standard methods. Some other matching algorithms are also popular: the &lt;a title=&quot;Damerau–Levenshtein distance&quot; href=&quot;https://secure.wikimedia.org/wikipedia/en/wiki/Damerau%E2%80%93Levenshtein_distance&quot;&gt;Damerau–Levenshtein distance&lt;/a&gt; (Levenshtein with transposition of letters), the &lt;a title=&quot;Soundex&quot; href=&quot;https://secure.wikimedia.org/wikipedia/en/wiki/Soundex&quot;&gt;Soundex&lt;/a&gt; (a phonetic algorithm for indexing names by sound) and also the &lt;a title=&quot;Bitap algorithm&quot; href=&quot;https://secure.wikimedia.org/wikipedia/en/wiki/Bitap_algorithm&quot;&gt;Bitap&lt;/a&gt;. Many of them can be found in Ruby, or could also be hand coded.&lt;/p&gt;

&lt;p&gt;Using the Levenshtein algorithm, we get a distance between two strings. This gives for example :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sinatra&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;sinatra&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#= 0, equality&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sinatra&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;senatra&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#= 1, one permutation&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;sinatra&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;rails&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#= 6, many permutation&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;This allows us to display to the user not only the strings that match the input, but also the strings that are approximately equal.&lt;/p&gt;

&lt;h2&gt;The application&lt;/h2&gt;

&lt;p&gt;The application uses the following pieces of code :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;A Sinatra application&lt;/li&gt;
    &lt;li&gt;JQuery UI for the Autocomplete&lt;/li&gt;
    &lt;li&gt;The &amp;#8220;text&amp;#8221; gem which has an implementation of the Levenshtein distance algorithm (source: &lt;a title=&quot;Source code of the levenshtein algorithm&quot; href=&quot;https://github.com/threedaymonk/text/blob/master/lib/text/levenshtein.rb&quot;&gt;https://github.com/threedaymonk/text/blob/master/lib/text/levenshtein.rb&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The source code is available on : &lt;a href=&quot;https://github.com/tomsquest/better-autocompletes-with-fuzzy-matching&quot;&gt;https://github.com/tomsquest/better-autocompletes-with-fuzzy-matching&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Frontend&lt;/h3&gt;

&lt;p&gt;The JQuery Autocomplet widget is simple to setup. The source is defined to call the &amp;#8220;countries&amp;#8221; URL and it will send it the input like &amp;#8220;countries?term=my_input&amp;#8221;.&lt;/p&gt;

&lt;h4&gt;1. Add an input&lt;/h4&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;haml&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nc&quot;&gt;.ui-widget&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt; &lt;span class=&quot;nt&quot;&gt;%label&lt;/span&gt;(&lt;span class=&quot;na&quot;&gt;for=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;country&amp;quot;&lt;/span&gt;) Country:
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt; &lt;span class=&quot;nt&quot;&gt;%input&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#country&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h4&gt;2. Bind the JS&lt;/h4&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#country&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;autocomplete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;countries&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ui&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;      &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;#results&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;input was: &amp;#39;&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;#39; and selection was: &amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h3&gt;Backend&lt;/h3&gt;

&lt;p&gt;Even simpler, the backend is a simple get method which respond with JSON :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/countries&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt; &lt;span class=&quot;n&quot;&gt;content_type&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:json&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt; &lt;span class=&quot;n&quot;&gt;find_countries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_json&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The real stuff is in the &amp;#8220;find_countries&amp;#8221; method :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_countries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;c1&quot;&gt;# Exact match&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;countries&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;COUNTRIES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;downcase&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;downcase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_a&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;c1&quot;&gt;# Partial match&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty?&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;countries&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;COUNTRIES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;downcase&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;downcase&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;c1&quot;&gt;# Here is where we call the distance method of the text gem. It computes the Levenshtein distance and&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;c1&quot;&gt;# appends the results to the partial match done before&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;max_distance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Should be tweaked&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;countries&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;COUNTRIES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;countries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uniq!&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;countries&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The find_countries method can serve as an example. It uses exact and partial matching and use the Levenshtein distance to add some more results. A real-world-awesome-production implementation would be different, by narrowing the results (less results, lower distance).&lt;/p&gt;

&lt;h2&gt;Wrapping up&lt;/h2&gt;

&lt;p&gt;With a minimal mathematical background and a minimal technical setup (no indexing, no DB specific feature), we have boosted our autocomplete results.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve seen how to setup a quick-and-simple sinatra app which computes on the Levenshtein distance on the backend. The Frontend was easily done using the JQuery UI Autocomplete widget.&lt;/p&gt;

&lt;p&gt;For advanced use cases, we should improve the way we mix the Fuzzy-maching results with the strictly matching results. Switching to a better algorithm, or a set of algorithm (Longest common substring + Dameau-Levenshtein) could also be easily done.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The complete source code is available on Github : &lt;a href=&quot;https://github.com/tomsquest/better-autocompletes-with-fuzzy-matching&quot;&gt;https://github.com/tomsquest/better-autocompletes-with-fuzzy-matching&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>FitNesse technical setup</title>
    <link href="http://www.tomsquest.com/blog/2010/12/fitnesse-technical-setup/"/>
    <updated>2010-12-04T00:00:00+01:00</updated>
    <id>http://www.tomsquest.com/blog/2010/12/fitnesse-technical-setup</id>
    <content type="html">&lt;p&gt;Getting &lt;a title=&quot;FitNesse homepage&quot; href=&quot;http://fitnesse.org&quot; target=&quot;_blank&quot;&gt;FitNesse&lt;/a&gt; working for a development team is not particularly evident. You have many possibilities and some of them are not so effective.&lt;/p&gt;

&lt;p&gt;The Setup proposed here has a good combination of pros and cons. It will enable the work of two teams: one team of functional people using a central server and one team of developers writing the fixture straight from their workspace.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Advantages and disadvantages&lt;/h2&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Developer friendly&lt;/li&gt;
    &lt;li&gt;One unique source of test cases: the central server&lt;/li&gt;
    &lt;li&gt;Test pages backup along the source code&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Pages cannot be created locally; they have to be created on the central server&lt;/li&gt;
    &lt;li&gt;The backup task seems hacky, but it does the job&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;Team process&lt;/h2&gt;


&lt;p&gt;The functional people use the central server to manage the test pages&lt;/p&gt;

&lt;p&gt;Each developer has its own FitNesse server, which imports the page from the central server and use the local workspace&lt;/p&gt;

&lt;p&gt;A job adds, delete and commits the changes made on the central server’s pages&lt;/p&gt;

&lt;p&gt;Basic rules:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Pages must be created on the central server, never locally&lt;/li&gt;
    &lt;li&gt;Pages must be modified remotely (using the “Edit Remotely” button); Local pages may be erased at the next sync, so use them carefully&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;img class=&#8217;center &#8217; src=&#8217;http://www.tomsquest.com/images/posts/fitnesse-schema_resized2.jpg&#8217; width=&#8217;500&#8217; height=&#8217;359&#8217; alt=&#8221; title=&#8221;&gt;&lt;/p&gt;

&lt;h2&gt;Setup&lt;/h2&gt;




&lt;h3&gt;Central Server&lt;/h3&gt;




&lt;h4&gt;Launcher&lt;/h4&gt;


&lt;p&gt;The launcher will use a local checkout of the project. This checkout is used for compiling the fixture and project code, and also to be able to commit the changes made to the test pages.&lt;/p&gt;

&lt;p&gt;Launcher command line:&lt;/p&gt;

&lt;figure role=code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;div class=&#8217;line&#8217;&gt;java -jar fitnesse.jar -p 8086 -e 0 -r $dir_with_fitnesse_pages&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The “-e 0” argument disables the built-in versioning system of FitNesse.&lt;/p&gt;

&lt;p&gt;The “-r $dir” argument tells FitNesse to use this directory as the repository of pages.&lt;/p&gt;

&lt;p&gt;The whole command line arguments are described here: &lt;a href=&quot;http://fitnesse.org/FitNesse.UserGuide.CommandLineArguments&quot;&gt;http://fitnesse.org/FitNesse.UserGuide.CommandLineArguments&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Classpath&lt;/h4&gt;


&lt;p&gt;We use the “root” page (&lt;a href=&quot;http://localhost:8086/root&quot;&gt;http://localhost:8086/root&lt;/a&gt;) to declare the server’s configuration and classpath.&lt;/p&gt;

&lt;p&gt;This page won’t be added to source control, because its content will be different on a developer’s workstation.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/joel1di1/fitnesse-maven-classpath&quot;&gt;fitnesse-maven-plugin&lt;/a&gt; is used to create the list of jars we depend on. It reads the pom.xml file of our maven project, but it can also read a pom file directly from the central repository.&lt;/p&gt;

&lt;p&gt;Content of the root page:&lt;/p&gt;

&lt;figure role=code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;div class=&#8217;line&#8217;&gt;Use Slim engine instead of Fit
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;!define TEST_SYSTEM {slim}
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;Change the default port to avoid conflicts
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;!define SLIM_PORT {62123}
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;Classpath and pom file
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;!path /home/hudson/workspace/myproject/fitnesse/target/test-classes
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;!pomFile /home/hudson/workspace/myproject/fitnesse/pom.xml&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;h4&gt;Backup job&lt;/h4&gt;


&lt;p&gt;The backup job is simple. It is run by our Build server, every minute and launches a basic script, which adds, deletes and commits all changes within a directory.&lt;/p&gt;

&lt;p&gt;Here is a simple batch file for Subversion.
The first argument should be the directory to backup.&lt;/p&gt;

&lt;figure role=code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;div class=&#8217;line&#8217;&gt;for /f &quot;tokens=2*&quot; %%i in (&#8216;svn status %1 ^| find &quot;?&quot;&#8217;) do svn add &quot;%%i&quot;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;for /f &quot;tokens=2*&quot; %%i in (&#8216;svn status %1 ^| find &quot;!&quot;&#8217;) do svn delete &quot;%%i&quot;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;svn commit -m &quot;Automatic commit&quot; %1&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;We did try to use a FitNesse plugin for Subversion to backup the pages automatically (and in a less hacky way) but that simply did not work at all. This plugin was: &lt;a href=&quot;http://code.google.com/p/cm-subversion&quot;&gt;http://code.google.com/p/cm-subversion&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;FitNesse has also a pseudo-native support of Git (see &lt;a href=&quot;http://fitnesse.org/FitNesse.UserGuide.SourceCodeControl.GitPlugin&quot;&gt;here&lt;/a&gt;) but corporate Git repositories are still not the standard.&lt;/p&gt;

&lt;h4&gt;SVN ignore&lt;/h4&gt;


&lt;p&gt;All files in the working directory of FitNesse can be versioned, except:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;The “root” page we used earlier, this is the content.txt and properties.xml at the root of the working directory&lt;/li&gt;
    &lt;li&gt;The “ErrorLogs” directory&lt;/li&gt;
    &lt;li&gt;All zip files “*.zip” (there should be none because of the “-e 0” flag&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Source: &lt;a href=&quot;http://stackoverflow.com/questions/249580/how-do-i-add-fitnesse-pages-to-version-control&quot;&gt;http://stackoverflow.com/questions/249580/how-do-i-add-fitnesse-pages-to-version-control&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Developer server&lt;/h3&gt;




&lt;h4&gt;Launcher&lt;/h4&gt;


&lt;p&gt;On a developer server, we don’t need the “-r” flag. The pages will be imported from the central server.&lt;/p&gt;

&lt;p&gt;Launcher command line:&lt;/p&gt;

&lt;figure role=code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;div class=&#8217;line&#8217;&gt;java -jar fitnesse.jar -p 8086 -e 0&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;h4&gt;Classpath&lt;/h4&gt;


&lt;p&gt;As on the central server, the “root” page is used to configure the classpath.&lt;/p&gt;

&lt;p&gt;The content is the same, with the exception of the local path:&lt;/p&gt;

&lt;figure role=code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;div class=&#8217;line&#8217;&gt;Use Slim engine instead of Fit
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;!define TEST_SYSTEM {slim}
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;Change the default port to avoid conflicts
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;!define SLIM_PORT {62123}
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;Classpath and pom file
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;!path /home/tom/dev/myproject/fitnesse/target/test-classes
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;!pomFile /home/tom/dev/myproject/fitnesse/pom.xml&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;h4&gt;Wiki import&lt;/h4&gt;


&lt;p&gt;The Wiki Import feature is used to, well&amp;#8230; import the pages from the central server.&lt;/p&gt;

&lt;p&gt;How-to:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;From the developer’s server, create a new page&lt;/li&gt;
    &lt;li&gt;From the properties, paste the URL to the parent page you wish to import (something like http://fitnesse:8086/MyProject)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;img class=&#8217;center &#8217; src=&#8217;http://www.tomsquest.com/images/posts/fitnesse_wiki_import.jpg&#8217; width=&#8217;500&#8217; height=&#8217;87&#8217; alt=&#8221; title=&#8221;&gt;&lt;/p&gt;

&lt;h4&gt;Debugging&lt;/h4&gt;


&lt;p&gt;Debugging is easy. Add a breakpoint to a fixture then create a “Remote Debug” configuration (within the Debug menu).&lt;/p&gt;

&lt;p&gt;Under FitNesse, just append the following at the end of the page you want to debug:&lt;/p&gt;

&lt;figure role=code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;div class=&#8217;line&#8217;&gt;?responder=test&amp;amp;remote_debug=true&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;h4&gt;Random problem (Bind, Socket exception)&lt;/h4&gt;


&lt;p&gt;&lt;img class=&#8217;center &#8217; src=&#8217;http://www.tomsquest.com/images/posts/fitnesse_error.jpg&#8217; width=&#8217;500&#8217; height=&#8217;121&#8217; alt=&#8221; title=&#8221;&gt;&lt;/p&gt;

&lt;p&gt;If you experience strange errors with no output, or better Socket and Bind exceptions (like in the screenshot), you should use the SLIM_PORT option (as used in this article). This basically shift the ports used by Slim to avoid conflicts with, let’s say, Tomcat.&lt;/p&gt;

&lt;p&gt;Add this:&lt;/p&gt;

&lt;figure role=code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;div class=&#8217;line&#8217;&gt;!define SLIM_PORT {62123}&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;

</content>
  </entry>
  
  <entry>
    <title>Industrialisation des développements : automatisez votre base de données</title>
    <link href="http://www.tomsquest.com/blog/2010/09/industrialisation-des-developpements-automatisez-votre-base-de-donnees/"/>
    <updated>2010-09-16T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2010/09/industrialisation-des-developpements-automatisez-votre-base-de-donnees</id>
    <content type="html">&lt;p&gt;Le grand oubli dans l&amp;#8217;industrialisation des développements est la base de données, cette chose monolithique et statique qui n&amp;#8217;évolue pas aussi vite et aussi aisément que le code. Au même titre que l&amp;#8217;intégration continue et les systèmes de gestion de version pour le code source, il existe des outils permettant de fluidifier et d&amp;#8217;automatiser le travail autour du schéma physique des données. Travailler avec ces outils permet de compléter une démarche Agile en permettant une réactivité forte face aux changements.&lt;/p&gt;

&lt;p&gt;Une première partie de cet article concernera les principes et pratiques autour de ces outils (partie « boss compliant »). La deuxième est orientée technique (partie « geek aware »).&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;




&lt;h2&gt;Principes directeurs&lt;/h2&gt;


&lt;p&gt;Dans son article paru en 2003 intitulé « &lt;a href=&quot;http://martinfowler.com/articles/evodb.html&quot;&gt;Evolutionary Database Design&lt;/a&gt; », Martin Fowler pose les principes du design évolutif de base de données. Les points clés en sont :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;La base de données évolue en même temps que le code ;&lt;/li&gt;
    &lt;li&gt;Il faut donc tester en continu la base de données pour permettre un refactoring sans conséquence, comme on le fait avec le code source ;&lt;/li&gt;
    &lt;li&gt;Il faut outiller les processus autour de la base de données afin d&amp;#8217;améliorer la productivité des développements et leur industrialisation.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Les outils existants reposent sur les principes suivants :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Un schéma doit pouvoir être détruit et recréé de manière répétable ;&lt;/li&gt;
    &lt;li&gt;La version du schéma doit être identifiable ;&lt;/li&gt;
    &lt;li&gt;La montée et la descente de version doivent être automatisées ;&lt;/li&gt;
    &lt;li&gt;Les changements appliqués doivent être connus ;&lt;/li&gt;
    &lt;li&gt;Un changement doit pouvoir être défait ou annulé ;&lt;/li&gt;
    &lt;li&gt;Un changement précédemment appliqué ne doit pas être modifié mais un nouveau changement doit être créé.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;Principes techniques&lt;/h2&gt;


&lt;p&gt;Sur le plan technique, le fonctionnement des outils de migration est simple. Ils se basent sur une table contenant la version de la base de données. La liste des scripts exécutés est conservée ainsi qu’une empreinte de chaque script afin de détecter une altération d’un script déjà exécuté.&lt;/p&gt;

&lt;p&gt;A chaque lancement, l’outil de migration compare la version de la base et les scripts existants  et propose la mise à jour le cas échéant.&lt;/p&gt;

&lt;p&gt;Il est également possible de « descendre de version » le schéma (fonctionnalité disponible dans quasiment tous les outils). Il s’agit de remettre la base de données dans un état cohérent. Deux cas d’usage :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;développement d’une nouvelle fonctionnalité : il est ainsi possible de créer un script et de l’exécuter plusieurs fois (montée de version, test, modification, descente, puis nouvelle montée de version). La descente de version permet ainsi de faire revenir la base de données dans l’état précédent ;&lt;/li&gt;
    &lt;li&gt;Ré-alignement automatique du schéma avec le code quand la version de la base de données n’est plus la bonne. Ce cas intervient quand il faut corriger un bug sur la version de production ou au passage à une autre branche de développement, ou encore quand un script a été exécuté puis modifié.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Même si la descente de version est utile, elle a néanmoins deux inconvénients. Le premier est que les instructions de descente doivent être écrites à la main. Les outils les plus simples fonctionnent sur le principe où chaque script contient une partie montée de version et une partie descente (voir l’exemple plus bas avec MyBatis). Seul Liquibase est capable de générer les instructions de descente de version grâce à son DSL.&lt;/p&gt;

&lt;p&gt;Le deuxième inconvénient est que certaines montées de version ne sont pas réversibles (suppression de table ou de données). Dans ce cas, la descente ne sera possible que jusqu&amp;#8217;à la version incluant ce type de modification. L&amp;#8217;alternative est de recréer le schéma de zéro, une fonctionnalité que tous les outils proposent et qui est en fin de compte très rapide.&lt;/p&gt;

&lt;h2&gt;Bonnes pratiques&lt;/h2&gt;


&lt;p&gt;Les bonnes pratiques poussées par ces outils sont :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Scripts (SQL ou XML pour Liquibase) stockés avec le code source&lt;/li&gt;
    &lt;li&gt;Une base de données par développeur (réaliste quand la gestion de la DB est automatisée, hors problème de coût de licence) ;&lt;/li&gt;
    &lt;li&gt;Une base de données commune à l’équipe qui représente l’état complet et stable ;&lt;/li&gt;
    &lt;li&gt;L’intégration continue déroule l’ensemble des scripts à chaque livraison ;&lt;/li&gt;
    &lt;li&gt;Un script qui a déjà pu être exécuté ne doit plus être modifié. On risque sinon de désynchroniser les scripts et le schéma  La livraison d’un nouveau script est nécessaire dans ce cas. Ce script est un refactoring du précédent. La seule exception est un script buggé qui provoque la perte de la donnée. Il ne faut donc pas que ce script atteigne les autres environnements.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;Les outils existants&lt;/h2&gt;




&lt;h3&gt;Liquibase : puissant mais complexe&lt;/h3&gt;


&lt;p&gt;&lt;a title=&quot;Site de Liquibase&quot; href=&quot;http://liquibase.org/&quot;&gt;Liquibase&lt;/a&gt; est le plus connu des outils de migration de base de données. Il se base sur les patterns décrits dans le livre « Refactoring database ». À ce titre, il est conçu autour d’une approche théorique par pattern de refactoring.&lt;/p&gt;

&lt;p&gt;Le noyau de Liquibase est son DSL basé sur XML qui a les avantages :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;d’être compatible avec plusieurs moteurs SQL ;&lt;/li&gt;
    &lt;li&gt;de donner une sémantique aux opérations (on écrira un &amp;lt;renameColumn&amp;gt; plutôt qu’un alter table) ;&lt;/li&gt;
    &lt;li&gt;de générer automatique des instructions de rollback (par exemple, un &amp;lt;createColumn&amp;gt; sera compensé par un &amp;lt;dropColumn&amp;gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Liquibase est complet. Il s’intègre à Maven, Grails, Spring et Hibernate et supporte la génération de documentation ou encore la création d’un diff entre schémas.&lt;/p&gt;

&lt;p&gt;L’inconvénient principal de Liquibase est une certaine complexité qui ne se retrouve pas dans les autres outils (XML, notion de changelog et de changeset, versionning sur id/auteur/chemin). La courbe d&amp;#8217;apprentissage est donc plus élevée que les autres outils se basant purement sur du SQL.&lt;/p&gt;

&lt;p&gt;Exemple de changeSet Liquibase :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;xml&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;changeSet&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;author=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;bob&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;createTable&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;tableName=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;department&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;column&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;int&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;   &lt;span class=&quot;nt&quot;&gt;&amp;lt;constraints&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;primaryKey=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;nullable=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/column&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;column&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;varchar(50)&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;/createTable&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/changeSet&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;h3&gt;Les pragmatiques&lt;/h3&gt;


&lt;p&gt;D’autres outils ne vont pas aussi loin que Liquibase en termes de fonctionnalités et d&amp;#8217;abstraction mais leur approche est pragmatique et plus simple. Ils visent avant tout à automatiser la gestion des scripts SQL. Les principaux sont &lt;a title=&quot;Site de Mybatis&quot; href=&quot;http://www.mybatis.org/java.html&quot;&gt;MyBatis Schema Migration&lt;/a&gt;, &lt;a title=&quot;Site de DBMaintain&quot; href=&quot;http://dbmaintain.sourceforge.net/&quot;&gt;DbMaintain&lt;/a&gt; et &lt;a title=&quot;Site de C5 DB Migration&quot; href=&quot;http://code.google.com/p/c5-db-migration/&quot;&gt;C5 DB Migration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Le principe de ces outils est assez simple et consiste à lancer une série de scripts stockés dans une arborescence répartie en version. Les actions sont tracées ce qui permet de connaître l’état du schéma.&lt;/p&gt;

&lt;p&gt;Exemple d’arborescence organisée pour DbMaintain :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;xml&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;scripts/01_v1.0/01_products_and_orders.sql
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;                02_users.sql
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        02_v1.1/01_add_barcode_column.sql
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;                02_drop_itemcode_column.sql
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Le schéma de base de données est mis à jour en exécutant :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;dbmaintain.sh update chemin/vers/les/scripts
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Dans le cas de MyBatis, les instructions de montée et de descente de version sont écrites dans le même script SQL.
Exemple :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sql&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;&#8211;// create product table&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PRODUCT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ID&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAME&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;VARCHAR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;&#8211;//@UNDO&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PRODUCT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Les outils de migration de base de données permettent une meilleure productivité en levant certaines barrières au changement du schéma des données et ils rendent l&amp;#8217;industrialisation accessible.&lt;/p&gt;

&lt;p&gt;Les points clés à retenir sont :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Les outils de migration de bases de données nous permettent de gagner en efficacité lors de la manipulation du schéma de la base de données ;&lt;/li&gt;
    &lt;li&gt;Ces outils fiabilisent les traitements en les automatisant et en les intégrants à l’usine de développement ;&lt;/li&gt;
    &lt;li&gt;Ces outils apportent de bonnes pratiques permettant un travail en équipe plus efficace ;&lt;/li&gt;
    &lt;li&gt;Ces outils sont disponibles, simples à mettre en place et OpenSource.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Par extension, on peut imaginer qu&amp;#8217;une application puisse se mettre à jour d&amp;#8217;elle-même. En effet, il s’agirait de permettre à l’application de lancer les migrations de schémas quand elle démarre. Cette fonctionnalité réduit le temps de mise en production en supprimant l’étape de passage des scripts par les DBA. Liquibase propose déjà cette fonctionnalité.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Notes sur Rework de 37signals</title>
    <link href="http://www.tomsquest.com/blog/2010/08/notes-sur-rework-de-37signals/"/>
    <updated>2010-08-29T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2010/08/notes-sur-rework-de-37signals</id>
    <content type="html">&lt;p&gt;&lt;a title=&quot;Site du livre Rework&quot; href=&quot;http://37signals.com/rework/&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/rework_cover.jpg&#8217; width=&#8217;100&#8217; height=&#8217;152&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;Mes notes sur le deuxième livre de la société 37signals, &lt;a title=&quot;Site du livre Rework&quot; href=&quot;http://37signals.com/rework/&quot;&gt;Rework&lt;/a&gt;. Il fait suite à Getting Real. J&amp;#8217;ai avalé rapidement le livre car les idées sont tranchantes,  inspirantes et quelque fois révoltantes. Mais le but est là : réaliser  qu&amp;#8217;il y a d&amp;#8217;autres façons de faire du business. de concevoir son  entreprise et de travailler.&lt;/p&gt;

&lt;p&gt;Oui, il est possible de concevoir des applications avec moins de fonctionnalités que la concurrence. Non, l&amp;#8217;argent des investisseurs n&amp;#8217;est pas toujours bon à prendre.&lt;/p&gt;

&lt;p&gt;Le livre est composé d&amp;#8217;un ensemble de courts chapitres et décrit les recettes qu’applique 37Signals pour ces produits et sa façon d’être en tant que business.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;




&lt;h2&gt;Learning form mistakes is overrated&lt;/h2&gt;


&lt;p&gt;Apprendre de ses erreurs est surévalué, il vaut mieux apprendre de ses succès. L&amp;#8217;échec n&amp;#8217;est pas un pré requis du succès. Quelqu&amp;#8217;un qui a déjà eu un succès a plus de chance de l&amp;#8217;être à nouveau. Ceux qui ont eu un échec n&amp;#8217;ont pas plus de chance d&amp;#8217;avoir un succès que les nouveau.&lt;/p&gt;

&lt;p&gt;[Voir &lt;a title=&quot;Article sur la réussite et l&#8217;échec de Leslie Berlin &amp;quot;Try, try again, or maybe not&amp;quot; &quot; href=&quot;http://www.nytimes.com/2009/03/22/business/22proto.html&quot;&gt;l&amp;#8217;article de Leslie Berlin &amp;#8220;Try, try again, or maybe not&amp;#8221;&lt;/a&gt; qui montre que l&amp;#8217;échec ne garantit pas le succès mais que le succès participe au succès].&lt;/p&gt;

&lt;h2&gt;Why Grow ?&lt;/h2&gt;


&lt;p&gt;Une entreprise avec beaucoup d’employé n’est pas forcément saine. Avec la taille viennent de nouveaux problèmes et une plus grande complexité. Chacun doit trouver la bonne taille pour son business en commençant petit et en voyant comment il grandit.&lt;/p&gt;

&lt;h2&gt;Start making something&lt;/h2&gt;


&lt;p&gt;Une idée ne vaut rien tant que vous n&amp;#8217;en avez rien fait. La vraie question est de quelle bonne façon on la réalise.&lt;/p&gt;

&lt;h2&gt;No time is no excuse&lt;/h2&gt;


&lt;p&gt;Il est toujours possible de prendre quelques heures dans son planning pour travailler sur nos projets. Pas de temps, n&amp;#8217;est pas une excuse !&lt;/p&gt;

&lt;h2&gt;Outside Money is plan Z&lt;/h2&gt;


&lt;p&gt;Prendre l’argent d’investisseurs peut ne pas en valoir le coût, car :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;il fait perdre une partie du contrôle : devoir prendre en compte les ordres d&amp;#8217;autres personnes par exemple ;&lt;/li&gt;
    &lt;li&gt;il occasionne une baisse de qualité au détriment du retour sur investissement rapide ;&lt;/li&gt;
    &lt;li&gt;Dépenser l&amp;#8217;argent des autres est addictif ;&lt;/li&gt;
    &lt;li&gt;C&amp;#8217;est souvent un mauvais coup financier (au début, on n&amp;#8217;a aucun levier pour gérer mieux le deal) ;&lt;/li&gt;
    &lt;li&gt;Le client ne devient plus le premier objectif, mais les objectifs des investisseurs le deviennent ;&lt;/li&gt;
    &lt;li&gt;Obtenir de l&amp;#8217;argent prend beaucoup d&amp;#8217;énergie et de temps.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;Start a business, not a startup&lt;/h2&gt;


&lt;p&gt;Le mot Startup signifie être dispendieux, ne pas affronter les réalités du marché, être dans une bulle. Or la réalité est là. Mieux vaut créer un business qu’une Startup.&lt;/p&gt;

&lt;h2&gt;Embrace constraint&lt;/h2&gt;


&lt;p&gt;Moins (de temps, d&amp;#8217;argent, de personne, d&amp;#8217;expérience) est une vraie bonne chose. Cela force à être créatif et à éviter le gâchis.&lt;/p&gt;

&lt;h2&gt;Illusions of agreement&lt;/h2&gt;


&lt;p&gt;Essayer de supprimer les niveaux d&amp;#8217;abstractions (docs, plans, rapports). Chacun peut imaginer une chose différente de chaque niveau. Seul le résultat (le produit) met tout le monde d&amp;#8217;accord.&lt;/p&gt;

&lt;h2&gt;Reasons to quit&lt;/h2&gt;


&lt;p&gt;Questions à se poser pour s&amp;#8217;assurer que l&amp;#8217;on travaille sur des choses qui importent :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Pourquoi faites-vous cela ? A qui cela bénéficie, quelle est la motivation&amp;#8230;&lt;/li&gt;
    &lt;li&gt;Quel problème résolvez-vous ?&lt;/li&gt;
    &lt;li&gt;Est-ce utile finalement ? Faire quelque chose ou quelque chose d&amp;#8217;utile ?&lt;/li&gt;
    &lt;li&gt;Ajoutez vous de la valeur ?&lt;/li&gt;
    &lt;li&gt;Est-ce que cela changera quelque chose ?&lt;/li&gt;
    &lt;li&gt;Que pourriez-vous faire à la place ? Priorité…&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Ne pas hésiter à abandonner ce que l&amp;#8217;on est en train de faire. Des fois, c&amp;#8217;est la bonne chose à faire.&lt;/p&gt;

&lt;h2&gt;Make tiny decisions&lt;/h2&gt;


&lt;p&gt;Mieux vaut faire un ensemble de petites décisions qu&amp;#8217;une grosse décision. Grosse décision égale de grosses erreurs. Cela n&amp;#8217;est pas vrai pour de petites décisions qui seront réparables. Cela n&amp;#8217;empêche pas d&amp;#8217;avoir de grosses idées et de grands plans, juste que la meilleure façon de les réaliser, c&amp;#8217;est par petite décision.&lt;/p&gt;

&lt;p&gt;Les meilleurs buts sont ceux que l&amp;#8217;on peut atteindre, puisqu&amp;#8217;une fois réalisés, on peut construire dessus.&lt;/p&gt;

&lt;h2&gt;Underdo your competition&lt;/h2&gt;


&lt;p&gt;Pour battre un compétiteur, pas besoin de faire plus. Viser à moins faire que ses concurrents, mais faire mieux. [Philosophie à la base des produits de 37Sgnals]&lt;/p&gt;

&lt;h2&gt;Emulate Chefs&lt;/h2&gt;


&lt;p&gt;Apprendre aux autres ce que l&amp;#8217;on connait de son business, ne veut pas dire que les autres pourront nous copier plus facilement (image des chefs cuistot qui donnent leur recette).&lt;/p&gt;

&lt;h2&gt;Drug dealers get it right&lt;/h2&gt;


&lt;p&gt;Pouvoir faire essayer un produit (une dose) car s’il est bon les clients reviendront pour se le payer.&lt;/p&gt;

&lt;h2&gt;Résumés are ridiculous&lt;/h2&gt;


&lt;p&gt;Un CV est toujours exagéré mais aussi toujours vague. Embauchez sur la base du CV est dangereux. Une lettre de motivation est déjà mieux car il n&amp;#8217;est pas possible que le candidat ait envoyé une lettre personnalisée à 100 entreprises.&lt;/p&gt;

&lt;h2&gt;Years of irrelevance&lt;/h2&gt;


&lt;p&gt;Les années d&amp;#8217;expérience ne veulent pas dire grand chose. Connaitre combien de temps une personne a fait une chose ne vaut pas savoir avec quelle qualité et comment elle l&amp;#8217;a fait.&lt;/p&gt;

&lt;h2&gt;Hire great writers&lt;/h2&gt;


&lt;p&gt;Le talent pour l&amp;#8217;écriture est un critère de choix entre candidats. Savoir bien écrire signifie savoir penser correctement, communiquer et savoir expliquer.&lt;/p&gt;

&lt;h2&gt;Take a deep breath&lt;/h2&gt;


&lt;p&gt;Les gens sont des créatures ave des habitudes, c&amp;#8217;est pour cela que le changement est souvent vu comme négatif. Une réaction négative est presque toujours plus forte et plus passionnée qu&amp;#8217;une réaction positive.&lt;/p&gt;

&lt;p&gt;Quand on réalise en changement, il y aura toujours de mécontents. Il faut les écouter, attendre un peu, montrer que l&amp;#8217;on est conscient du problème. Souvent les gens s&amp;#8217;adapteront.&lt;/p&gt;

&lt;h2&gt;Decisions are temporary&lt;/h2&gt;


&lt;p&gt;Une décision n&amp;#8217;est pas définitive. Il faut se laisser la possibilité d&amp;#8217;y revenir. Décider pour maintenant et s&amp;#8217;inquiéter pour le futur plus tard.&lt;/p&gt;

&lt;h2&gt;Liens annexes&lt;/h2&gt;




&lt;ul&gt;
    &lt;li&gt;Le site du livre : &lt;a href=&quot;http://37signals.com/rework/&quot;&gt;http://37signals.com/rework/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Les notes d&amp;#8217;&lt;a title=&quot;Blog d&#8217;Ulrich Vachon&quot; href=&quot;http://ulrichinaction.blogspot.com&quot;&gt;Ulrich Vachon&lt;/a&gt; sur le livre : &lt;a href=&quot;http://ulrichinaction.blogspot.com/2010/08/retour-sur-rework.html&quot;&gt;http://ulrichinaction.blogspot.com/2010/08/retour-sur-rework.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Construire la nouvelle génération de leaders techniques</title>
    <link href="http://www.tomsquest.com/blog/2010/08/construire-la-nouvelle-generation-de-leaders-techniques/"/>
    <updated>2010-08-24T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2010/08/construire-la-nouvelle-generation-de-leaders-techniques</id>
    <content type="html">&lt;p&gt;Transcription de la session de Patrick KUA à l&amp;#8217;USI 2010 : &lt;a title=&quot;Session à l&#8217;USI : Construire la nouvelle génération de leaders techniques&quot; href=&quot;http://www.universite-du-si.com/en/conferences/6-paris-usi-2010/sessions/912-construire-la-nouvelle-generation-de-leaders-techniques&quot;&gt;Building the next génération of technical leaders&lt;/a&gt;.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Définition&lt;/h2&gt;

&lt;p&gt;Un leader technique est un développeur qui passe 30% de son temps à coder avec l’équipe et 70% en activités de leader. Il a donc deux types de compétences : le développement et le leadership.&lt;/p&gt;

&lt;p&gt;Un leader technique ne doit pas être déconnecté de ce qu’il prône, sinon il risque de se baser sur ses opinions plutôt que sur des faits.&lt;/p&gt;

&lt;p&gt;Un leader est facteur important pour la réussite d’une équipe.&lt;/p&gt;

&lt;h2&gt;De mauvais Leaders Techniques&lt;/h2&gt;

&lt;p&gt;Différents types de mauvais leader technique :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&amp;#8220;Benevolent Dictator&amp;#8221; : il dicte ce qu’il fait en étant soutenu par ses opinions plutôt que par du concret&lt;/li&gt;
    &lt;li&gt;&amp;#8220;Do it yourself&amp;#8221; : ne sait pas déléguer&lt;/li&gt;
    &lt;li&gt;&amp;#8220;Hard Problems are mine&amp;#8221; : ne prends que les sujets difficiles (intéressants)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Il existe des développeurs dont la valeur produite est négative (leur impact nette est négative). Il en est de même pour les leaders techniques.  Ceux-ci peuvent provoquer une perte d’enthousiasme de l’équipe, de l’apathie ou encore de la déresponsabilisation.&lt;/p&gt;

&lt;h2&gt;Former de bons leader techniques&lt;/h2&gt;

&lt;p&gt;Nos systèmes ne savent pas produire de bons tech leads.  Le principe de Peter est souvent de rigueur. Ce principe stipule que dans une hiérarchie, un employé tend à s’élever jusque son niveau d’incompétence.&lt;/p&gt;

&lt;p&gt;Patrick raconte une anecdote sur des chercheurs italiens qui ont démontré qu’une société est plus efficace si elle fait monter en grade les personnes aléatoirement plutôt qu’en se basant sur le mérite.&lt;/p&gt;

&lt;p&gt;Un bon développeur ne fera pas forcément un bon leader technique. Les compétences de ces deux métiers ne sont tout simplement pas les mêmes.&lt;/p&gt;

&lt;h2&gt;Des compétences différentes&lt;/h2&gt;

&lt;p&gt;Compétences du développeur :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Implémenter une fonctionnalité&lt;/li&gt;
    &lt;li&gt;Changer un comportement existant&lt;/li&gt;
    &lt;li&gt;Ecrire des tests&lt;/li&gt;
    &lt;li&gt;Coder proprement&lt;/li&gt;
    &lt;li&gt;Challenger les choses établies&lt;/li&gt;
    &lt;li&gt;Proposer des solutions annexes&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Compétence du leader technique :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Aligner chacun sur une même vision&lt;/li&gt;
    &lt;li&gt;Résoudre les conflits&lt;/li&gt;
    &lt;li&gt;Prendre la responsabilité de la livraison&lt;/li&gt;
    &lt;li&gt;Raconter une histoire&lt;/li&gt;
    &lt;li&gt;Faire croitre les talents&lt;/li&gt;
    &lt;li&gt;Faire en sorte que chacun puisse décider&lt;/li&gt;
    &lt;li&gt;Créer un environnement d’équipe sain&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Solutions&lt;/h2&gt;

&lt;p&gt;Pour avoir de meilleurs leaders techniques, Patrick recommande de :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Reconnaître officiellement les différences entre un développeur et un leader technique : expliquer ce qu’est un leader technique, quelles sont les compétences à acquérir ;&lt;/li&gt;
    &lt;li&gt;Développer les compétences : un apprenti tech lead peut travailler avec un tech lead expert (pairing, one-on-one), donner le droit explicitement à l’apprenti de faire des erreurs et sans conséquence pour lui  (cela maximise sa progression).&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Liens&lt;/h2&gt;

&lt;p&gt;&lt;a title=&quot;Blog de Patrick KUA&quot; href=&quot;http://www.thekua.com/atwork/&quot;&gt;Blog de Patrick KUA&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://qconlondon.com/london-2010/file?path=/qcon-london-2010/slides/PatrickKua_BuildingTheNextGenerationOfTechnicalLeaders.pdf&quot;&gt;Slides de la présentation faire à la QCon London (PDF)&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>JPA : les illusions sur les NamedQueries</title>
    <link href="http://www.tomsquest.com/blog/2010/03/jpa-les-illusions-sur-les-namedqueries/"/>
    <updated>2010-03-28T00:00:00+01:00</updated>
    <id>http://www.tomsquest.com/blog/2010/03/jpa-les-illusions-sur-les-namedqueries</id>
    <content type="html">&lt;p&gt;Un certain nombre d&amp;#8217;idées reçues existent sur les NamedQueries. On les dit plus performantes car mises en cache, on les dit plus sûres car validées au chargement. Etudions ces points et regardons quels sont les réels avantages des NamedQueries.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Rappel sur les NamedQueries&lt;/h2&gt;

&lt;p&gt;Une NamedQuery est une requête nommée. Ce n&amp;#8217;est pas une nouveauté de la norme JPA car elles existaient dans Hibernate bien avant. Une namedQuery est un moyen de donner un non à une requête JPQL et de la rappeler par ce nom par la suite.&lt;/p&gt;

&lt;p&gt;Création :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;java&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nd&quot;&gt;@Entity&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nd&quot;&gt;@NamedQuery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;findAllCustomers&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Select c From Customers c&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;o&quot;&gt;&#8230;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Utilisation :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;java&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findAll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createNamedQuery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;findAllCustomers&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getResultList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Une NamedQuery est plus performante&lt;/h2&gt;

&lt;p&gt;La rumeur dit qu&amp;#8217;une NamedQuery est plus performante car elle est mise en cache.&lt;/p&gt;

&lt;p&gt;Techniquement, au démarrage, le moteur JPA va compiler la NamedQuery puis la mettre en cache dans le statementCache des Connections. Cela rappelle fortement les PreparedStatement, non ? Or, Hibernate utilise de toute façon des PreparedStatements si le driver Jdbc le permet. Une NamedQuery ne fait donc pas mieux qu&amp;#8217;une requête dynamique, même s&amp;#8217;il y a le coût de parsing de la requête si celle-ci est dynamique.&lt;/p&gt;

&lt;p&gt;Je n&amp;#8217;ai pas trouvé de benchmark entre les deux approches (NamedQuery versus requête dynamique). La principale variable en jeu est le driver Jdbc et donc la base de données utilisée.&lt;/p&gt;

&lt;h2&gt;Une NamedQuery est validée&lt;/h2&gt;

&lt;p&gt;Une NamedQuery est validée au lancement de l&amp;#8217;application avant d&amp;#8217;être soit placée dans le statementCache. Cela permet théoriquement de contrôler la syntaxe JPQL, que le mapping est correct, que les entités utilisées sont annotées et que les colonnes ont bien un attribut (ou un getter/setter) dans les entités.&lt;/p&gt;

&lt;p&gt;Dans les faits, cette phase de validation est très limitée (testée avec Hibernate 3.3 et mysql) :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Pour une entité inexistante (&amp;#8220;From EntiteInexistante&amp;#8221;), une erreur est remontée&lt;/li&gt;
    &lt;li&gt;Pour une colonne inexistante (&amp;#8220;From Client where colonneInexistante is null&amp;#8221;), aucune erreur n&amp;#8217;est soulevée&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Aujourd&amp;#8217;hui, je ne vois donc pas en quoi cette phase de validation apporte de la valeur. Si la conversion JPQL vers SQL n&amp;#8217;est pas complète, elle n&amp;#8217;empêche pas de valider les requêtes sur &lt;a title=&quot;Base de données embarquée ou non&quot; href=&quot;http://www.tomsquest.com/blog/2009/10/tests-d-integration-quid-de-la-base-de-donnees/&quot;&gt;la base de données cible&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;NamedQuery, alors pourquoi ?&lt;/h2&gt;

&lt;p&gt;Une fois éliminées ces illusions, il ne reste pas grand-chose d&amp;#8217;attrayant aux NamedQueries. On sait qu&amp;#8217;elles ne sont pas systématiquement pas plus performantes et que la validation n&amp;#8217;est pas complète. Il leur reste cependant trois petits avantages :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Les NamedQueries sont réutilisables en plusieurs endroits. Ce cas est principalement utile quand  l&amp;#8217;entityManager est injecté dans la couche de service (et donc qu&amp;#8217;il n&amp;#8217;y a pas de couche de DAO) ;&lt;/li&gt;
    &lt;li&gt;Elles sont chargées au démarrage ce qui permet de diminuer la réponse de l&amp;#8217;application au premier accès, mais c&amp;#8217;est au détriment du temps de chargement de l&amp;#8217;application ;&lt;/li&gt;
    &lt;li&gt;Les requêtes sont regroupées avec le mapping (@Column&amp;#8230;), ce qui permet de faciliter leur écriture.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Pour conclure, je pense que les NamedQueries résultent plus d&amp;#8217;une question de goût et de convention d&amp;#8217;écriture que d&amp;#8217;un réel intérêt technique et factuel.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>8 raisons d&#8217;aimer Ruby</title>
    <link href="http://www.tomsquest.com/blog/2009/11/8-raisons-d-aimer-ruby/"/>
    <updated>2009-11-11T00:00:00+01:00</updated>
    <id>http://www.tomsquest.com/blog/2009/11/8-raisons-d-aimer-ruby</id>
    <content type="html">&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/ruby_logo.gif&#8217; width=&#8217;331&#8217; height=&#8217;119&#8217; alt=&#8221; title=&#8221;&gt;Ruby est un langage qui évolue vite, qui monte fortement et qui est utilisé pour faire de vraies choses (même en prod !). Cet article contient 8 points qui font de Ruby un très bon langage et une plateforme de choix pour réaliser ses futurs projets.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Plus productif&lt;/h2&gt;

&lt;p&gt;Martin Fowler a fait une synthèse de l’utilisation de Ruby chez ThoughtWorks.&lt;/p&gt;

&lt;p&gt;La conclusion est une impression très forte d’une meilleure productivité. La majorité des projets ont ressenti un doublement de leur productivité (une impression car la productivité n’est pas mesurable).&lt;/p&gt;

&lt;p&gt;Je vous encourage à lire l’article sur le site de Martin Fowler : &amp;#8221;&lt;a href=&quot;http://martinfowler.com/articles/rubyAtThoughtWorks.html&quot;&gt;Ruby at ThoughtWorks&lt;/a&gt;&amp;#8221;&lt;/p&gt;

&lt;h2&gt;Meta-Programming&lt;/h2&gt;

&lt;p&gt;Le meta-programming c’est la génération de code par le code. Cela permet par exemple d’écrire des DSL et de simplifier son code. C’est aussi une arme puissante à utiliser modérément.&lt;/p&gt;

&lt;p&gt;L’équivalent de la génération d’une méthode au Runtime en Java donnerait :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;java&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;genereUneMethode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;cm&quot;&gt;/* cette méthode sera ajouté à la classe appelante */&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;nouvelleMethode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;c1&quot;&gt;// Les commentaires de Chuck Norris sont compilés&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Duck Typing&lt;/h2&gt;

&lt;p&gt;Le static typing s’oppose au duck typing. En Ruby, il n’y a pas de notion de type vérifié à la compilation.&lt;/p&gt;

&lt;p&gt;Cela veut dire, qu’il est possible d’appeler une méthode avec un Array à la place d’une String. Tant que l’autre objet répond aux méthodes de l’objet attendu, le code est valide.&lt;/p&gt;

&lt;p&gt;Le Duck Typing permet d’avoir du code beaucoup plus souple. La forte orientation vers les tests de Ruby en est la conséquence.&lt;/p&gt;

&lt;p&gt;Il y a eu beaucoup de débats sur au sujet de « Static typing » contre « Duck typing ». Les auteurs de « Programming Ruby 1.9 » expliquent que le typage statique ne rend pas forcément un code plus fiable et peut diminuer la productivité. (Non, pas de Troll)&lt;/p&gt;

&lt;p&gt;Plus d’info sur le &lt;a href=&quot;http://en.wikipedia.org/wiki/Duck_typing&quot;&gt;duck typing sur Wikipedia&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Closures&lt;/h2&gt;

&lt;p&gt;Les Closures ont fortement animé les débats autour de leur inclusion (ou pas) dans Java.&lt;/p&gt;

&lt;p&gt;Elles font partie de la syntaxe de base de Ruby.&lt;/p&gt;

&lt;p&gt;Les Closures sont des méthodes dont l’exécution peut être retardée tout en retenant le contexte quand elles ont été créées. Elles ont plein d’usages mais ne sont pas pourtant pas évidentes à appréhender.&lt;/p&gt;

&lt;h2&gt;JRuby&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://jruby.org&quot;&gt;JRuby&lt;/a&gt; est une implémentation de Ruby pour la JVM. Avantages : un super garbage collector (merci Java), des threads efficaces, multi-plateformes… Il fait tourner des projets Rails sans problème.&lt;/p&gt;

&lt;p&gt;L’avantage est également de pouvoir faire du Ruby sur nos serveurs d’app Java, comme Glassfish 3 qui supporte JRuby.&lt;/p&gt;

&lt;h2&gt;Frameworks novateurs&lt;/h2&gt;

&lt;p&gt;Rails, Capistrano ou encore Cucumber sont les fers de lance de Ruby et montrent ce que le langage permet de construire.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://rubyonrails.org/&quot;&gt;Rails&lt;/a&gt; : c’est le Framework Web qui a donné de la visibilité à Ruby. Rails permet de produire des sites Web très rapidement et de manière simple&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.capify.org/&quot;&gt;Capistrano&lt;/a&gt; simplifie fortement le déploiement de projets Ruby et permet par exemple de se brancher sur un SVN pour faire de la mise en production en continue&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://cukes.info/&quot;&gt;Cucumber&lt;/a&gt; est un framework de BDD simple à prendre en main. Le Meta-Programming apporte beaucoup aux frameworks de tests en permettant l’écriture de DSL de tests&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;GEM : le packaging facile&lt;/h2&gt;

&lt;p&gt;Les &lt;a href=&quot;http://www.rubyfrance.org/documentations/rubygem&#8212;introduction/&quot;&gt;GEM&lt;/a&gt; sont des archives de projet Ruby. Un peu comme nos JAR/WAR/EAR mais en mieux. Une Gem permet de packager son code, ses tests et ses scripts selon un format normé.&lt;/p&gt;

&lt;p&gt;On installe une Gem en ligne de commande, idem pour la mettre à jour ou en rechercher d’autres.&lt;/p&gt;

&lt;p&gt;Il est également très simple de pousser une Gem sur les repos (voir par exemple l’impressionnant de simplicité &lt;a href=&quot;http://gemcutter.org/&quot;&gt;Gemcutter&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;Une communauté riche (et aussi en France)&lt;/h2&gt;

&lt;p&gt;Ruby bouge beaucoup et sa communauté est importante. Comme avec Java, il y a des sites de news, des podcasts, des screencasts…&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Des news : &lt;a href=&quot;http://www.rubyinside.com/&quot;&gt;RubyInside&lt;/a&gt;, &lt;a href=&quot;http://ruby.about.com/&quot;&gt;About Ruby&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Des podcasts : &lt;a href=&quot;http://railsenvy.com/&quot;&gt;RailsEnvy&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Des screencasts : &lt;a href=&quot;http://www.learnivore.com&quot;&gt;Learnivore&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Des challenges de programmation : &lt;a href=&quot;http://rubylearning.com/blog/&quot;&gt;RubyLearning &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Les &lt;a href=&quot;http://www.rubyfrance.org/&quot;&gt;Apéros Ruby&lt;/a&gt; ressemblent à nos JUGs. Le prochain a lieu ce jeudi 12. Ils sont moins cadrés que les JUGs mais tout aussi intéressants : Coding Dojo, Lightning talk…&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Ruby dispose de nombreux atouts pour plaire, même face à ses concurrents dynamiques ou statiques (Scala par exemple).&lt;/p&gt;

&lt;p&gt;Une des principales qualités de Ruby est sa communauté vivante et innovante. Découvrir une plateforme comme Ruby donne un nouvel élan et permet de faire fonctionner ses neurones sur d’autres paradigmes.&lt;/p&gt;

&lt;p&gt;J’ai choisi Ruby pour toutes ces bonnes raisons et il y en a encore bien d’autres à découvrir.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Tests d&#8217;intégration : quid de la base de données ?</title>
    <link href="http://www.tomsquest.com/blog/2009/10/tests-d-integration-quid-de-la-base-de-donnees/"/>
    <updated>2009-10-12T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2009/10/tests-d-integration-quid-de-la-base-de-donnees</id>
    <content type="html">&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/serveur.jpg&#8217; width=&#8217;87&#8217; height=&#8217;110&#8217; alt=&#8221; title=&#8221;&gt;La base de données est un élément important des tests d&amp;#8217;intégration. Les deux questions à se poser sont :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Puis-je utiliser une base de données embarquée ?&lt;/li&gt;
    &lt;li&gt;Puis-je désactiver les contraintes d&amp;#8217;intégrité ?&lt;/li&gt;
&lt;/ul&gt;




&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Base de données embarquée ou non ?&lt;/h2&gt;

&lt;p&gt;C&amp;#8217;est Rod Johnson qui en parlait sur InfoQ : &amp;#8221;&lt;a title=&quot;System Integration Testing with Spring&quot; href=&quot;http://www.infoq.com/presentations/system-integration-testing-with-spring&quot;&gt;System Integration Testing using Spring&lt;/a&gt;&amp;#8221; : une base de données embarquée est inutile dans la plupart des cas.&lt;/p&gt;

&lt;p&gt;L&amp;#8217;argument majeur en faveur d&amp;#8217;une base embarquée est le travail en mode déconnecté. Dans une équipe disséminée (télétravail, multiples bureaux, déplacement fréquent), ce type de base fait l&amp;#8217;affaire.&lt;/p&gt;

&lt;p&gt;Mais il y a certains inconvénients importants :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Moteur SQL différent de la cible : il est possible de certaines requêtes s&amp;#8217;exécutent sur la base embarquée mais pas sur le type de base utilisée en Prod  (différences d&amp;#8217;implémentation SQL par exemple, expérience vécue avec SQL Server) ;&lt;/li&gt;
    &lt;li&gt;Debugage difficile : si la base meurt à la fin des tests, il devient difficile d&amp;#8217;étudier les opérations faites et d&amp;#8217;étudier pourquoi une requête ne fonctionne pas.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Je vois peu d&amp;#8217;intérêt aujourd&amp;#8217;hui à utiliser une base de données embarquées si c&amp;#8217;est pour se rendre compte qu&amp;#8217;on ne valide pas un comportement similaire à celui de production. Créer une base par développeur sur Oracle ou autre, n&amp;#8217;est pas si difficile.&lt;/p&gt;

&lt;p&gt;Un  inconvénient d&amp;#8217;une base standard est qu&amp;#8217;elle nécessite d&amp;#8217;être maintenue (passage des scripts), mais cela est automatisable grâce à des outils comme DBMaintain ou LiquiBase.&lt;/p&gt;

&lt;h2&gt;Contraintes d&amp;#8217;intégrité actives ou non ?&lt;/h2&gt;

&lt;p&gt;Filip Neven, le créateur d&amp;#8217;Unitils et de DbMaintain, pointe le problème sur son blog (traduction libre) :&lt;/p&gt;

&lt;blockquote&gt;Les gens pensent que la désactivation des contraintes produit une sérieuse dévaluation des tests, car le code qui a été validé avec succès par les tests unitaires pourrait ne pas fonctionner avec une base de données normales - &lt;a title=&quot;Article de Filip Neven sur la désactivation des contraintes&quot; href=&quot;http://filipneven.blogspot.com/2008/02/disable-constraints-on-your-test.html&quot;&gt;Filip Neven&lt;/a&gt;&lt;/blockquote&gt;


&lt;p&gt;La chose à retenir  est : &amp;#8220;il faut limiter au maximum les données de test&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Autrement dit : le moins de données de test il y a, le plus maintenable sont les  tests.&lt;/p&gt;

&lt;p&gt;Filip Neven résume parfaitement la situation :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Les tests doivent valider un fonctionnement et non vérifier l&amp;#8217;intégrité de la base&lt;/li&gt;
    &lt;li&gt;Les tests unitaires ne sont pas le bon outil pour découvrir des problèmes de contraintes&lt;/li&gt;
    &lt;li&gt;Dans la plupart des cas, d&amp;#8217;autres tests, comme les tests fonctionnels, permettront de découvrir les problèmes de contraintes&lt;/li&gt;
    &lt;li&gt;Désactiver les contraintes est un gain de temps important pour l&amp;#8217;écriture des tests&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;En effet, les jeux de données ne font généralement que croitre. Une fois qu&amp;#8217;une donnée est ajoutée à un jeu de tests, il devient laborieux de savoir si cette donnée est utilisée d&amp;#8217;une manière ou d&amp;#8217;une autre et donc de la retirer.&lt;/p&gt;

&lt;p&gt;En désactivant les contraintes d&amp;#8217;intégrité, il devient possible que les jeux de données ne contiennent que les données utilisées dans les Where et dans les jointures ; c&amp;#8217;est-à-dire les données &lt;strong&gt;réellement utiles&lt;/strong&gt;. Cette façon de voir les choses simplifie énormément la maintenance des jeux de tests. Finis les fichiers DBUnit.xml qui contiennent 80% de données dues aux colonnes not-null donc inutiles pour le test courant.&lt;/p&gt;

&lt;p&gt;&lt;a title=&quot;Tutorial Unitils sur la gestion de la base de données&quot; href=&quot;http://www.unitils.org/tutorial.html#Automatic_test_database_maintenance&quot;&gt;Unitils/DbMaintain&lt;/a&gt; propose une méthode rapide pour désactiver ces contraintes (not null et foreign key).&lt;/p&gt;

&lt;h2&gt;Une fausse sensation de sécurité&lt;/h2&gt;

&lt;p&gt;Il faut  se poser la question : est-ce que l&amp;#8217;on nuit à la qualité de nos tests si nous touchons à l&amp;#8217;intégrité de la base de données par la désactivation des contraintes ?&lt;/p&gt;

&lt;p&gt;En effet, si les tests passent sur une base qui sera identique à la production (colonnes non nulles, clés étrangères, utilisateur non privilégié), alors nous validons en totalité le fonctionnement cible. Au contraire, si nous avons désactivé les contraintes, alors nous risquons de rencontrer des erreurs plus tard dans la vie du projet, et donc que cela soit plus dur à corriger.&lt;/p&gt;

&lt;p&gt;La réponse est double :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Oui, nous nous écartons du fonctionnement cible (like &amp;#8220;Prod&amp;#8221;) en modifiant le comportement de la base de données ;&lt;/li&gt;
    &lt;li&gt;Non, ce la ne nuit pas à la qualité des tests.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Pourquoi ?&lt;/p&gt;

&lt;p&gt;Tester &amp;#8220;comme en prod&amp;#8221; donne un &lt;strong&gt;faux sentiment de sécurité&lt;/strong&gt;. Les erreurs susceptibles de ne pas être détectée avant la production ne sont pas des problèmes récurrents. Ok, vous allez détecter qu&amp;#8217;il manque un &amp;#8220;GRANT select&amp;#8221; mais cette erreur ne se reproduira pas.&lt;/p&gt;

&lt;p&gt;D&amp;#8217;autant plus que les tests d&amp;#8217;intégration seront complétés par les tests fonctionnels et que détecteront les erreurs de not-null/foreign key laissées derrière.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Je suis aujourd&amp;#8217;hui pour une gestion &amp;#8220;Agile&amp;#8221; de la base de données utilisée pour les tests. La bonne voie est pour moi d&amp;#8217;éviter l&amp;#8217;usage d&amp;#8217;une base embarquée car il y a trop de différences entre moteurs SQL mais de désactiver certaines contraintes sur la base de test afin de faciliter le vrai travail : l&amp;#8217;écriture de test qui valident les requêtes (le DML) et non les restrictions SQL (le DDL).&lt;/p&gt;

&lt;p&gt;Et vous, avez-vous d&amp;#8217;autres recommandations pour vos tests d&amp;#8217;intégration ?&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>MoreUnit : les tests plus vite sous Eclipse</title>
    <link href="http://www.tomsquest.com/blog/2009/07/moreunit-les-tests-plus-vite-sous-eclipse/"/>
    <updated>2009-07-29T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2009/07/moreunit-les-tests-plus-vite-sous-eclipse</id>
    <content type="html">&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/classDecoration.png&#8217; width=&#8217;252&#8217; height=&#8217;257&#8217; alt=&#8221; title=&#8221;&gt;J&amp;#8217;ai découvert aujourd&amp;#8217;hui le plugin &lt;a title=&quot;Site de MoreUnit : plugin Eclipse&quot; href=&quot;http://moreunit.sourceforge.net&quot;&gt;MoreUnit&lt;/a&gt; pour Eclipse. Celui-ci accélère grandement le passage code/test et la création de tests.&lt;/p&gt;

&lt;p&gt;Il permet de :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Passer d&amp;#8217;une méthode à ses tests et des tests à la méthode testée (ctrl+j depuis une méthode)&lt;/li&gt;
    &lt;li&gt;Montrer les méthodes et classes testées&lt;/li&gt;
    &lt;li&gt;Créer un test pour la méthode en cours (ctrl+u) [même si ça ne remplace pas &amp;#8220;Ctrl+3 &amp;gt; New Junit test case&amp;#8221;]&lt;/li&gt;
    &lt;li&gt;Changer le nom et déplacer les tests lors d&amp;#8217;un refactoring&lt;/li&gt;
&lt;/ul&gt;




&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Je le trouve vraiment pratique pour switcher d&amp;#8217;une méthode aux tests et inversement. Il montre également  les méthodes et classes qui ne sont pas testées et synchronise les tests quand je renomme une méthode. Un vrai gain de temps ! (c&amp;#8217;est mon manager qui va être content).&lt;/p&gt;

&lt;h2&gt;Quelques infos&lt;/h2&gt;

&lt;p&gt;MoreUnit est compatible avec Eclipse 3.5 (Galileo). Il fonctionne parfaitement avec un project Maven.&lt;/p&gt;

&lt;p&gt;Le site : &lt;a title=&quot;Site du plugin MoreUnit&quot; href=&quot;http://moreunit.sourceforge.net&quot;&gt;http://moreunit.sourceforge.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;L&amp;#8217;update site : &lt;a title=&quot;Update Site MoreUnit&quot; href=&quot;http://moreunit.sourceforge.net/org.moreunit.updatesite/&quot;&gt;http://moreunit.sourceforge.net/org.moreunit.updatesite/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Astuces&lt;/h2&gt;

&lt;p&gt;La configuration qui fonctionne pour un projet Maven et Junit 3.x est :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Directory for test cases : src/test/java&lt;/li&gt;
    &lt;li&gt;Test prefixes : &lt;em&gt;vide&lt;/em&gt;&lt;/li&gt;
    &lt;li&gt;Test suffixes : Test&lt;/li&gt;
    &lt;li&gt;Enable flexible naming of tests : coché&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Pour voir le marqueur sur les méthodes (caché par d&amp;#8217;autres annotations Eclipse), il est intéressant d&amp;#8217;activer le soulignement des méthodes ou :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Préférences &amp;gt; Editors &amp;gt; Text Editors &amp;gt; Annotations &amp;gt; MoreUnit Marker &amp;gt; Cocher &amp;#8220;Test as Suiggly line&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Il est possible de créer une nouvelle méthode de test en appuyant plusieurs fois sur ctrl+u depuis la méthode de test.&lt;/p&gt;

&lt;p&gt;La vue qui montre les tests manquants fonctionnent partiellement donc je ne m&amp;#8217;en sers pas.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Critique du livre &#8220;Passionate Programmer&#8221;</title>
    <link href="http://www.tomsquest.com/blog/2009/07/passionate-programmer-critique-du-livre/"/>
    <updated>2009-07-19T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2009/07/passionate-programmer-critique-du-livre</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.pragprog.com/titles/cfcar2/the-passionate-programmer&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/the_passionate_programmer.jpg&#8217; width=&#8217;150&#8217; height=&#8217;225&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;Dans &amp;#8221;&lt;a title=&quot;Site du livre Passionate Programmer&quot; href=&quot;http://www.pragprog.com/titles/cfcar2/the-passionate-programmer&quot;&gt;The Passionate Programmer&lt;/a&gt;&amp;#8221;, apprenez comment gérer votre carrière de geek, comment booster votre vie professionnelle, et avoir du fun et l&amp;#8217;argent du fun.&lt;/p&gt;

&lt;p&gt;L&amp;#8217;auteur, &lt;a title=&quot;Site personnel de Chad Fowler&quot; href=&quot;http://chadfowler.com/&quot;&gt;Chad Fowler&lt;/a&gt;, établit une stratégie pour planifier et créer une vie réussie dans le développement logiciel. Il explique comment prendre le contrôle de sa carrière, s&amp;#8217;activer pour en faire une réussite.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Sa carrière comme un business&lt;/h2&gt;

&lt;blockquote&gt;Il faut se voir comme un produit qu&amp;#8217;il faut construire et vendre&lt;/blockquote&gt;


&lt;p&gt;Une entreprise ne nous emploie pas parce qu&amp;#8217;elle nous aime, mais pour faire de  l&amp;#8217;argent (pour en gagner ou ne pas en perdre). En nous embauchant, la société investie en nous. Donc le challenge est de devenir un bon investissement pour elle, être rentable. Il faut juger ses performances par rapport à notre valeur ajoutée pour la société.&lt;/p&gt;

&lt;p&gt;C&amp;#8217;est sur cette notion de R.O.I. personnelle que Chad Fowler conseille de se poser régulièrement cette question : &amp;#8220;Suis-je un bon investissement ?&amp;#8221;.&lt;/p&gt;

&lt;h2&gt;Ta carrière, c&amp;#8217;est ta vie (ou presque)&lt;/h2&gt;

&lt;p&gt;Vivre une vie remarquable n&amp;#8217;est souvent pas un but quand on débute sa carrière. C&amp;#8217;est beaucoup plus facile de suivre le courant et de se laisser guider par les autres. Vous avez déjà entendu le commercial vous dire : &amp;#8220;C&amp;#8217;est la mission qu&amp;#8217;il te faut&amp;#8221; pour être déçu dès les cinq premières minutes de l&amp;#8217;entretien.&lt;/p&gt;

&lt;p&gt;Le travail représente 50% du temps éveillé. Si vous n&amp;#8217;aimez pas ce que vous faites au boulot, ce chiffre devrait vous choquer. Cela veut aussi dire que l&amp;#8217;on passe plus de temps avec ses collègues qu&amp;#8217;avec notre femme !&lt;/p&gt;

&lt;p&gt;Donc aimer son boulot, c&amp;#8217;est aussi aimer sa vie. On se leurre souvent en cherchant simplement le prochain job mieux payé qui ne nous apportera pas grand-chose. Il faut chercher la satisfaction : &amp;#8220;qu&amp;#8217;est-ce qui me fait plaisir ?&amp;#8221;.&lt;/p&gt;

&lt;h2&gt;Quelques conseils tirés du livre&lt;/h2&gt;

&lt;h4&gt;La Roadmap personnelle&lt;/h4&gt;


&lt;p&gt;Chad Fowler conseille de se construire une liste des compétences que l&amp;#8217;on veut acquérir. Cette liste est une roadmap équivalent à celle d&amp;#8217;un projet qui permettra de planifier et de définir vers où on veut aller.
L&amp;#8217;exercice peut se faire sur son passé : de où je viens, ce que j&amp;#8217;ai appris à chaque fois jusque maintenant.&lt;/p&gt;

&lt;h4&gt;Ne pas mettre tous ses oeufs dans le panier de quelqu&amp;#8217;un d&amp;#8217;autre&lt;/h4&gt;


&lt;p&gt;Java, Java et rien que Java ? Pour l&amp;#8217;auteur, l&amp;#8217;intégrisme technologique est une mauvaise chose. Chaque techno, langage, framework progresse, stagne et décroit. Pour éviter d&amp;#8217;investir sur un mauvais choix (une techno en déclin), il faut étudier le marché et dans tous les cas se diversifier.&lt;/p&gt;

&lt;p&gt;Une entreprise a les moyens (argent et temps) de passer d&amp;#8217;une techno à une autre. Ce n&amp;#8217;est pas le cas pour un individu, car il n&amp;#8217;aura pas les ressources pour le faire (moins d&amp;#8217;argent, moins de temps).&lt;/p&gt;

&lt;p&gt;S&amp;#8217;élargir à d&amp;#8217;autres technos, c&amp;#8217;est limité les risques. Comme en bourse, il s&amp;#8217;agit de diversifier son  portefeuille.&lt;/p&gt;

&lt;h4&gt;Savoir dire Non&lt;/h4&gt;


&lt;p&gt;Oser dire Non à son client ou à son manager est un bon challenge quand on commence sa carrière. Nous avons tous un devoir de conseil qui passe, parfois, par l&amp;#8217;émission d&amp;#8217;un Non motivé. C&amp;#8217;est assez dur à faire car on se sent souvent en infériorité (par exemple, développeur contre client). Il faut être courageux pour savoir dire Non.&lt;/p&gt;

&lt;p&gt;D&amp;#8217;autre part, savoir dire Non renforce notre Oui car les personnes savent alors que cette réponse est sérieuse et motivée.&lt;/p&gt;

&lt;p&gt;Petit bémol, dans certains contextes un &amp;#8220;Oui, mais&amp;#8221; permet de sauver sa peau.&lt;/p&gt;

&lt;h2&gt;Mon avis&lt;/h2&gt;

&lt;p&gt;J&amp;#8217;ai aimé ce livre car j&amp;#8217;ai découvert un nouveau point de vue intéressant et une vision du business différente de la vision traditionnelle. On ne vit pas dans un monde de Bisounours comme diraient les Cast Codeurs.J&amp;#8217;en tire de nombreux conseils et des actions afin de me remettre régulièrement en question et progresser.&lt;/p&gt;

&lt;p&gt;Ce que je n&amp;#8217;ai pas aimé :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Certains chapitres sont trop simplistes ou évidents. Mais, sur 53 chapitres, c&amp;#8217;est normal que tous ne soient pas bons.&lt;/li&gt;
    &lt;li&gt;Beaucoup d&amp;#8217;anecdotes divertissantes sur l&amp;#8217;auteur et la musique mais quelquefois trop écartés du sujet (Chad Fowler est un ancien musicien professionnel)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Note finale : 7/10&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;Will code for food&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://www.pragprog.com/titles/mjwti/my-job-went-to-india&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/my_job_went_to_india.jpg&#8217; width=&#8217;100&#8217; height=&#8217;155&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;Pour l&amp;#8217;anecdote, la première version du livre était intitulée : &amp;#8221;&lt;a title=&quot;Site du livre My Job Went To India&quot; href=&quot;http://www.pragprog.com/titles/mjwti/my-job-went-to-india&quot;&gt;My Job went to India&lt;/a&gt;&amp;#8221; (ce qui a bien fait rire mes collègues de Singapour).&lt;/p&gt;

&lt;p&gt;Sur la couverture, on voit un homme tenant une pancarte &amp;#8220;Will code for food&amp;#8221;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Gradle : vos builds aux petits oignons</title>
    <link href="http://www.tomsquest.com/blog/2009/06/gradle-vos-builds-aux-petits-oignons/"/>
    <updated>2009-06-26T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2009/06/gradle-vos-builds-aux-petits-oignons</id>
    <content type="html">&lt;p&gt;&lt;a title=&quot;Site Web de Gradle&quot; href=&quot;http://www.gradle.org/&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/gradle.jpg&#8217; width=&#8217;144&#8217; height=&#8217;65&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;&lt;a title=&quot;Site Web de Gradle&quot; href=&quot;http://www.gradle.org/&quot;&gt;Gradle&lt;/a&gt; est un outil permettant d&amp;#8217;écrire ses scripts de build en groovy.
Il nous a été présenté hier soir chez &lt;a title=&quot;Zenika&quot; href=&quot;http://www.zenika.com/&quot;&gt;Zenika&lt;/a&gt; par son créateur, Hans Dockter.&lt;/p&gt;

&lt;p&gt;A première vue, c&amp;#8217;est un outil puissant et extrêmement souple. Il apporte beaucoup de bonnes idées et on s&amp;#8217;amuse vite à le comparer à Maven.&lt;/p&gt;

&lt;p&gt;Alors, Gradle pour tous ou seulement pour votre pire ennemi ?&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Donner du sens à vos builds&lt;/h2&gt;

&lt;p&gt;Gradle, c&amp;#8217;est avant tout un DSL en Groovy pour décrire ses builds. Il bénéficie donc des améliorations du langage comme les closures et d&amp;#8217;une syntaxe épurée.&lt;/p&gt;

&lt;p&gt;Hans Docker insiste sur ce point : un script de build qui épouse votre projet est beaucoup plus intéressant qu&amp;#8217;un projet où la structure est imposée par l&amp;#8217;outil de build (comme Maven).&lt;/p&gt;

&lt;p&gt;Il fait un parallèle avec « l&amp;#8217;&lt;a title=&quot;Anemic Object Model de Martin Fowler&quot; href=&quot;http://martinfowler.com/bliki/AnemicDomainModel.html&quot;&gt;Anemic Object Model&lt;/a&gt; » de Martin Fowler et le DDD dans le sens où votre build se décrit lui-même et ses buts se documentent eux-mêmes.&lt;/p&gt;

&lt;p&gt;Gradle propose donc de donner du sens à nos builds en permettant d&amp;#8217;améliorer la compréhension du système et des tâches réalisées.&lt;/p&gt;

&lt;p&gt;Hans oppose les notions de « Langage de build » (Gradle) et de « framework de build » (Maven). L&amp;#8217;un offre la flexibilité, l&amp;#8217;autre pose un cadre défini.&lt;/p&gt;

&lt;h2&gt;Attention, outil coupant&lt;/h2&gt;

&lt;p&gt;Vous avez déjà eu des projets complexes à construire, avec par exemple de la génération de code ou des fichiers à emboiter. Vous vous êtes battu avec Maven et vous avez souvent perdu (c&amp;#8217;est mon cas, je n&amp;#8217;ai pas encore ma ceinture noire de Maven).&lt;/p&gt;

&lt;p&gt;Gradle vient directement répondre à ce besoin : simplifier les builds complexes.
C&amp;#8217;est d&amp;#8217;ailleurs son moto : « Make the impossible possible, the possible easy, and the easy elegant&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Discussion faite avec Florent Ramière de Jaxio, nous sommes du même avis : Oui, Gradle est adapté pour les builds complexes mais 80% ont des besoins simples, réalisables avec Maven.&lt;/p&gt;

&lt;p&gt;Gradle est un outil puissant qui permet de faire précisément ce que vous voulez.
Cette flexibilité extrême permet aussi de faire n&amp;#8217;importe quoi, y compris se tirer une balle dans le pied.
Maven a pris beaucoup d&amp;#8217;ampleur en proposant des conventions et une structure commune (par exemple, les phases et les packages).&lt;/p&gt;

&lt;p&gt;Franchement, c&amp;#8217;est un bonheur de s&amp;#8217;y retrouver entre différents projets. Malheureusement, ces conventions ne peuvent pas se conformer à tous les projets.&lt;/p&gt;

&lt;h2&gt;Un peu jeune&lt;/h2&gt;

&lt;p&gt;Gradle est « production ready » comme le dit Hans. Il est utilisé par certains gros projets aux besoins complexes.
Pourtant, il est encore en fort développement, signe de bonne santé, mais aussi manque de maturité. Le projet n&amp;#8217;a pas encore un an.&lt;/p&gt;

&lt;p&gt;Il lui manque un certain nombre de fonctionnalités avant de devenir réellement complet, par exemple le support d&amp;#8217;autres langages que Java ou encore celui de Netbeans (mais « Why bother ? » comme dirait Antonio Goncalves).&lt;/p&gt;

&lt;p&gt;Bref, il y a du travail et ce n&amp;#8217;est pas la crise comme l&amp;#8217;indique la &lt;a title=&quot;Roadmap Gradle&quot; href=&quot;http://docs.codehaus.org/display/GRADLE/Roadmap&quot;&gt;Roadmap&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Mon avis&lt;/h2&gt;

&lt;p&gt;J&amp;#8217;aime :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;L&amp;#8217;usage d&amp;#8217;un DSL pour donner du sens à ses scripts de build ;&lt;/li&gt;
    &lt;li&gt;La puissante de ce DSL pour faire des choses qui font rêver (par exemple, une tâche à accès à la liste des tâches suivantes afin de pouvoir modifier son comportement) ;&lt;/li&gt;
    &lt;li&gt;La réutilisation des tâches Ant facilement, ce qui veut dire qu&amp;#8217;on peut presque tout faire ;&lt;/li&gt;
    &lt;li&gt;La flexibilité offerte. J&amp;#8217;adore les outils coupants qui me permettent de faire ce que je veux comme je le veux. Mais je reconnais que je n&amp;#8217;ai pas rencontré souvent de besoin très exotique ;&lt;/li&gt;
    &lt;li&gt;Le Gradle Wrapper qui permet de dérouler un build Gradle sans aucune installation préalable (il télécharge ses dépendances automatiquement).&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Je n&amp;#8217;aime pas :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Le fait de ne pas avoir une intégration/réutilisabilité complète avec Maven (la faute aux Plugins apparemment) ;&lt;/li&gt;
    &lt;li&gt;Le trop peu de convention, même si c&amp;#8217;est le but du projet, car les conventions permettent d&amp;#8217;entrer dans l&amp;#8217;entreprise pour éviter que chacun puisse faire ce qu&amp;#8217;il veut. Adieu structuration et normalisation entre projets. Mais rien ne dit qu&amp;#8217;on ne puisse pas poser une structure à respecter. Ce serait l&amp;#8217;équivalent des normes de codages ;&lt;/li&gt;
    &lt;li&gt;Il n&amp;#8217;est pas à  mettre entre toutes les mains. Gros risques de faire dans le non maintenable (quid du debugging, du diagnostique, des performances ?)&lt;/li&gt;
    &lt;li&gt;La jeunesse du projet qui ne garantit pas encore une pérennité suffisante pour l&amp;#8217;entreprise.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Pour allez plus loin&lt;/h2&gt;

&lt;p&gt;Zenika a publié des articles à propose de Gradle ainsi que deux podcasts. Le deuxième podcast couvre bien les avantages et inconvénients de Gradle :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Les &lt;a title=&quot;Articles Zenika sur Gradle&quot; href=&quot;http://blog.zenika.com/index.php?tag/gradle&quot;&gt;articles&lt;/a&gt; ;&lt;a title=&quot;Articles Zenika sur Gradle&quot; href=&quot;http://blog.zenika.com/index.php?tag/gradle&quot;&gt;
&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Les &lt;a title=&quot;Podcast Zenika sur Gradle&quot; href=&quot;http://blog.zenika.com/index.php?post/2009/05/29/Podcast-Gradle&quot;&gt;podcasts&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Nicolas Martignole du Touilleur Express a fait un &lt;a title=&quot;Compte rendu Gradle à Jazoon&quot; href=&quot;http://www.touilleur-express.fr/2009/06/23/jazoon-gradle-la-presentation-qui-aura-lieu-jeudi-soir/&quot;&gt;compte rendu de la présentation&lt;/a&gt; faite à Jazoon. Les commentaires sont également intéressants. J&amp;#8217;aime beaucoup le « Gradle as the assembly language for builds » de Vincent Massol.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Les limites de Wicket</title>
    <link href="http://www.tomsquest.com/blog/2009/05/les-limites-de-wicket/"/>
    <updated>2009-05-03T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2009/05/les-limites-de-wicket</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://wicketframework.org/&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/wicket_logo.jpg&#8217; width=&#8217;150&#8217; height=&#8217;147&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;Connaître un framework, c&amp;#8217;est aussi reconnaître ses limites et ses points faibles. Pour &lt;a href=&quot;http://wicketframework.org/&quot;&gt;Wicket&lt;/a&gt;, il m&amp;#8217;a fallu creuser profondément. J&amp;#8217;ai interrogé les pros de Wicket présent à cette soirée, Carl Azoury, un des boss de Zenika et Martin Dashort, committer Wicket.&lt;/p&gt;

&lt;p&gt;Quelles sont les limites de Wicket ? Quelles sont leurs solutions ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mise à jour le 02/06/2010 :&lt;/strong&gt; &lt;a href=&quot;http://www.developpez.net/forums/d908584/java/developpement-web-java/frameworks/wicket/limites-wicket-commentaire-texte/&quot;&gt;une discussion intéressante sur les limites de Wicket&lt;/a&gt; a eu lieu sur les forums developpez.com. Il y a des arguments intéressants et de vrais retours d&amp;#8217;expérience.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Un mot sur la conférence Wicket/Zenika&lt;/h2&gt;

&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/zenika_logo.gif&#8217; width=&#8217;211&#8217; height=&#8217;68&#8217; alt=&#8221; title=&#8221;&gt;L&amp;#8217;invité de la soirée &lt;a title=&quot;Zenika&quot; href=&quot;http://www.zenika.com/&quot;&gt;Zenika&lt;/a&gt; du 29 avril était &lt;a href=&quot;http://wicketinaction.com/&quot;&gt;Martin Dashorst&lt;/a&gt;, un des committers principaux de Wicket et coauteur du livre « Wicket In Action », dont vous trouverez &lt;a title=&quot;Critique du Livre Wicket In Action&quot; href=&quot;http://www.tomsquest.com/blog/critique-du-livre-wicket-in-action/&quot;&gt;la critique ici-même&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Martin a réalisé une introduction d&amp;#8217;une heure à Wicket en montrant ses principaux avantages et les façons de faire les choses. La présentation a été convaincante mais j&amp;#8217;aurai aimé plus de détails et d&amp;#8217;exemples sur le futur de Wicket.&lt;/p&gt;

&lt;p&gt;La soirée a encore été une nouvelle belle réussite pour Zenika, après les très  bonnes sessions Terracotta et Lean.&lt;/p&gt;

&lt;h2&gt;Le markup n&amp;#8217;est pas toujours prévisualisable&lt;/h2&gt;

&lt;p&gt;Quand votre application commence à être découpée en composants (et c&amp;#8217;est le but final de Wicket), le markup HTML est lui aussi scindé en différents fichiers. Adieu pré-visualisation, le Designer peut recommencer à s&amp;#8217;arracher les cheveux comme avec ces bonnes vieilles JSP.&lt;/p&gt;

&lt;p&gt;Un designer intervient principalement au début du projet. C&amp;#8217;est donc à ce moment-là que la pré-visualisation est importante. Wicket n&amp;#8217;est pas un frein dans cette situation, car il offre trois choix pour gérer son markup. Quand le nombre de pages est inférieur à dix, les auteurs conseillent tout simplement de dupliquer le code dans toutes les pages (hé oui, pour moins de 10 pages, le R.O.I. nous dit : « fais-le avec tes mains »). Au-delà, Wicket propose d&amp;#8217;utiliser le Markup inheritance qui est simplement une hiérarchie de classes et de markup qui composent le layout final. Finalement, il est possible de créer un ensemble de Panels pour découper ses écrans, mais la pré-visualisation devient difficile (inclusion de code HTML entre les balises Wicket qui sera ignoré au runtime).&lt;/p&gt;

&lt;h2&gt;Wicket ne tient pas la charge&lt;/h2&gt;

&lt;p&gt;Wicket stocke beaucoup d&amp;#8217;informations en session et il est donc trop lourd pour gérer plusieurs milliers d&amp;#8217;utilisateurs simultanés. Le versionning des pages qui conserve l&amp;#8217;historique de l&amp;#8217;état des pages ouvertes par l&amp;#8217;utilisateur en est le principal responsable. Martin a quelques références de sites à fort trafic, mais un vide se fait sentir à ce sujet.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Oui, Wicket stocke beaucoup d&amp;#8217;infos en session mais celles-ci sont nécessaires pour les fonctionnalités avancées comme la gestion du back button et les requêtes Ajax. Wicket propose un tas d&amp;#8217;optimisation et un modèle de programmation qui permettent d&amp;#8217;alléger cette charge. Par exemple, les LoadableDetachableModel permettent d&amp;#8217;attacher et de détacher les objets à chaque affichage plutôt que de maintenir la donnée dans la session ;&lt;/li&gt;
    &lt;li&gt;Certes certaines pratiques recommandées par Wicket sont assez dures à comprendre. Dans mon cas, je me pose souvent la question : si je mets mon attribut là, est-ce qu&amp;#8217;il sera sérialisé en session avec ses dépendances ? Pour s&amp;#8217;en convaincre, l&amp;#8217;article suivant illustre certains de ces cas : « &lt;a title=&quot;Wicket Anti Patterns&quot; href=&quot;http://letsgetdugg.com/2009/04/19/wicket-anti-patterns-avoiding-session-bloat/&quot;&gt;Wicket Anti-Patterns: Avoiding Session Bloat&lt;/a&gt; ».&lt;a href=&quot;http://letsgetdugg.com/2009/04/19/wicket-anti-patterns-avoiding-session-bloat/&quot;&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Tester une application Wicket est difficile&lt;/h2&gt;

&lt;p&gt;Le projet WicketTester est intégré au framework même s&amp;#8217;il n&amp;#8217;a pas été développé par l&amp;#8217;équipe principale. D&amp;#8217;après Martin, il s&amp;#8217;écarte un peu du modèle du framework lui-même et souffre de certaines limitations. Parmi celles-ci, il faut connaître le chemin complet d&amp;#8217;un composant dans la hiérarchie pour y accéder (exemple : pour tester un lien d&amp;#8217;un form d&amp;#8217;un panel, il faut connaître cette hiérarchie pour cliquer sur le lien).&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;En réalité, ces limitations ne sont pas bloquante, juste gênantes. Certains projets Wicket utilisant WicketTester ont une couverture de code importante. Martin nous a montré après la conférence des exemples de tests réels assez convainquant. Ca reste proche de l&amp;#8217;API Selenium (sans ses bugs aléatoires, j&amp;#8217;espère);&lt;/li&gt;
    &lt;li&gt;Wicket 1.5 devrait apporter un framework de test plus complet et basé sur une partie du travail accomplit sur JDave. JDave est un framework de BDD (Behavior Driven Development) qui permet de spécifier par l&amp;#8217;exemple les comportements des objets. Plus d&amp;#8217;infos sur : &lt;a href=&quot;http://www.jdave.org/bdd-wicket/&quot;&gt;http://www.jdave.org/bdd-wicket/&lt;/a&gt;;&lt;/li&gt;
    &lt;li&gt;L&amp;#8217;article « &lt;a title=&quot;Tesing Wicket With FitNesse&quot; href=&quot;http://blog.xebia.com/2008/07/06/testing-wicket-with-fitnesse/&quot;&gt;Testing Wicket with FitNesse&lt;/a&gt; » illustre également certains problèmes rencontrés et leurs solutions pour l&amp;#8217;écriture de fixture FitNesse.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Les URLs générées sont moches&lt;/h2&gt;

&lt;p&gt;Wicket génère par défaut des URL de type : http://cheer.com/shop?wicket:interface=:0:detail1::ILinkListener::&lt;/p&gt;

&lt;p&gt;Moche, non ? Et surtout pas facile à retenir et pas terrible pour le référencement. Ces URL contiennent de plus un numéro de version propre à la session courante. De ce fait, il sera impossible de la bookmarker.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Problème récurrent des frameworks Web, la génération des URL par Wicket peut être configurée par pas moins de six stratégies d&amp;#8217;encodage. Un exemple tiré du livre, la stratégie « IndexParamUrlCodingStrategy » est Restful car elle génère une URL de type : http://cheesr.com/cheeses/edam, où « edam » est le paramètre d&amp;#8217;indice 0. D&amp;#8217;autres exemples figurent sur le &lt;a title=&quot;Exemple de URL Strategy&quot; href=&quot;http://cwiki.apache.org/WICKET/url-coding-strategies.html&quot;&gt;Wiki&lt;/a&gt;.&lt;a href=&quot;http://cwiki.apache.org/WICKET/url-coding-strategies.html&quot;&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Spring Security s&amp;#8217;intègre mal à Wicket&lt;/h2&gt;

&lt;p&gt;Intégrer SpringSecurity/Acegi à une application Wicket n&amp;#8217;est pas une sinécure. SpringSecurity réalise ses contrôles essentiellement à partir d&amp;#8217;URLs (par exemple : « l&amp;#8217;utilisateur Hadopi est-il autorisé à accéder à www.thepitatebay.com »). Hors les URL de Wicket contiennent toutes par défaut un identifiant de version, ce qui limite fortement l&amp;#8217;usage de SpringSecurity.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Wicket dispose de son propre framework de sécurité orienté composant (au lieu d&amp;#8217;être orienté URL) donc il est plus granulaire. Avec ce système, Martin nous explique qu&amp;#8217;il est très simple de ne pas afficher un lien si l&amp;#8217;utilisateur n&amp;#8217;a pas accès à sa destination. Illustration :&lt;/li&gt;
&lt;/ul&gt;




&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;java&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;Link&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adminPage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;admin&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onClick&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;n&quot;&gt;setResponsePage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AdminPage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isVisible&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;n&quot;&gt;UserSession&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userSession&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserSession&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userSession&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isAdmin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;ul&gt;
    &lt;li&gt;Pour aller plus loin et centraliser les autorisations, Wicket propose d&amp;#8217;autres projets. Wicket-auth-roles couvre des besoins simples et Wicket-security-wasp/Wicket-security-swarm émule JAAS. L&amp;#8217;article suivant compare ces solutions : « &lt;a title=&quot;Comparison projets de sécurité Wicket&quot; href=&quot;http://wicketstuff.org/confluence/display/STUFFWIKI/Security+Framework+Comparison&quot;&gt;Security Framework comparison&lt;/a&gt; » ;&lt;/li&gt;
    &lt;li&gt;Au passage, il est même possible de développer ses propres annotations et de les poser sur les composants à protéger. Wicket, ce n&amp;#8217;est que du Java après tout :-)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Wicket n&amp;#8217;est pas un framework managé&lt;/h2&gt;

&lt;p&gt;Avec Wicket, vous allez réapprendre à utiliser les mots-clés « new » et « extend » pour lier vos composants. Il n&amp;#8217;y a pas d&amp;#8217;injection de dépendances natives entres les composants.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Et c&amp;#8217;est tant mieux car on n&amp;#8217;en a pas besoin ! Avec Wicket, il y a pas de Xml pour pseudo-découpler vos composants. Et franchement, vous en avez eu souvent besoin ?&lt;/li&gt;
    &lt;li&gt;Côté Injection de dépendances, Wicket s&amp;#8217;intègre très bien avec Spring et Guice. Notamment, il propose pas moins de trois solutions pour utiliser des beans Spring (service locator, proxy et annotation). Plus d&amp;#8217;infos sur la &lt;a title=&quot;Intégration Wicket et Spring&quot; href=&quot;http://cwiki.apache.org/WICKET/spring.html&quot;&gt;page du Wiki dédiée à Spring&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Wicket n&amp;#8217;est pas outillé&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.laughingpanda.org/~inhuman/wicket-bench/docs/features-0.5.html&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/wicket_editor-150x150.jpg&#8217; width=&#8217;150&#8217; height=&#8217;150&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;Même si Wicket enlève sa part de Xml, il nous reste quand-même les pages en Java avec leur markup Html et leurs ressources Xml. Il peut devenir vite fastidieux de manipuler ces fichiers séparément alors qu&amp;#8217;ils ne forment en réalité qu&amp;#8217;une seule page.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;En réalité, il n&amp;#8217;y a pas vraiment besoin d&amp;#8217;outils pour manipuler Wicket. La plupart des choses se passent en Java. Le markup doit être valide (bons identifiants) sinon Wicket refusera de se lancer ce qui permettra de valider son code ;&lt;/li&gt;
    &lt;li&gt;Si vous cherchez vraiment un outil, Wicket est assez bien supporté par les IDE. Pour Eclipse. &lt;a title=&quot;Wicket Bench&quot; href=&quot;http://www.laughingpanda.org/~inhuman/wicket-bench/docs/features-0.5.html&quot;&gt;WicketBench&lt;/a&gt; propose quelques fonctionnalités intéressantes, mais il n&amp;#8217;est pas toujours stable.&lt;a href=&quot;http://www.laughingpanda.org/%7Einhuman/wicket-bench/docs/features-0.5.html&quot;&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;L&amp;#8217;intégrable avec des frameworks JavaScript est difficile&lt;/h2&gt;

&lt;p&gt;A l&amp;#8217;usage, on se rend compte que l&amp;#8217;intégration manuelle avec le JavaScript n&amp;#8217;est pas évidente. Toujours ces histoires d&amp;#8217;Id générés qui rendent plus compliqué un framework orienté Composants qu&amp;#8217;un bon vieux Struts.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Comme toujours, un framework Javascript est d&amp;#8217;un grand secours et Wicket ne fait pas l&amp;#8217;impasse là-dessus. Wicket s&amp;#8217;intègre aux principaux frameworks JavaScript : YahooUI, Dojo, Scripaculous ou encore JQuery.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;L&amp;#8217;exemple suivant montre l&amp;#8217;usage de &lt;a title=&quot;WiQuery&quot; href=&quot;http://code.google.com/p/wiquery/&quot;&gt;WiQuery&lt;/a&gt; qui intègre Jquery/JQueryUI à Wicket au travers des Behaviors, qui permettent d&amp;#8217;ajouter des comportements à des objets existants (dont des attributs JS ou Ajax) :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;17&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;java&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyWebPage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;Label&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;example1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;example1&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Example 1&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;example1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WiQueryEventBehavior&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MouseEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CLICK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JsScope&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JsScope&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;                &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;                &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JsScopeContext&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scopeContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;                    &lt;span class=&quot;n&quot;&gt;scopeContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;chain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CssHelper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;border&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;1px solid red&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;                &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;            &lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;o&quot;&gt;}));&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;example1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Ah Wicket. Quand l&amp;#8217;utiliser ou s&amp;#8217;en passer ? Une chose est sûre : aucun framework n&amp;#8217;est « One size fits all ». Ainsi connaître les limitations de Wicket et leurs solutions est un bon moyen de mieux l&amp;#8217;utiliser et de l&amp;#8217;apprécier. Et moi, j&amp;#8217;adore.&lt;/p&gt;

&lt;p&gt;Vous aussi, vous avez certainement rencontré des problèmes et touché les limites de Wicket. Lesquelles ? Les avez-vous trouvées bloquantes ?&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Retour du Barcamp &#8220;Travailleurs Du Web&#8221;</title>
    <link href="http://www.tomsquest.com/blog/2009/04/retour-du-barcamp-travailleurs-du-web/"/>
    <updated>2009-04-27T00:00:00+02:00</updated>
    <id>http://www.tomsquest.com/blog/2009/04/retour-du-barcamp-travailleurs-du-web</id>
    <content type="html">&lt;p&gt;&lt;a title=&quot;Barcamp Travailleurs du Web&quot; href=&quot;http://barcamp.pbwiki.com/TravailleursDuWebCamp&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/tdw_camp.jpg&#8217; width=&#8217;200&#8217; height=&#8217;193&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;Samedi a eu lieu le premier &lt;a title=&quot;Barcamp Travailleurs du Web&quot; href=&quot;http://barcamp.pbwiki.com/TravailleursDuWebCamp&quot;&gt;Barcamp TDW&lt;/a&gt; destinés aux personnes travaillant dans le Web ou s&amp;#8217;y intéressant : designers, développeurs, webmasters, curieux et même un mec qui fait du Java (vous avez deviné qui).&lt;/p&gt;

&lt;p&gt;Le but du Barcamp était de faire rencontrer les acteurs du Web afin d&amp;#8217;échanger des points de vues et des idées, ainsi que de passer un moment convivial. Mission réussie.&lt;/p&gt;

&lt;p&gt;Les sessions étaient nombreuses et j&amp;#8217;ai assisté à :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Web Mobile&lt;/li&gt;
    &lt;li&gt;Freelance&lt;/li&gt;
    &lt;li&gt;SCOP&lt;/li&gt;
    &lt;li&gt;Vie/Travail&lt;/li&gt;
&lt;/ul&gt;




&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Web Mobile&lt;/h2&gt;

&lt;p&gt;Le Web sur mobile est avant tout un moyen d&amp;#8217;attirer le client, en assurant une continuité totale. L&amp;#8217;équivalent du &amp;#8220;partout, toujours&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Rémi d&amp;#8217;&lt;a title=&quot;Heklectic&quot; href=&quot;http://www.heklektic.fr&quot;&gt;Hekletic&lt;/a&gt; déclare que 60% du Web mobile se fait par un IPhone. Le reste étant divisé en Symbian, Windows Mobile, Black Berry et Androïd.&lt;/p&gt;

&lt;p&gt;J&amp;#8217;ai tenu mon rôle en expliquant que Java était donc disponible (presque) partout.&lt;/p&gt;

&lt;p&gt;Oui, l&amp;#8217;Iphone se porte bien avec ses 1 milliard d&amp;#8217;application téléchargés en deux ans (cf &lt;a title=&quot;1 milliard d&#8217;application IPhone vendue&quot; href=&quot;http://fr.techcrunch.com/2009/04/24/bientot-deux-ans-un-milliard-dapplications-telechargees-liphone-se-porte-a-merveille/&quot;&gt;cette news sur techcrunch&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Les principales contraintes de développement sur mobile sont :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;la taille de l&amp;#8217;écran&lt;/li&gt;
    &lt;li&gt;la rapidité de réception/envoi    des données&lt;/li&gt;
    &lt;li&gt;la puissance du processeur&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Pour Rémi, la principale limitation est le débit de réception. En effet, il faut éviter de streamer trop de données au risque de gâcher l&amp;#8217;expérience utilisateur.&lt;/p&gt;

&lt;p&gt;Certaines applications sont designées entièrement au type de téléphone. Facebook est cité et démonstration à l&amp;#8217;appui : le Facebook de Symbian et celui de l&amp;#8217;Iphone sont bien deux interfaces complètement distinctes. Du point de vue financier, seulement certains éditeurs vont se permettre de développer une interface par téléphone. A quand une homogénéisation ?&lt;/p&gt;

&lt;p&gt;A ma question : &amp;#8220;le Web Mobile pour quels usages ?&amp;#8221;. Je n&amp;#8217;ai pas eu de réponse claire : oui pour les mails, la géo-localisation, les news, twitter&amp;#8230; Mais est-ce tout ? Pas de réponse franche, mais une chose est sûre : le mobile est une nouvelle console de jeu et sert aussi de gadgets (avec en preuve cette application IPhone qui affiche des chiens en train de lécher l&amp;#8217;intérieur de l&amp;#8217;écran, si si, j&amp;#8217;vous jure, 79 centimes sur l&amp;#8217;AppStore). Quasiment tout le monde autour de la table a déjà acheté plusieurs applications sur Iphone.&lt;/p&gt;

&lt;p&gt;Le Wap est mort, je suis triste. En plus, j&amp;#8217;ai enterré mon minitel la semaine dernière.&lt;/p&gt;

&lt;h2&gt;Freelance&lt;/h2&gt;

&lt;p&gt;Les freelances ont, entre autres, certains problèmes comme le manque de crédibilité (statut, ancienneté) et le risque personnel.&lt;/p&gt;

&lt;p&gt;Quelqu&amp;#8217;un raconte que sa société s&amp;#8217;est fait auditer de A à Z par son client, une grande marque de luxe. Le but était de rassurer le client sur sa solidité financière. Cette garantie de &amp;#8220;pouvoir être là dans 3 ans&amp;#8221; n&amp;#8217;étant apparemment pas réaliste pour un freelance. Ce que le client n&amp;#8217;a jamais su, c&amp;#8217;est que le projet a finalement été développé par des indépendants. Donc la &amp;#8220;continuité&amp;#8221; n&amp;#8217;est de toute façon pas assurée.&lt;/p&gt;

&lt;p&gt;Passer freelance est toujours difficile, tout le monde est unanime.&lt;/p&gt;

&lt;p&gt;Il peut donc être intéressant de transiter de son activité salarié vers le statut de Freelance en passant par celui d&amp;#8217;auto-entrepreneur, afin de pour tâter le terrain, travailler avec des clients et se faire connaître.&lt;/p&gt;

&lt;p&gt;Le statut d&amp;#8217;auto-entrepreneur permet d&amp;#8217;avoir une activité annexe sur laquelle on ne paye des charges que s&amp;#8217;il y a chiffre d&amp;#8217;affaire. Dans les services, le chiffre d&amp;#8217;affaire max est de 32000 euros (au-delà, il faudra changer de statut).&lt;/p&gt;

&lt;p&gt;Mais attention, on me souffle à l&amp;#8217;oreille que le statut d&amp;#8217;auto-entrepreneur engage la responsabilité illimité de l&amp;#8217;entrepreneur. Ouch ! A lire dans &lt;a title=&quot;Responsabilité illimité de l&#8217;auto-entrepreneur&quot; href=&quot;http://transtextuel.wordpress.com/2009/04/09/odyssee-d%E2%80%99une-traducteuse-au-regime-l%E2%80%99entreprenariat-volet-2/&quot;&gt;&amp;#8220;Odyssée d&amp;#8217;une traducteuse au régime - l&amp;#8217;entreprenariat, volet 2&amp;#8221;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Au niveau de la concrétisation, un freelance jouît d&amp;#8217;une plus grande liberté. Tous les freelances à la table organisent leur journée à leur convenance. La liberté est en effet un des attraits du statut. Travailler tôt ou tard, faire sa veille quotidienne, coder, toutes ces tâches s&amp;#8217;enchaînent différemment selon les individus.&lt;/p&gt;

&lt;p&gt;La crise ! Ah, le gros mot. Au final pas grand monde pour me dire que la crise se fait durement sentir. Grosse surprise, pour Sébastien d&amp;#8217;&lt;a href=&quot;http://www.altrasys.fr&quot;&gt;Altrasys&lt;/a&gt;, la crise lui a apporté de nouveaux clients. Ceux-ci ne veulent plus payer pour des licences Windows onéreuses, ils veulent de l&amp;#8217;OpenSource car c&amp;#8217;est gratuit et non parce que c&amp;#8217;est mieux.&lt;/p&gt;

&lt;p&gt;Au niveau des contrats/paiement, la méthode &amp;#8220;forfait puis à l&amp;#8217;heure travaillée&amp;#8221; semble convenir. Certaines personnes ont eu des problèmes de règlement quand le client fait le difficile pour payer la dernière partie de l&amp;#8217;ardoise. Il faut bien s&amp;#8217;arranger pour que cette dernière partie soit le &amp;#8220;bonus&amp;#8221;, le bénéfice. Autrement dit, il ne faut pas compter dessus pour vivre et continuer à exercer son travail.&lt;/p&gt;

&lt;h2&gt;SCOP&lt;/h2&gt;

&lt;p&gt;Cette session visait à échanger autour du statut de SCOP (Société Coopérative de Production). C&amp;#8217;est, de façon simplifié, une forme d&amp;#8217;entreprise à but social (par exemple, tous les salariés ont droit de vote).&lt;/p&gt;

&lt;p&gt;Mes notes ne seront jamais aussi complètes que la documentation de cette forme d&amp;#8217;entreprise. Je vous renvoie à :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Wikipedia pour la &lt;a title=&quot;Définition de SCOP&quot; href=&quot;http://fr.wikipedia.org/wiki/Scop&quot;&gt;définition de    SCOP&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Un de mes compte-rendus traite  aussi du sujet : &lt;a title=&quot;Entreprendre au Jug2b&quot; href=&quot;http://www.tomsquest.com/blog/entreprendre-au-jug2b/&quot;&gt;Ma petite entreprise ne connaît pas la   crise&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Cédric, un des fondateurs de la Scop &amp;#8221;&lt;a title=&quot;SCOP La Green Team&quot; href=&quot;http://www.lagreenteam.fr&quot;&gt;La Green Team&lt;/a&gt;&amp;#8221;, était présent et nous a brièvement parlé de sa société. Comme son nom le dit, sa Scop est axée développement durable dans ses statuts. Ses salariés allouent une partie de leur temps (2 jours par mois) à former leur membre, assister aux formations des membres et participer bénévolement à un projet de développement durable. La Scop apporte également une marque et une vision. Elle se rémunère quand elle apporte une affaire.&lt;/p&gt;

&lt;p&gt;Je pense que le statut de Scop est un moyen de faire passer ses idées. L&amp;#8217;orientation sociale et l&amp;#8217;axe donné, comme dans le cas de La Green Team, sont pour moi un vrai moyen de faire du business en allant plus loin dans ses idées. Faire des affaires en changeant le moyen de le faire.&lt;/p&gt;

&lt;h2&gt;Vie/Travail&lt;/h2&gt;

&lt;p&gt;Cette session a fortement dévié de son but initial et on a donc fait pas mal de prospective.&lt;/p&gt;

&lt;p&gt;On s&amp;#8217;interroge sur pourquoi tant d&amp;#8217;intérêt pour le Web. Car Internet réduit avant toutes les distances et les intermédiaires. A tel point qu&amp;#8217;il est dorénavant possible de trouver des fournisseurs, presque qu&amp;#8217;au même prix que des fournisseurs des pays à bas coups de mains d&amp;#8217;oeuvre. Le fondateur de LaFraise est cité, son nouveau business aura des partenaires français sans payer beaucoup plus qu&amp;#8217;en allant les chercher en Chine.&lt;/p&gt;

&lt;p&gt;Sous cet angle de la réduction des intermédiaires, Babozor de &lt;a href=&quot;http://www.travailleursduweb.com/&quot;&gt;TDW&lt;/a&gt; imagine une nouvelle version de la politique où le contact avec le citoyen est quasi-direct. L&amp;#8217;idée est intéressante. Il a lui-même essayé de prendre rendez-vous avec un député sans avoir de vrai succès. Les contacts peuvent se faire mais ils ne sont pas faciles.&lt;/p&gt;

&lt;p&gt;On parle également d&amp;#8217;identité des entreprises. Il est possible de devenir l&amp;#8217;identité d&amp;#8217;un domaine ou, autrement dit, la personne de référence d&amp;#8217;un secteur, d&amp;#8217;une marque ou d&amp;#8217;une entreprise. Babozor explique cette personne qui twittait tout ce qui se faisait sur CNN et qui est ainsi devenu le représentant CNN non-officiel. Son compte Twitter a depuis été racheté par la société. Et vous, deviendrez-vous un porte-parole d&amp;#8217;une marque par votre activité sur le Web ? Y a-t-il des places à prendre ?&lt;/p&gt;

&lt;p&gt;Pour revenir au sujet initial côté horaire de travail, Sébastien d&amp;#8217;Altrasys se fixe sur ceux des bureaux : 9h-18h. Il souhaite limiter ses activités afin de ne pas dépasser et s&amp;#8217;offrir une vraie coupure travail/Vie. Cela n&amp;#8217;est pas facile quand on travaille de chez soi. De même, il ne répondra qu&amp;#8217;exceptionnellement aux mails tardifs à 11h du soir afin de ne pas envoyer de message &amp;#8220;je suis corvéable, allez-y à n&amp;#8217;importe quelle heure&amp;#8221;.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Une bonne journée destinée au Web et pour les gens du Web. Ces sessions m&amp;#8217;ont permis de rencontrer des gens beaucoup plus créatifs que la moyenne. Il y avait une forte concentration de freelances, de fondateurs de sociétés innovantes et de codeurs. De quoi animer plusieurs jours en sujets de toutes sortes. (D&amp;#8217;ailleurs, je crois bien qu&amp;#8217;il y avait aussi assez à manger pour plusieurs jours. Oh ces rillettes, qu&amp;#8217;elles étaient bonnes !).&lt;/p&gt;

&lt;p&gt;Si vous voulez continuer l&amp;#8217;aventure, rendez-vous sur le site des &lt;a title=&quot;Travailleurs du Web&quot; href=&quot;http://www.travailleursduweb.com/&quot;&gt;travailleurs du web&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Merci à Babozor et à &lt;a href=&quot;http://www.quatuorprod.com/&quot;&gt;Fred&lt;/a&gt; pour la très bonne organisation.&lt;/p&gt;

&lt;h2&gt;Les photos&lt;/h2&gt;

&lt;p&gt;Voici un échantillon des photos réalisés par Seb. Vous en trouverez d&amp;#8217;autres sur &lt;a title=&quot;Galerie photos TDW&quot; href=&quot;http://tdwcamp.altrasys.fr&quot;&gt;son site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img class=&#8221; src=&#8217;http://www.tomsquest.com/images/posts/imgp9635-150x150.jpg&#8217; width=&#8217;150&#8217; height=&#8217;150&#8217; alt=&#8221; title=&#8221;&gt;
&lt;img class=&#8221; src=&#8217;http://www.tomsquest.com/images/posts/imgp9658-150x150.jpg&#8217; width=&#8217;150&#8217; height=&#8217;150&#8217; alt=&#8221; title=&#8221;&gt;
&lt;img class=&#8221; src=&#8217;http://www.tomsquest.com/images/posts/imgp9659-150x150.jpg&#8217; width=&#8217;150&#8217; height=&#8217;150&#8217; alt=&#8221; title=&#8221;&gt;
&lt;img class=&#8221; src=&#8217;http://www.tomsquest.com/images/posts/imgp9664-150x150.jpg&#8217; width=&#8217;150&#8217; height=&#8217;150&#8217; alt=&#8221; title=&#8221;&gt;
&lt;img class=&#8221; src=&#8217;http://www.tomsquest.com/images/posts/imgp9673-150x150.jpg&#8217; width=&#8217;150&#8217; height=&#8217;150&#8217; alt=&#8221; title=&#8221;&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Démarrer avec JPA, Spring, Maven et Glassfish</title>
    <link href="http://www.tomsquest.com/blog/2009/02/demarrer-avec-jpa-spring-maven-et-glassfish/"/>
    <updated>2009-02-26T00:00:00+01:00</updated>
    <id>http://www.tomsquest.com/blog/2009/02/demarrer-avec-jpa-spring-maven-et-glassfish</id>
    <content type="html">&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2009/02/screenshot_06.jpeg&#8217; width=&#8217;148&#8217; height=&#8217;59&#8217; alt=&#8221; title=&#8221;&gt;Je vous propose un projet qui permettra de démarrer avec &lt;a title=&quot;Java Persistence API&quot; href=&quot;http://java.sun.com/javaee/5/docs/api/javax/persistence/package-summary.html&quot;&gt;JPA&lt;/a&gt; et &lt;a title=&quot;Doc Spring&quot; href=&quot;http://static.springframework.org/spring/docs/2.5.x/reference/&quot;&gt;Spring&lt;/a&gt;, de déployer sous &lt;a href=&quot;https://glassfish.dev.java.net/&quot;&gt;Glassfish v3&lt;/a&gt; et de lancer les tests d&amp;#8217;intégration sans serveur d&amp;#8217;application, le tout avec le pom &lt;a href=&quot;http://maven.apache.org/&quot;&gt;Maven&lt;/a&gt; qui va bien.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;JPA&lt;/h2&gt;

&lt;p&gt;Le projet contient deux configurations de JPA : l&amp;#8217;une pour le déploiement, utilisée par Glassfish, l&amp;#8217;autre pour les tests d&amp;#8217;intégration.&lt;/p&gt;

&lt;p&gt;Les PersistentUnits sont configurés par :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt; le fichier « persistence.xml » pour Glassfish, l&amp;#8217;attribut transaction-type doit valoir « JTA », sinon Glassfish refuse de démarrer ;&lt;/li&gt;
    &lt;li&gt;le fichier « orm.xml » pour les test. L&amp;#8217;Attribut transaction-type vaut « RESOURCE_LOCAL »&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Spring est lui aussi configuré en deux fois (déploiement et test). Grâce aux classpath de Maven, le bon fichier est sélectionné.&lt;/p&gt;

&lt;p&gt;&lt;img class=&#8217;center &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2009/02/screenshot_05.jpeg&#8217; width=&#8217;225&#8217; height=&#8217;348&#8217; alt=&#8221; title=&#8221;&gt;&lt;/p&gt;

&lt;p&gt;Le fichier JPA pour le serveur est le suivant :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;xml&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;jee:jndi-lookup&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;dataSource&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;jndi-name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;jdbc/springify&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;jee:jndi-lookup&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;entityManagerFactory&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;jndi-name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;persistence/springify&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;tx:jta-transaction-manager&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Le fichier JPA pour les tests d&amp;#8217;intégration est le suivant (un peu plus copieux) :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;13&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;xml&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;bean&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;dataSource&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;org.springframework.jdbc.datasource.DriverManagerDataSource&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;na&quot;&gt;p:driverClassName=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;com.mysql.jdbc.Driver&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;p:url=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;jdbc:mysql://localhost:3306/springify&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;na&quot;&gt;p:username=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;root&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;p:password=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;bean&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;entityManagerFactory&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;na&quot;&gt;p:dataSource-ref=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;dataSource&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;p:persistenceXmlLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;META-INF/orm.xml&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;na&quot;&gt;p:persistence-unit-name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;springify&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;p:jpaVendorAdapter-ref=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;jpaAdapter&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;bean&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;transactionManager&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;org.springframework.orm.jpa.JpaTransactionManager&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;na&quot;&gt;p:entityManagerFactory-ref=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;entityManagerFactory&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;bean&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;jpaAdapter&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;na&quot;&gt;p:database=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;MYSQL&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;p:showSql=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Glassfish&lt;/h2&gt;

&lt;p&gt;Côté Glassfish, il suffit de créer une nouvelle DataSource. Rien de très compliqué.
Si vous utilisez MySQL, veillez à utiliser le moteur InnoDb afin que les transactions soient activées (sinon pas de rollback). Par exemple :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sql&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Tag&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;      &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AUTO_INCREMENT&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;  &lt;span class=&quot;nb&quot;&gt;VARCHAR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Engine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InnoDB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h3&gt;NoClassDefFoundError: javax/interceptor/InvocationContext&lt;/h3&gt;

&lt;p&gt;Cette erreur est visible au lancement de Glassfish mais elle n&amp;#8217;impacte pas le fonctionnement de l&amp;#8217;application. Apparemment, un Glassfish v3 n&amp;#8217;aurait pas les Jars EJB par défaut, comme dit dans &lt;a title=&quot;Glassfish n&#8217;a pas cette classe, par défaut&quot; href=&quot;http://markmail.org/message/j3p4jj4o6q27wfhn&quot;&gt;ce message&lt;/a&gt;. Je n&amp;#8217;ai pas poussé plus loin, « if it works, don&amp;#8217;t try to fix it ».&lt;/p&gt;

&lt;p&gt;Détail de l&amp;#8217;erreur pour info :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;java&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nl&quot;&gt;SEVERE:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;interceptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InvocationContext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;found&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loading&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;springframework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ejb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;interceptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SpringBeanAutowiringInterceptor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;nl&quot;&gt;WARNING:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;annotation&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;processing:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;NoClassDefFoundError&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;javax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;interceptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InvocationContext&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;Maven&lt;/h2&gt;

&lt;p&gt;Les dépendances dans le pom.xml ont été limitées au maximum. Pour démarrer, il faut :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt; Spring et Spring-test pour les tests d&amp;#8217;intégration JPA ;&lt;/li&gt;
    &lt;li&gt; Hibernate entity manager, c&amp;#8217;est l&amp;#8217;implémentation JPA utilisé pour les tests d&amp;#8217;intégration. Elle fournit aussi un lien vers le package javax.persistence ;&lt;/li&gt;
    &lt;li&gt;J&amp;#8217;ai ajouté Spring-MVC pour monter une stack complète avec un Controleur Web annoté.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Améliorations&lt;/h2&gt;

&lt;p&gt;Le &amp;#8220;petites&amp;#8221; choses à faire :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Utiliser la même implémentation JPA que le serveur (EclipseLink avec Glassfish) pour les tests d&amp;#8217;intégration (Hibernate) pour éviter d&amp;#8217;éventuels écarts de comportement ;&lt;/li&gt;
    &lt;li&gt;Configurer les transactions de manières déclaratives en utilisant Spring-AOP plutôt que des @Transactional un peu partout ;&lt;/li&gt;
    &lt;li&gt;Séparer les tests d&amp;#8217;intégration des tests unitaires comme conseillé dans Better Builds With Maven ;&lt;/li&gt;
    &lt;li&gt;Utiliser DBUnit pour ré-initialiser la base de données au démarrage des tests, ou passer à Unitils pour faire tout ça et encore plus.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Le projet&lt;/h2&gt;

&lt;p&gt;Le code source est disponible sur Github : &lt;a href=&quot;https://github.com/tomsquest/spring-jpa-maven-glassfish&quot;&gt;https://github.com/tomsquest/spring-jpa-maven-glassfish&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>JavaCamp 3 : Compte-rendu</title>
    <link href="http://www.tomsquest.com/blog/2009/02/javacamp-3-compte-rendu/"/>
    <updated>2009-02-01T00:00:00+01:00</updated>
    <id>http://www.tomsquest.com/blog/2009/02/javacamp-3-compte-rendu</id>
    <content type="html">&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2009/02/parisjavacamp3.jpg&#8217; width=&#8217;150&#8217; height=&#8217;128&#8217; alt=&#8221; title=&#8221;&gt;J&amp;#8217;ai assisté hier au &lt;a title=&quot;Java Camp numero 3&quot; href=&quot;http://barcamp.org/JavaCampParis3&quot;&gt;JavaCamp n°3&lt;/a&gt; organisé par Valtech chez Sun. Une quinzaine de personnes étaient présentes et les sessions se sont rapidement organisées. Un compte rendu rapide des sessions auxquelles j&amp;#8217;ai participées.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Le TEST&lt;/h2&gt;

&lt;p&gt;Sujet général où nous avons parlé outils et méthodes.&lt;/p&gt;

&lt;p&gt;&lt;a title=&quot;Blog Eric Lefevre&quot; href=&quot;http://ericlefevre.net/wordpress/&quot;&gt;Eric Lefevre&lt;/a&gt; explique que le test est avant tout une question de retour sur investissement (ROI). Le test pour le test n&amp;#8217;est pas une finalité, il faut tester ce qui est important et ce qui apporte de la valeur.&lt;/p&gt;

&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2009/02/cohn.jpg&#8217; width=&#8217;200&#8217; height=&#8217;134&#8217; alt=&#8221; title=&#8221;&gt;Il dessine rapidement la pyramide de Mike Cohn appliqué aux tests que je ne connaissais pas.&lt;/p&gt;

&lt;p&gt;Il y a quelques années la majorité des projets faisaient peu de tests unitaires, plus de tests fonctionnels et une majorité de tests graphiques (ah les fameux dossiers de recette).Aujourd&amp;#8217;hui, la tendance est à un maximum de tests unitaires et à beaucoup de tests graphiques (Selenium, robots). Hors ce type de test est coûteux en temps et dans la majorité des cas, on peut se contenter de tester les services plutôt que la couche graphique.&lt;/p&gt;

&lt;p&gt;Eric conseille de renverser la pyramide afin d&amp;#8217;avoir beaucoup de tests unitaires, un peu moins de tests fonctionnels (que l&amp;#8217;on pourrait appeler tests d&amp;#8217;intégration) et le moins possible de tests graphiques, servant uniquement à valider que la couche graphique soit fonctionnelle.&lt;/p&gt;

&lt;p&gt;Nous avons parlé d&amp;#8217;autres outils que &lt;a title=&quot;Site FitNesse&quot; href=&quot;http://fitnesse.org/&quot;&gt;FitNesse&lt;/a&gt; et &lt;a title=&quot;GreenPapper software&quot; href=&quot;http://www.greenpeppersoftware.com&quot;&gt;GreenPepper&lt;/a&gt;. Sébastien Letélié a repris la liste sur &lt;a title=&quot;Compte rendu Sébastien Lettelié&quot; href=&quot;http://www.itaware.eu/2009/01/31/javacamp-iii-tdd-et-ddd/&quot;&gt;son compte rendu du JavaCamp&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;DDD, quoi, qu&amp;#8217;est-ce ?&lt;/h2&gt;

&lt;p&gt;Cette session fut animée par Sébastien que je viens de citer. Je fais un rapide passage ici car il en a parlé &lt;a title=&quot;Article DDD de Sébastien Lettelié&quot; href=&quot;http://www.itaware.eu/2008/08/24/programmation-orientee-composite/&quot;&gt;sur son blog&lt;/a&gt; et Xebia en a fait un &lt;a title=&quot;Article DDD de Xebia&quot; href=&quot;http://blog.xebia.fr/2009/01/28/ddd-la-conception-qui-lie-le-fonctionnel-et-le-code/&quot;&gt;article dernièrement&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sébastien nous explique qu&amp;#8217;en &lt;a title=&quot;Article Wikipedia sur le Domain Driven Design&quot; href=&quot;http://en.wikipedia.org/wiki/Domain-driven_design&quot;&gt;DDD&lt;/a&gt;, on ne parle plus de classe mais d&amp;#8217;interface. Comme exemple, il cite un politicien qui a plusieurs rôles (Speaker, Décideur, Escroc). Chacun de ses rôles étant représentés par une interface qui seront combinées en Mixin qui sont en quelque sorte des classes d&amp;#8217;interface. On imagine déjà les avantages de séparer les responsabilités (testabilité) et le fait de pouvoir les combiner dynamiquement (réutilisabilité, évolutivité, souplesse).&lt;/p&gt;

&lt;h2&gt;Scrum is Evil&lt;/h2&gt;

&lt;p&gt;Réuni pour parler de Scrum en général et notre façon de le pratiquer sur nos projets, on échange rapidement nos points de vue&amp;#8230; différents. Eric est une nouvelle fois très à l&amp;#8217;aise pour discuter du sujet (voir &lt;a title=&quot;Article Eric Lefevre sur Scrum is Evil&quot; href=&quot;http://ericlefevre.net/wordpress/2008/10/07/scrum-is-evil/&quot;&gt;son article sur le sujet&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Une discussion est lancée sur la question « est-il possible d&amp;#8217;affecter certaines tâches d&amp;#8217;une itération plutôt que laisser l&amp;#8217;équipe les choisir ».&lt;/p&gt;

&lt;p&gt;Pour &lt;a title=&quot;Blog Sfeir&quot; href=&quot;http://www.insideit.fr&quot;&gt;Tarik Filali&lt;/a&gt;, il est possible que le ScrumMaster affecte une tâche à quelqu&amp;#8217;un qui pourra la mener à bien, selon la criticité de celle-ci.&lt;/p&gt;

&lt;p&gt;Pour Eric, ce n&amp;#8217;est pas conseillé. Cette action a un effet bénéfique à court terme (tâche bien réalisée et finie à temps) mais elle a un mauvais effet à long terme. En effet, que doivent penser les développeurs à qui on n&amp;#8217;a pas osé confier cette tâche ? Quel est l&amp;#8217;effet sur leur moral ?&lt;/p&gt;

&lt;p&gt;Je vous passe les détails de la discussion que nous avons eue sur le fait de rester travailler tard le soir. Quel est l&amp;#8217;effet sur le moral de l&amp;#8217;équipe si le Scrum Master reste tard ? Ne doit-il pas montrer l&amp;#8217;exemple en prouvant que les estimations ont bien été faites et que tout va bien ?&lt;/p&gt;

&lt;p&gt;Sur la partie « Scrum is Evil », Eric nous rappelle que Scrum a des mauvais côtés, mais ce n&amp;#8217;est pas la méthode elle-même, c&amp;#8217;est sa popularité. Il rappelle le système de certification pyramidal et le fait de mettre en oeuvre les pratiques de Scrum sans penser aux valeurs qui doivent venir avec (collaboration, individus &amp;amp; intéractions, logiciel fonctionnel, adaptation).&lt;/p&gt;

&lt;p&gt;Moralité : tous les mauvais côtés de Scrum se retrouvent dans les autres méthodes, donc Scrum est autant Evil que les autres :-) .&lt;/p&gt;

&lt;h2&gt;Mock ou pas Mock&lt;/h2&gt;

&lt;p&gt;Eric, très en forme ce jour-là, nous parle de trois approches :
l&amp;#8217;approche Mock où on utilise un framework de Mock (EasyMock, JmockIt&amp;#8230;) afin de vérifier le comportement de la classe en cours de test ;
l&amp;#8217;approche Stub où l&amp;#8217;on va soi-même mettre en place des fausses classes pour comparer les entrées/sorties ;
l&amp;#8217;approche « je ne teste pas les interactions mais uniquement la partie intéressante ».&lt;/p&gt;

&lt;p&gt;Cette 3ème approche mérite d&amp;#8217;être détaillée.
Imaginez que vous vouliez tester la méthode suivante :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;java&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calculeLaMoyenneDesSalaires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;employ&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;é&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sSousPay&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;é&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chargeLaListeSilTePLait&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;Pour&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chaque&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;employ&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;é&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;n&quot;&gt;ajoute&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;à&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;la&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;moyenne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;laMoyenne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Dans ce cas, on peut voir que ce qui est important dans la méthode, c&amp;#8217;est le comment on calcule la moyenne, non pas le chargement de la liste des employés. La 3ème approche consisterait à revoir le code pour avoir une méthode qui calcule la moyenne à partir d&amp;#8217;une liste d&amp;#8217;employés :&lt;/p&gt;

&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line&#8217;&gt;11&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;java&#8217;&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calculeLaMoyenneDesSalaires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;employ&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;é&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sSousPay&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;é&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chargeLaListeSilTePLait&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;moyenne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculeMoyenne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;employ&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;é&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sSousPay&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;é&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;laMoyenne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;cm&quot;&gt;/* package */&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculeMoyenne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;employ&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;é&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;Pour&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chaque&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;employ&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;é&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;        &lt;span class=&quot;n&quot;&gt;ajoute&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;à&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;la&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;moyenne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;laMoyenne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&#8217;line&#8217;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Dans cette approche, le test se passe sur la méthode &lt;em&gt;calculeMoyenne(List employés)&lt;/em&gt; et non sur la méthode appelante. L&amp;#8217;avantage est de se concentrer sur le code utile et non pas sur la glue (qu&amp;#8217;il faudrait mocker). L&amp;#8217;inconvénient principal est qu&amp;#8217;il faudra des tests d&amp;#8217;intégrations plus complets que dans une approche Mock ou Stub.&lt;/p&gt;

&lt;p&gt;L&amp;#8217;approche Mock consiste à vérifier les appels de méthode de la classe testée.  Mais nous avons tendance à tester que tous les appels sont faits, dans l&amp;#8217;ordre, avec tous les bons paramètres. Eric pense qu&amp;#8217;il ne faut pas procéder ainsi. Il vaut mieux vérifier les appels qui nous intéresse vraiment. Par exemple, vérifier que la donnée est bien chargée et sauvegardée, mais ignorer la méthode fait un appel à une autre méthode en plus (approche &lt;em&gt;NiceMock&lt;/em&gt; plutôt que &lt;em&gt;StrictMock&lt;/em&gt; chez EasyMock).&lt;/p&gt;

&lt;p&gt;L&amp;#8217;approche Stub ne permet pas de contrôler tous les appels. On est donc plus libre dans les vérifications mais moins sévère. Dans ce cas, on utilise souvent une méthode Bottom-Up, c&amp;#8217;est-à-dire qu&amp;#8217;on va plutôt partir des DAO et remonter vers les services. C&amp;#8217;est l&amp;#8217;inverse de la méthode Mock où il est possible (et conseillé) de partir des services et de mocker les classes du dessous en attendant une vraie implémentation (« Top-Down »). Cela se rapproche du TDD et influence beaucoup le design des couches basses.&lt;/p&gt;

&lt;p&gt;Nous avons comparé rapidement les différents frameworks de Mock. EasyMock est le plus populaire mais pourtant pas le meilleur. Il n&amp;#8217;est pas facile d&amp;#8217;accès et il contraint à définir le comportement avant l&amp;#8217;appel à la méthode testée, ce qui rebute au début (on s&amp;#8217;attendrait à tester après).&lt;/p&gt;

&lt;h2&gt;Une bonne journée&lt;/h2&gt;

&lt;p&gt;Mon premier JavaCamp ne sera pas le dernier. Plein de gens intéressants et motivés avec leurs expériences, cela donne un bon moment. Pas forcément de venir un samedi, mais c&amp;#8217;est tant mieux : seuls les gens motivés se déplacent :-) .&lt;/p&gt;

&lt;p&gt;Merci à tous pour ce que j&amp;#8217;ai appris ce jour-là et à &lt;a href=&quot;http://valtech.fr&quot;&gt;Valtech&lt;/a&gt; pour l&amp;#8217;organisation.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>30 secondes avec Glassfish v3</title>
    <link href="http://www.tomsquest.com/blog/2009/01/30-secondes-avec-glassfish-v3/"/>
    <updated>2009-01-15T00:00:00+01:00</updated>
    <id>http://www.tomsquest.com/blog/2009/01/30-secondes-avec-glassfish-v3</id>
    <content type="html">&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2009/01/glassfish_logo.jpg&#8217; width=&#8217;150&#8217; height=&#8217;76&#8217; alt=&#8221; title=&#8221;&gt;Retour rapide sur &lt;a href=&quot;https://glassfish.dev.java.net/&quot;&gt;Glassfish&lt;/a&gt;, le serveur d&amp;#8217;app dont on entend parler &lt;a title=&quot;Compte rendu JUG sur J2EE 6 et Glassfish&quot; href=&quot;http://www.touilleur-express.fr/2009/01/14/compte-rendu-de-la-soiree-du-paris-jug-sur-jee6-et-glassfish/&quot;&gt;un peu partout&lt;/a&gt;.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;1. Intégration avec Maven : semi-Echec&lt;/h2&gt;

&lt;p&gt;Glassfish n&amp;#8217;a apparemment pas de support de Maven officiel. Il existe quelques plugins Maven mais d&amp;#8217;après &lt;a href=&quot;http://eskatos.wordpress.com/2008/03/28/maven-plugins-for-glassfish-ecosystem/&quot;&gt;cet article&lt;/a&gt;, rien de vraiment fonctionnel à part le plugin de l&amp;#8217;auteur.&lt;/p&gt;

&lt;p&gt;J&amp;#8217;ai donc essayé le plugin Maven « &lt;a href=&quot;http://code.google.com/p/asadmin-maven-plugin/&quot;&gt;Asadmin &lt;/a&gt;» qui m&amp;#8217;a permis de déployer un War Wicket dans Glassfish. Pour info, seule la version 0.3-snapshot » de Asadmin a fonctionné.&lt;/p&gt;

&lt;p&gt;Une autre solution serait de démarrer soi-même un Glassfish via l&amp;#8217;&lt;a href=&quot;https://embedded-glassfish.dev.java.net/&quot;&gt;API Embedded&lt;/a&gt; (voir &lt;a href=&quot;http://www.tomsquest.com/blog/jetty-demarrage-rapide/#comment-11&quot;&gt;ce commentaire&lt;/a&gt; d&amp;#8217;Alexis MP). Mais apparemment, il s&amp;#8217;agit toujours de déployer un War. Il faut donc générer à chaque changement de code.&lt;/p&gt;

&lt;p&gt;Pour résumer :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Pas de plugin Maven pour Glassfish aussi facile d&amp;#8217;accès que celui de Jetty ;&lt;/li&gt;
    &lt;li&gt;Mais possibilité de déployer un War en ligne de commande facilement.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;2. Installation : succès&lt;/h2&gt;

&lt;p&gt;Le site du projet a plusieurs liens vers différents guides de démarrage qui donnent à peu près les mêmes infos.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Dézipper le zip ;&lt;/li&gt;
    &lt;li&gt;Lancer $GLASSFISH_HOME/bin/asadmin start-domain ;&lt;/li&gt;
    &lt;li&gt;Pour tester, copier l&amp;#8217;application hello.war dans le répertoire autodeploy ;&lt;/li&gt;
    &lt;li&gt;En quelques secondes, l&amp;#8217;application devient accessible ainsi que la console d&amp;#8217;admin.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Aucun problème d&amp;#8217;installation, Glassfish est très rapidement mis en place.&lt;/p&gt;

&lt;p&gt;Le démarrage est très rapide mais si on suppose vite que plein de choses se passent en tâche de fond (comme le précise la console au lancement).&lt;/p&gt;

&lt;h2&gt;3. Intégration à Eclipse : succès&lt;/h2&gt;

&lt;p&gt;L&amp;#8217;ajout d&amp;#8217;un serveur dans le WTP d&amp;#8217;Eclipse propose de télécharger des « server adaptor » additionnels, chose requise pour utiliser Glassfish. Ici encore, la &lt;a href=&quot;https://glassfishplugins.dev.java.net/eclipse34/index.html&quot;&gt;documentation&lt;/a&gt; est détaillée avec des captures d&amp;#8217;écran.&lt;/p&gt;

&lt;p&gt;Mon impatience a failli me coûter cher. La liste a mis plusieurs minutes pour trouver le connecteur Glassfish. Si ça vous arrive, allez prendre un café en attendant.&lt;/p&gt;

&lt;p&gt;Une fois le serveur ajouté, le déploiement sur Glassfish d&amp;#8217;un projet Web prend quelques secondes, démarrage du serveur compris. Une modification d&amp;#8217;une classe Java est prise en compte quasiment immédiatement.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Glassfish est facilement installable. Sa mise en place dans un projet est rapide au travers d&amp;#8217;un IDE. Il démarre en quelques secondes, aussi vite que Jetty.&lt;/p&gt;

&lt;p&gt;Pourtant sur l&amp;#8217;aspect configuration et intégration à Maven, &lt;a href=&quot;http://www.tomsquest.com/blog/jetty-demarrage-rapide/&quot;&gt;Jetty est encore imbattable&lt;/a&gt; (plugin Maven au Top et simple fichier de config pour les dataSources).&lt;/p&gt;

&lt;p&gt;Il m&amp;#8217;a manqué du temps pour tester le rechargement à chaud des classes et la persistance des sessions mais si c&amp;#8217;est aussi facile que le reste, je l&amp;#8217;adopte pour mes dév.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Critique du livre &#8220;Don&#8217;t Make Me Think&#8221;</title>
    <link href="http://www.tomsquest.com/blog/2009/01/critique-du-livre-dont-make-me-think/"/>
    <updated>2009-01-14T00:00:00+01:00</updated>
    <id>http://www.tomsquest.com/blog/2009/01/critique-du-livre-dont-make-me-think</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://sensible.com/buythebook.html&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2009/01/dmmt-cover-2nd.jpg&#8217; width=&#8217;150&#8217; height=&#8217;193&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;J&amp;#8217;ai eu le plaisir de lire le livre de Steve Krug « &lt;a href=&quot;http://sensible.com/buythebook.html&quot;&gt;Don&amp;#8217;t Make Me Think&lt;/a&gt; » dont le sujet est l&amp;#8217;usabilité Web. L&amp;#8217;usabilité, c&amp;#8217;est la conception d&amp;#8217;un site afin qu&amp;#8217;il fonctionne au mieux. Pourquoi faire un site utilisable ? Steve Krug cite sa femme : « Si quelque chose est difficile à utiliser, alors je l&amp;#8217;utilise moins ».&lt;/p&gt;

&lt;p&gt;Je cite &lt;a href=&quot;http://fr.wikipedia.org/wiki/Utilisabilit%C3%A9&quot;&gt;Wikipedia &lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;Les critères de l&amp;#8217;usabilité (ou utilisabilité) sont :
- l&amp;#8217;efficacité : le produit permet à ses utilisateurs d&amp;#8217;atteindre le résultat prévu ;
- l&amp;#8217;efficience : atteint le résultat avec un effort moindre ou requiert un temps minimal ;
- la satisfaction : confort et évaluation subjective de l’interaction pour l’utilisateur.&lt;/blockquote&gt;




&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;L&amp;#8217;auteur&lt;/h2&gt;

&lt;p&gt;Steve Krug est consultant, il aide les concepteurs d&amp;#8217;un site à le rendre plus utilisable. Il est donc payé pour établir des recommandations afin qu&amp;#8217;un visiteur trouve l&amp;#8217;information qu&amp;#8217;il cherche, puisse utiliser le service au mieux de ses possibilités ou tout simplement pour acheter plus.&lt;/p&gt;

&lt;p&gt;Il propose dans son livre des conseils pour ceux qui n&amp;#8217;ont pas les moyens d&amp;#8217;embaucher un expert comme lui dans ce domaine.&lt;/p&gt;

&lt;h2&gt;Le livre&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.amazon.fr/veux-pas-chercher-navigation-internautes/dp/274402189X&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2009/01/dmmt-cover-fr-je-ne-veux-pas-chercher.jpg&#8217; width=&#8217;100&#8217; height=&#8217;121&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;C&amp;#8217;est un bel objet, on prend plaisir à le feuilleter. Il est aéré et son contenu est bien mis en valeur. Il contient beaucoup d&amp;#8217;illustrations et de captures d&amp;#8217;écran pour montrer par exemple les d&amp;#8217;améliorations avant/après (convainquant !).&lt;/p&gt;

&lt;p&gt;Le livre a été traduit sous le titre « &lt;a href=&quot;http://www.amazon.fr/veux-pas-chercher-navigation-internautes/dp/274402189X&quot;&gt;Je ne veux pas chercher&lt;/a&gt; ».&lt;/p&gt;

&lt;h2&gt;Mon avis&lt;/h2&gt;

&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2009/01/dmmt-usability-glance.gif&#8217; width=&#8217;300&#8217; height=&#8217;157&#8217; alt=&#8221; title=&#8221;&gt; Je recommande chaudement ce livre qui se veut très simple d&amp;#8217;accès, intéressant et agréable à lire. Il m&amp;#8217;a fait prendre conscience de nombreuses choses, aussi bien sur comment les utilisateurs voient un site, que les tests utilisateurs ou encore l&amp;#8217;accessibilité. Le livre m&amp;#8217;a étonné plusieurs fois. Et ça, c&amp;#8217;est ce que je lui demandais.&lt;/p&gt;

&lt;p&gt;Il faut noter qu&amp;#8217;il est réservé à des débutants, il n&amp;#8217;y a pas de concepts très avancés.&lt;/p&gt;

&lt;p&gt;Le livre une remise à plat de ce que l&amp;#8217;on pense au niveau ergonomie et conception d&amp;#8217;un site. La première chose est qu&amp;#8217;il n&amp;#8217;y a pas de réponse toute faite (« les utilisateurs n&amp;#8217;aiment pas ça ») mais que seuls les tests utilisateurs peuvent dire ce qui fonctionne ou pas. Steve Krug nous apprend beaucoup de choses à ce sujet. Il revient sur les bases et expliquent quels sont les éléments fondamentaux d&amp;#8217;un site (son identifiant, son sous-titre, sa navigation&amp;#8230;) et comment faire en sorte que le site soit plus efficace.&lt;/p&gt;

&lt;h2&gt;Test Driven Website&lt;/h2&gt;

&lt;p&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2009/01/dmmt-webdesignfunnies1.jpg&#8217; width=&#8217;250&#8217; height=&#8217;188&#8217; alt=&#8221; title=&#8221;&gt;Un des chapitres qui m&amp;#8217;a le plus marqué dans le livre est celui où Steve Krug affirme que les discussions sur l&amp;#8217;usabilité sont une perte de temps.&lt;/p&gt;

&lt;p&gt;Pour lui, seul les tests avec des utilisateurs montrent ce qui fonctionne ou non.&lt;/p&gt;

&lt;p&gt;Pour limiter les débats au sein d&amp;#8217;une équipe (auxquels on a tous participés), il propose de se poser les bonnes questions. Ce n&amp;#8217;est pas : « Est-ce que les gens aiment les menus déroulants ? »,  mais « Est-ce que ce menu déroulant est utile dans ce contexte avec ce style et ces éléments sur cette page ? ».&lt;/p&gt;

&lt;p&gt;Et il n&amp;#8217;y a qu&amp;#8217;une seule réponse à ces débats : le test utilisateur.
Tester une page donne des réponses concrètes. On passe de « Ce qui est vrai ou faux » à « Ce qui fonctionne ou non ».
Pour Steve Krug, les tests sont donc le moyen principal de rendre un site « utilisable » (ça et les quelques règles des premiers chapitres). Un autre chapitre détaille ce qu&amp;#8217;est un test utilisateur, comment le mener (c&amp;#8217;est facile), ce que ça coûte (presque rien) et surtout ce que cela apporte (beaucoup).&lt;/p&gt;

&lt;p&gt;Un dernier mot sur le test : quand on démarre la conception d&amp;#8217;un site, il est intéressant de tester les sites concurrents. Ceux-ci servent de prototypes fonctionnels et gratuits. Intéressant, non ?&lt;/p&gt;

&lt;h2&gt;Une affaire de bon sens&lt;/h2&gt;

&lt;p&gt;Le slogan du livre est « A Common Sense Approach To Web Usability ». Pour Steve Krug, tout le monde peut améliorer son site car c&amp;#8217;est essentiellement une affaire de bon sens. Pas besoin d&amp;#8217;être un expert pour voir qu&amp;#8217;un titre de page doit ressembler à un titre de page et qu&amp;#8217;il doit encadrer le contenu.
Cet aspect « bon sens » se retrouve dans chaque chapitre. L&amp;#8217;auteur a réussi  parfaitement son exercice de vulgarisation.&lt;/p&gt;

&lt;h2&gt;L&amp;#8217;accessibilité&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://sensible.com/&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2009/01/screenshot001.jpg&#8217; width=&#8217;200&#8217; height=&#8217;203&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;Steve Krug expliquent que les aveugles scannent les pages, comme nous le faisons, mais de manière auditive. Les « screen readers » qui lisent les pages sont réglés pour lire très rapidement les premiers mots des phrases, permettant à l&amp;#8217;utilisateur de sauter de section en section.
L&amp;#8217;accessibilité est un sujet important, mais il pense qu&amp;#8217;il demande beaucoup d&amp;#8217;efforts qui seront comblés par les outils et la technologie. Il ne s&amp;#8217;attarde pas sur le sujet, mais il propose des références annexes.&lt;/p&gt;

&lt;h2&gt;Quelques points négatifs&lt;/h2&gt;

&lt;ul&gt;
    &lt;li&gt;Certaines affirmations ne sont pas prouvées. Quelques fois certaines choses sont exprimées comme des faits alors qu&amp;#8217;elles sont une opinion de l&amp;#8217;auteur. J&amp;#8217;aurai donc aimé qu&amp;#8217;il cite ses sources.&lt;/li&gt;
    &lt;li&gt;Le chapitre « Mon boss me dit de faire » aurait mérité d&amp;#8217;être plus étoffé. Dans ce chapitre, Steve Krug cite des arguments qui permettent de lutter contre un manager qui veut demander beaucoup d&amp;#8217;infos personnelles au moment de l&amp;#8217;inscription ou encore qui veut ajouter une multitude d&amp;#8217;éléments Bling-bling inutiles. Ce chapitre est trop court.&lt;/li&gt;
    &lt;li&gt;Le &lt;a href=&quot;http://sensible.com&quot;&gt;site de l&amp;#8217;auteur&lt;/a&gt; est pauvre. Dommage pour quelqu&amp;#8217;un qui donne des conseils sur la conception d&amp;#8217;un site. J&amp;#8217;aurais aimé trouver d&amp;#8217;autres exemples de ce qu&amp;#8217;il a accompli ailleurs (quitte à changer les logos et couleurs).&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>ClearCase : changer le comparateur de fichier</title>
    <link href="http://www.tomsquest.com/blog/2008/12/clearcase-changer-le-comparateur-de-fichier/"/>
    <updated>2008-12-30T00:00:00+01:00</updated>
    <id>http://www.tomsquest.com/blog/2008/12/clearcase-changer-le-comparateur-de-fichier</id>
    <content type="html">&lt;p&gt;L&amp;#8217;astuce du jour est : &amp;#8220;se passer de ClearCase pour comparer les fichiers&amp;#8221;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www-01.ibm.com/software/awdtools/clearcase/&quot;&gt;ClearCase&lt;/a&gt; permet de comparer les différences entres les versions de fichier avec ses propres outils.
Mais les comparateurs proposés par défaut de ClearCase ne sont pas les meilleurs. Il y a des outils plus souples comme &lt;a href=&quot;http://winmerge.org/&quot;&gt;WinMerge&lt;/a&gt;.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Comment faire ?&lt;/h2&gt;

&lt;p&gt;Pour associer tous les fichiers texte (Java et autres) avec WinMerge, il suffit d&amp;#8217;éditer le fichier &lt;em&gt;$CLEARCASE_HOME\Rational\ClearCase\lib\mgrs\map&lt;/em&gt; et de remplacer :&lt;/p&gt;

&lt;figure role=code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;div class=&#8217;line&#8217;&gt;text_file_delta xcompare ..&#46;.\bin\cleardiffmrg.exe&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;par :&lt;/p&gt;

&lt;figure role=code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;div class=&#8217;line&#8217;&gt;text_file_delta xcompare D:\Softs\WinMerge\WinMerge.exe&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Ce qui donne avant et après :&lt;/p&gt;

&lt;p&gt;&lt;img class=&#8221; src=&#8217;http://www.tomsquest.com/images/posts/2008/12/clearcase_compare_xml.jpg&#8217; width=&#8217;301&#8217; height=&#8217;201&#8217; alt=&#8221; title=&#8221;&gt;
&lt;img class=&#8221; src=&#8217;http://www.tomsquest.com/images/posts/2008/12/winmerge_compare_xml.jpg&#8217; width=&#8217;300&#8217; height=&#8217;166&#8217; alt=&#8221; title=&#8221;&gt;&lt;/p&gt;

&lt;p&gt;Les autres formats de fichier comme le HTML et le XML peuvent être également modifiés.
Il suffit de remplacer les lignes qui contiennent &amp;#8220;xcompare&amp;#8221;.
Exemple :&lt;/p&gt;

&lt;figure role=code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217; width=&#8217;100%&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;div class=&#8217;line&#8217;&gt;_xml xcompare    ..&#46;.\bin\xmldiffmrg.exe&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Bonne année 2009 !&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Présentation et retour sur GreenPepper</title>
    <link href="http://www.tomsquest.com/blog/2008/12/presentation-et-retour-sur-greenpepper/"/>
    <updated>2008-12-21T00:00:00+01:00</updated>
    <id>http://www.tomsquest.com/blog/2008/12/presentation-et-retour-sur-greenpepper</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.greenpeppersoftware.com&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2008/12/greenpepper-logo.gif&#8217; width=&#8217;130&#8217; height=&#8217;66&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;Au boulot, nous évaluons &lt;a href=&quot;http://www.greenpeppersoftware.com&quot;&gt;GreenPepper&lt;/a&gt; de la société &lt;a href=&quot;http://www.pyxis-tech.com/fr/&quot;&gt;Pyxis&lt;/a&gt;. GreenPepper est un outil de test fonctionnel et nous souhaitons à terme que les MOA l&amp;#8217;utilisent afin de rédiger les spécifications et les tests associés.&lt;/p&gt;

&lt;p&gt;Nous ne sommes qu&amp;#8217;en phase de POC technique et nous avons rencontré quelques soucis. Je vous fais mon retour au bout d&amp;#8217;une semaine avec GreenPepper.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Spécification exécutable&lt;/h2&gt;

&lt;p&gt;La base de GreenPepper est le concept de spécification exécutable. Une spec est dite exécutable quand elle fournit directement les cas de tests qui permettent de la valider et que ceux-ci sont exécutables afin de déterminer si les règles sont bien implémentées. Le site du projet héberge une &lt;a href=&quot;http://www.greenpeppersoftware.com/greenpepper-whatsin-videos/whatis-es/index.html&quot;&gt;vidéo de présentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dans la pratique, la création d&amp;#8217;une spécification exécutable avec GreenPepper prend la forme suivante :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt; La MOA se connecte au Wiki et exprime sa règle métier en bon français ;&lt;/li&gt;
    &lt;li&gt;Elle décrit également comment tester la fonctionnalité. La syntaxe se fait à base de tableaux qui permettent au système d&amp;#8217;extraire les méthodes et données de test à utiliser ;&lt;/li&gt;
    &lt;li&gt;L&amp;#8217;équipe de développement écrit ensuite le liant entre la page de test et le code réel. Ce branchement est appelé « fixture ».&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Exemple de spécification fonctionnelle&lt;/h3&gt;

&lt;p&gt;&lt;img class=&#8217;center &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2008/12/gp-test2.jpg&#8217; width=&#8217;500&#8217; height=&#8217;351&#8217; alt=&#8221; title=&#8221;&gt;&lt;/p&gt;

&lt;p&gt;Chaque page GreenPepper dispose d&amp;#8217;un bouton « Execute » qui permet d&amp;#8217;appeler les fixtures avec les paramètres du tableau. L&amp;#8217;appui sur ce bouton invoque le système testé qui récupère dans la page les classes à créer et invoque les méthodes avec les données.&lt;/p&gt;

&lt;p&gt;Dans l&amp;#8217;exemple ci-dessus, GreenPepper instancie la classe Cart et invoque deux fois la méthode « add » avec en paramètre « Persian Cat » puis « Dalmation » et enfin invoque la méthode numberOfItems. Celle-ci doit retourner 2. Si ce n&amp;#8217;est pas le cas, la case du tableau sera coloriée en rouge ou en vert si le résultat est valide.&lt;/p&gt;

&lt;h2&gt;Le coin de la technique&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.tomsquest.com/blog/wp-content/uploads/2008/12/logo-confluence.gif&quot;&gt;&lt;img class=&#8217;right &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2008/12/logo-confluence.gif&#8217; width=&#8217;80&#8217; height=&#8217;61&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;GreenPepper est en réalité un plugin pour &lt;a href=&quot;http://www.atlassian.com/software/confluence/&quot;&gt;Confluence&lt;/a&gt;, le wiki édité par Atlassian.&lt;/p&gt;

&lt;p&gt;C&amp;#8217;est LA différence avec &lt;a href=&quot;http://fitnesse.org/&quot;&gt;FitNesse&lt;/a&gt;, un autre outil très populaire de test fonctionnel. FitNesse embarque son propre serveur Web et son propre Wiki. Chez Pyxis, il a été décidé de s&amp;#8217;appuyer sur un outil existant, réputé et fiable.&lt;/p&gt;

&lt;p&gt;GreenPepper se contente donc de rentre les pages du Wiki Confluence testables en leur ajoutant des macros et le fameux bouton « Execute » vu plus haut.&lt;/p&gt;

&lt;h2&gt;Qualités de GreenPepper&lt;/h2&gt;

&lt;p&gt;GreenPepper, c&amp;#8217;est avant tout Confluence. Ce dernier apporte une plateforme puissante permettant à tous les acteurs de communiquer autour du logiciel. C&amp;#8217;est un wiki donc il apporte des notions de collaboration, de versionning et de partage.&lt;/p&gt;

&lt;p&gt;GreenPepper s&amp;#8217;intègre également avec Jira, un autre produit Atlassian permettant de faire du bug tracking. On peut donc imaginer avoir un rapport de bug lié à une page de spécification qui contient le test permettant de reproduire le bug.&lt;/p&gt;

&lt;p&gt;L&amp;#8217;écriture des fixtures peut se faire en Java et en .Net. Une fixture est une simple classe et GreenPepper ne pose aucune contrainte à ce niveau. Le produit propose aussi de créer un SUD (System Under Developement) permettant de réaliser des actions quand une fixture est instanciée/libérée (sorte de « setUp/tearDown »), d&amp;#8217;enregistrer des convertisseurs (par exemple, convertir un numéro de client en Client) et d&amp;#8217;importer des packages de fixture par défaut. Dans notre SUD actuel, nous démarrons également le contexte Spring afin d&amp;#8217;injecter les beans dans les fixtures.&lt;/p&gt;

&lt;h2&gt;Problèmes rencontrés&lt;/h2&gt;

&lt;p&gt;Nous avons rencontré plusieurs problèmes avec GreenPepper. Nous étions très confiants pour un produit « packagé » comme GreenPepper, mais la machine fut difficile à démarrer.&lt;/p&gt;

&lt;h3&gt;La documentation&lt;/h3&gt;

&lt;p&gt;Le plus gros point noir du produit est sa documentation. Elle forme un patchwork difficile à ingérer. On trouve des exemples mais pas toujours le code associé. Certaines fixtures sont détaillées, mais je n&amp;#8217;ai pas trouvé les exemples simples ni percutants.&lt;/p&gt;

&lt;p&gt;La courbe d&amp;#8217;apprentissage n&amp;#8217;est donc pas basse. C&amp;#8217;est laborieux. La documentation est difficilement compréhensible à la première lecture, voir à la deuxième. Après quelques jours, je commence enfin à en comprendre certaines sections.&lt;/p&gt;

&lt;p&gt;Un exemple vécu lors de l&amp;#8217;installation : le « step by step » est simple à suivre mais rien ne fonctionnait à la fin. Nous avons du désinstaller le plugin GreenPepper et le réinstaller différemment de ce qui est précisé dans la documentation. Pour cela, il a fallu chercher dans les forums afin de voir qu&amp;#8217;il était conseillé d&amp;#8217;installer le plugin directement dans WEB-INF/lib (plutôt que par l&amp;#8217;installateur Confluence comme indiqué dans la doc).&lt;/p&gt;

&lt;h3&gt;Le plugin Eclipse&lt;/h3&gt;

&lt;p&gt;Le plugin permet de rapatrier les pages de tests et de les exécuter localement. Il offre la possibilité de générer le squelette des fixtures à partir des pages.&lt;/p&gt;

&lt;p&gt;Beaucoup d&amp;#8217;options sont proposées et on a du mal à savoir quoi mettre. Il faut un répertoire de spécs que je n&amp;#8217;ai pas. Un SUT ? Non, je n&amp;#8217;en ai pas (encore). Et le classpath, j&amp;#8217;ai celui d&amp;#8217;Eclipse, pourquoi j&amp;#8217;en utiliserai un autre ?&lt;/p&gt;

&lt;p&gt;Au bout de quelques heures, ça fonctionne à peu près. Entre temps, on a essayé toutes les options dans tous les sens. C&amp;#8217;est rigolo 5 minutes.&lt;/p&gt;

&lt;p&gt;A titre d&amp;#8217;info, voilà la procédure :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt; Ecrire sa page dans Confluence et la marquer comme « Implemented » ;&lt;/li&gt;
    &lt;li&gt; Rafraichir la vue « Repository » dans Eclipse : la page apparaît ;&lt;/li&gt;
    &lt;li&gt; Executer une première fois la page depuis le menu de cette vue ;&lt;/li&gt;
    &lt;li&gt; Ouvrir avec le WebBrowser d&amp;#8217;Eclipse le HTML de la page crée plus haut (répertoire /greenpepper) ;&lt;/li&gt;
    &lt;li&gt; Executer la page une deuxième fois mais depuis le menu Run d&amp;#8217;Eclipse ;&lt;/li&gt;
    &lt;li&gt; La page doit enfin montrer les résultats (du jaune si les fixtures n&amp;#8217;exisente pas) ;&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Autres points :&lt;/h3&gt;

&lt;ul&gt;
    &lt;li&gt; Le plugin Eclipse n&amp;#8217;est pas stable. La vue se freeze de temps en temps ;&lt;/li&gt;
    &lt;li&gt;Il est en version bêta depuis un moment ;&lt;/li&gt;
    &lt;li&gt;Eclipse 3.4 n&amp;#8217;est pas supporté mais il s&amp;#8217;est installé sans soucis.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Capture du lancement depuis Eclipse&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://www.greenpeppersoftware.com/confluence/download/attachments/4783/Result.JPG&quot;&gt;&lt;img class=&#8217;center &#8217; src=&#8217;http://www.tomsquest.com/images/posts/2008/12/gp-runeclipse.jpg&#8217; width=&#8217;500&#8217; height=&#8217;420&#8217; alt=&#8221; title=&#8221;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Le classpath et Maven&lt;/h3&gt;

&lt;p&gt;Je n&amp;#8217;ai pas mis en place cette partie là sur notre projet actuel donc j&amp;#8217;ai peu à en dire. Ah si, une chose : beaucoup de sueur.&lt;/p&gt;

&lt;p&gt;Le plugin Maven permet de construire le classpath contenant l&amp;#8217;ensemble des dépendances pour permettre à GreenPepper d&amp;#8217;appeler les fixtures qui utilisent les classes de votre projet.&lt;/p&gt;

&lt;p&gt;Comme pour le plugin Eclipse, il a fallu batailler pour comprendre la doc, savoir quels paramètres saisir et comment configurer le SUT dans le plugin GreenPepper de Confluence (ne cherchez pas de définition de SUT dans la doc, il n&amp;#8217;y en a pas).&lt;/p&gt;

&lt;p&gt;Et quand ça ne fonctionne pas, il est difficile de trouver les erreurs et les exceptions remontées.&lt;/p&gt;

&lt;h2&gt;Quelques conseils autour de GreenPepper&lt;/h2&gt;

&lt;p&gt;Eric Pantera, d&amp;#8217;&lt;a href=&quot;http://www.octo.com/&quot;&gt;Octo Technology&lt;/a&gt;, est venu nous faire un retour sur GreenPepper. Il l&amp;#8217;utilise depuis 10 mois chez un de ses clients.&lt;/p&gt;

&lt;p&gt;Comme nous, l&amp;#8217;équipe a eu beaucoup de mal à mettre en place l&amp;#8217;outil. Mais dès les premières itérations, ils ont commencé à sentir d&amp;#8217;énormes gains : leur communication s&amp;#8217;est largement améliorée, tous les acteurs y voient plus clair, les MOA produisent les tests permettant d&amp;#8217;éprouver le système et le logiciel est au final  beaucoup plus fiable.&lt;/p&gt;

&lt;p&gt;Pour accélérer la mise en place de GreenPepper, Eric nous a conseillé de :&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt; Soigner la HomePage. Au début du projet, il faut donner envie. La MOA va devoir se former à un nouvel outil et un Wiki est toujours un peu complexe. Il faut lutter contre la résistance au changement et montrer les avantages de cette solution ;&lt;/li&gt;
    &lt;li&gt; Laisser libre la MOA pour les premières pages, puis repasser derrière et compléter les tests avec les noms des fixtures, par exemple. La MOA voit ensuite les modifications et utilisent celles-ci pour les tests suivants. Il faut donc éviter un maximum de restreindre la MOA à ses débuts.&lt;/li&gt;
    &lt;li&gt;Regarder les plugins Confluence. Certains sont très utiles comme le plugin Office permettant d&amp;#8217;éditer ses pages depuis Word ;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Pour résumer, GreenPepper est un produit très intéressant, mais qui souffre d&amp;#8217;une documentation défaillante. Il offre de nombreux avantages comme l&amp;#8217;intégration à Confluence, le plugin Eclipse et le support de Maven. La mise en place est déroutante car elle est laborieuse.&lt;/p&gt;

&lt;p&gt;D&amp;#8217;autre part, le produit évolue lentement. Les pages de documentation datent pour une bonne partie de 2007 et la dernière news du site concernant GreenPepper date de janvier 2008.&lt;/p&gt;

&lt;p&gt;Une question reste : est-ce que son concurrent direct, &lt;a href=&quot;http://fitnesse.org/&quot;&gt;FitNesse&lt;/a&gt;, fait mieux ?&lt;/p&gt;
</content>
  </entry>
  
</feed>

