<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
 <title>Matteo Caprari</title>
 
 <link href="http://caprazzi.net" />
 <updated>2011-08-05T14:52:37+00:00</updated>
 <id>http://caprazzi.net/</id>
 <author>
   <name>Matteo Caprari</name>
   <email>matteo.caprari@gmail.com</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/MatteoCaprari" /><feedburner:info uri="matteocaprari" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>The Slow Motion Syndrome</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/WOUrdorGqCE/if-stuck-do-something-else" />
   <updated>2011-08-05T00:00:01+00:00</updated>
   <id>http://caprazzi.net//posts/if-stuck-do-something-else</id>
   <content type="html">&lt;p&gt;Some days it's hard to focus, to-do lists grow long, emails go unread and the
ours slowly go by. I call it the Slow Motion Syndrome.&lt;/p&gt;

&lt;p&gt;Maybe you have had it too sometimes: you slow down for some reason
and slip to a low point from where you can't climb out. Stuff accumulates,
catching up becomes difficult and you end up short of breath and nothing much done.&lt;/p&gt;

&lt;p&gt;While it's ok to have few slow days, if it goes on for some time, it gets really
difficult to shake it off.&lt;/p&gt;

&lt;p&gt;I have not found a way to prevent it, but I have developed  a strategy
to get back on track.&lt;/p&gt;

&lt;h1&gt;1: Today I'm useless and I have to live with that&lt;/h1&gt;

&lt;p&gt;Do not start dunking coffee to counter it; no coffee or tea at all is best.
Do not set &lt;em&gt;any&lt;/em&gt; goals for the day, small or big. Do not even pretend you
are working. Stay at home if you can. Walk slowly.&lt;/p&gt;

&lt;p&gt;Just accept that today is slow.&lt;/p&gt;

&lt;h1&gt;2: Get bored&lt;/h1&gt;

&lt;p&gt;Do not try to kill time. Do not do anything that you don't feel strongly about:
no going on random wikipedia pages, no cleaning your inbox, no reading old xkcd
comics. No fake work, especially.&lt;/p&gt;

&lt;p&gt;Stare at the screen if you have to. I mean it.&lt;/p&gt;

&lt;h1&gt;3: Do one thing&lt;/h1&gt;

&lt;p&gt;After some time of total boredom, your brain will be screaming for action and
will be piping out with ideas. With some luck you'll remember something that you
always wanted to do if you only had time: learn a new language, learn a new
&lt;em&gt;programming&lt;/em&gt;  language, resolve a Rubik cube, start a blog, whatever.&lt;/p&gt;

&lt;p&gt;Well, &lt;em&gt;now&lt;/em&gt; you &lt;em&gt;have&lt;/em&gt; the time, so get to it. With some luck you'll get into it
and cycle up to higher activity level. Once you get there, you'll naturally pick
up your other stuff.&lt;/p&gt;

&lt;p&gt;Do you suffer from SMS? Do you have an exit strategy?&lt;/p&gt;

&lt;p&gt;-teo&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/WOUrdorGqCE" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/if-stuck-do-something-else</feedburner:origLink></entry>
 
 <entry>
   <title>Getting to know the Java JIT compiler</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/cnFCQ7TpdN8/jit-compiler-part-1" />
   <updated>2011-06-30T19:00:39+00:00</updated>
   <id>http://caprazzi.net//posts/jit-compiler-part-1</id>
   <content type="html">&lt;p&gt;What is the Java JIT compiler? How does it affect my programs? Should I care?
I've looked for answers to this questions and this is what I found.&lt;/p&gt;

&lt;h2&gt;The JIT is in&lt;/h2&gt;

&lt;p&gt;Most java VMs have a built in Just In Time compiler ("the JIT").&lt;/p&gt;

&lt;p&gt;The JIT analyzes the behaviour of a program while it runs and looks for
opportunities to optimize the bytecode and re-compile it to machine code using
the most appropriate native instruction. All mainstream java VMs have a JIT
compiler and you can bet that all your java programs are using it right now.&lt;/p&gt;

&lt;p&gt;The JIT is awesome and magical and very opaque and the gains will be different
on different machines, VMs and configurations.&lt;/p&gt;

&lt;p&gt;The JIT is on by default, but it can be disabled using &lt;code&gt;-Djava.compiler=none&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Because it is opaque and unpredictable, it is generally a bad idea to rely on
it for the performance of a program. Still, it is interesting to see it at work.&lt;/p&gt;

&lt;h2&gt;But is it faster?&lt;/h2&gt;

&lt;p&gt;Let's first work out if this JIT optimization works at all.&lt;/p&gt;

&lt;p&gt;I just added &lt;code&gt;-Djava.compiler=none&lt;/code&gt; to my eclipse.ini and restarted it. Itfeels slower on "big operations" like clean &amp;amp; rebuild all or searching for the string "this" in all java files in the workspace.&lt;/p&gt;

&lt;p&gt;That's good but very difficult to measure.&lt;/p&gt;

&lt;p&gt;This is simple class that does some float multiplcations&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;       
    &lt;span class="kt"&gt;int&lt;/span&gt;  &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parseInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]);&lt;/span&gt;     
    &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Run &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; times with JIT &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;...\t&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;        
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nanoTime&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nanoTime&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;                                        
    &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;completed in &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; nanoseconds &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;      
&lt;span class="o"&gt;}&lt;/span&gt;    
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And this is a simple script that executes the code alternatively with the JIT ON and OFF:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50000000
&lt;span class="k"&gt;for &lt;/span&gt;i in &lt;span class="k"&gt;$(&lt;/span&gt;seq 5&lt;span class="k"&gt;)&lt;/span&gt;; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="k"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-----&amp;quot;&lt;/span&gt;
    java -cp bin net.caprazzi.WWJD &lt;span class="nv"&gt;$COUNT&lt;/span&gt; ON
    java -Djava.compiler&lt;span class="o"&gt;=&lt;/span&gt;none -cp bin net.caprazzi.WWJD &lt;span class="nv"&gt;$COUNT&lt;/span&gt; OFF
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;It's immediately clear that with the JIT on, the execution is reliably 50 times faster:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ sh test.sh
1-----
Run 50000000 times with JIT ON...       completed in 166548543 nanoseconds
Run 50000000 times with JIT OFF...      completed in 8765290860 nanoseconds
2-----
Run 50000000 times with JIT ON...       completed in 161432520 nanoseconds
Run 50000000 times with JIT OFF...      completed in 8775846265 nanoseconds
3-----
Run 50000000 times with JIT ON...       completed in 180772121 nanoseconds
Run 50000000 times with JIT OFF...      completed in 9166550254 nanoseconds
4-----
Run 50000000 times with JIT ON...       completed in 152595716 nanoseconds
Run 50000000 times with JIT OFF...      completed in 8824074862 nanoseconds
5-----
Run 50000000 times with JIT ON...       completed in 157337479 nanoseconds
Run 50000000 times with JIT OFF...      completed in 8738365122 nanoseconds
&lt;/pre&gt;


&lt;p&gt;Cool. Let's change the code a bit and try again:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;floats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;floats&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;br/&gt;




&lt;pre class="terminal"&gt;
Run 50000000 times with JIT ON...       completed in 102871363 nanoseconds
Run 50000000 times with JIT OFF...      completed in 9154895167 nanoseconds
&lt;/pre&gt;


&lt;p&gt;Sweet, here the optimized version is 80 times faster.&lt;/p&gt;

&lt;h2&gt;Always always faster faster?&lt;/h2&gt;

&lt;p&gt;This code was tested on an laptop with an intel multicore processor and
windows 7 (java version: &lt;s&gt;sun&lt;/s&gt; oracle 6.0.26, client VM, 32 bit)&lt;/p&gt;

&lt;p&gt;Let's see what happens when we run it on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A scruffy linux virtual box, java OpenJDK 6 client VM 32 bit 6.0.20&lt;/li&gt;
&lt;/ul&gt;


&lt;pre class="terminal"&gt;
Run 50000000 times with JIT ON...       completed in 17990143548 nanoseconds
Run 50000000 times with JIT OFF...      completed in 27172812381 nanoseconds
&lt;/pre&gt;


&lt;p&gt;Boooo - that's just 1.5 times faster!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A different linux virtual box, java oracle 6.0.20, server VM, 64 bit&lt;/li&gt;
&lt;/ul&gt;


&lt;pre class="terminal"&gt;
Run 50000000 times with JIT ON...       completed in 305513000 nanoseconds
Run 50000000 times with JIT OFF...      completed in 2135685000 nanoseconds
&lt;/pre&gt;


&lt;p&gt;Mhhhh - 7 times faster.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A 1997 Mac Pro, oracle 6.0.24, server VM, 64 bit&lt;/li&gt;
&lt;/ul&gt;


&lt;pre class="terminal"&gt;
Run 50000000 times with JIT ON...       completed in 435386000 nanoseconds
Run 50000000 times with JIT OFF...      completed in 1844200000 nanoseconds 
&lt;/pre&gt;


&lt;p&gt;That's 4 times faster.&lt;/p&gt;

&lt;p&gt;Ok, so there is a definite but very variable performance loss in handling floats and array when turning off the JIT.&lt;/p&gt;

&lt;h2&gt;Let's try with strings&lt;/h2&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;charAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Windows 7, intel cpu, java client VM 6.0.26: &lt;strong&gt;no difference&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;pre class="terminal"&gt;
Run 50000 times with JIT ON...  completed in 1859603439 nanoseconds
Run 50000 times with JIT OFF... completed in 1832164432 nanoseconds
&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;linux virtual box, java 6.0.20, server vm 64 bit, &lt;strong&gt;1.4x&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;pre class="terminal"&gt;
Run 50000 times with JIT ON...  completed in 1362850000 nanoseconds
Run 50000 times with JIT OFF... completed in 2003949000 nanoseconds
&lt;/pre&gt;


&lt;p&gt;Magic magic magic&lt;/p&gt;

&lt;h2&gt;The JIT can speak&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;-XX:-PrintCompilation&lt;/code&gt; is an option to the Oracle's VM supports that makes the jit output some information on what it compiles a method. This allows to see how the JIT intervenes differently on each run of the same program.&lt;/p&gt;

&lt;p&gt;If we execute our test 1 time, we see no output:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ java -XX:+PrintCompilation -cp bin net.caprazzi.WWJD 1 ON
Run 1 times with JIT ON...      completed in 23000 nanoseconds  
&lt;/pre&gt;


&lt;p&gt;I've incremented the size of the test loop until at 3250 iterations we start seeing some output:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ java -XX:+PrintCompilation -cp bin net.caprazzi.WWJD 3250 ON
Run 4000 times with JIT ON...   ---   n   java.lang.System::arraycopy (static)
completed in 40601000 nanoseconds
&lt;/pre&gt;


&lt;p&gt;At 4500 iteration, more output:&lt;/p&gt;

&lt;pre class="terminal"&gt;
    n   java.lang.System::arraycopy (static)
    1   java.lang.Object::&lt;init&gt; (1 bytes)
&lt;/pre&gt;


&lt;p&gt;At 5000:&lt;/p&gt;

&lt;pre class="terminal"&gt;
    n   java.lang.System::arraycopy (static)
    1       java.lang.Object::&lt;init&gt; (1 bytes)
    2       java.lang.String::getChars (66 bytes)
    3       java.lang.AbstractStringBuilder::append (60 bytes)
    4       java.lang.StringBuilder::append (8 bytes)
&lt;/pre&gt;


&lt;p&gt;10000:&lt;/p&gt;

&lt;pre class="terminal"&gt;
    n   java.lang.System::arraycopy (static)
    1       java.lang.Object::&lt;init&gt; (1 bytes)
    2       java.lang.String::getChars (66 bytes)
    3       java.lang.AbstractStringBuilder::append (60 bytes)
    4       java.lang.StringBuilder::append (8 bytes)
    5       java.lang.Math::min (11 bytes)
    6       java.lang.String::&lt;init&gt; (72 bytes)
    7       java.util.Arrays::copyOfRange (63 bytes)
    8       java.lang.AbstractStringBuilder::&lt;init&gt; (12 bytes)
    9       java.lang.StringBuilder::toString (17 bytes)
    10       java.lang.String::valueOf (14 bytes)
    11       java.lang.StringBuilder::&lt;init&gt; (18 bytes)
&lt;/pre&gt;


&lt;p&gt;And finally, at 15000 the most verbose yet:&lt;/p&gt;

&lt;pre class="terminal"&gt;
    n   java.lang.System::arraycopy (static)
    1       java.lang.Object::&lt;init&gt; (1 bytes)
    2       java.lang.String::getChars (66 bytes)
    3       java.lang.AbstractStringBuilder::append (60 bytes)
    4       java.lang.StringBuilder::append (8 bytes)
    5       java.lang.Math::min (11 bytes)
    6       java.lang.String::&lt;init&gt; (72 bytes)
    7       java.util.Arrays::copyOfRange (63 bytes)
    8       java.lang.AbstractStringBuilder::&lt;init&gt; (12 bytes)
    9       java.lang.StringBuilder::toString (17 bytes)
    10       java.lang.String::valueOf (14 bytes)
    11       java.lang.StringBuilder::&lt;init&gt; (18 bytes)
    12       java.lang.String::toString (2 bytes)
    1%      net.caprazzi.WWJD::main @ 59 (133 bytes)
&lt;/pre&gt;


&lt;h1&gt;But what is it trying to say?&lt;/h1&gt;

&lt;p&gt;I found little info about decoding this output, but from what  I can
understand, each line shows a  method that has been compiled to native code and
a progressive id. 1% at the end means that WWJD::main has used "On stack
replacement". I have ino idea of what 'n' means.&lt;/p&gt;

&lt;p&gt;The little I know about -XX:+PrintCompilation, I got it from &lt;a href="http://www.infoq.com/articles/java-threading-optimizations-p2"&gt;Do Java 6
threading optimizations actually work? - Part
II&lt;/a&gt;. The article
is excellent and a hard read. It links two detailed explaination of
PrintCompilation output, but they are both dead.&lt;/p&gt;

&lt;h1&gt;So what?&lt;/h1&gt;

&lt;p&gt;Ok, so we have seen that &lt;em&gt;the JIT is definitely there&lt;/em&gt;, that it &lt;strong&gt;can&lt;/strong&gt; make a
program faster, but that it's difficult to gauge how much so, and with a so wide range of possible outcomes the safest strategy is to assume that the JIT won't gain you anything.&lt;/p&gt;

&lt;p&gt;This post is far from a complete exploration of the JIT, and it raises more
questions than it answers. While writing I found a lot of interesting cues and
I'll be back with more stuff once I have followed them.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/cnFCQ7TpdN8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/jit-compiler-part-1</feedburner:origLink></entry>
 
 <entry>
   <title>Enforcing design principles in software</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/nlOGJYNM1tw/enforcing-design-principles-in-software" />
   <updated>2011-06-27T17:33:31+00:00</updated>
   <id>http://caprazzi.net//posts/enforcing-design-principles-in-software</id>
   <content type="html">&lt;p&gt;Before starting to write a new piece of software, I come up with some simple design principles that I think will do some good.
For smallish projects I just keep the principles in mind and behave so, but for bigger stuff I try to actively enforce the policy.&lt;/p&gt;

&lt;blockquote&gt;"In theory, theory and practice are the same. In practice, they are not."
&lt;br/&gt;
    --  Lawrence Peter Berra&lt;/blockquote&gt;


&lt;p&gt;Actively "defending" your code from your own mistakes is controversial;
in theory if you stick to a principle, there is no need for enforcement. A &lt;a href="http://blog.acaro.org/"&gt;friend of mine&lt;/a&gt; &lt;strong&gt;has never written a single bug in his life.&lt;/strong&gt; (It's true, I swear). He clearly can go without a safety net.&lt;/p&gt;

&lt;p&gt;Another friend added that proper code testing makes enforcement useless.&lt;/p&gt;

&lt;p&gt;I hate to admit it, but I do do bugs sometimes, and some tests I wrote turned
out to be not so great. I've learnt that I'm a better coder
when there are some safety checks. One immediate benefit is that checking
rules makes me less likely to cut corners "just this once".&lt;/p&gt;

&lt;p&gt;More deeply, I find that established check policies, much like widely used vaccines, have the potential to eradicate some categories of bugs.&lt;/p&gt;

&lt;h2&gt;No country for nulls&lt;/h2&gt;

&lt;p&gt;The principle I use most frequently is &lt;em&gt;nulls are no good&lt;/em&gt;. Nulls are the
source of Null Pointer Exceptions (NPE) and null checks. NPEs are a pain
because they tend to happen far from where the assignment has happened, while
null checks are just plain ugly. &lt;em&gt;If I could, I would change the language and
remove the concept of nullability&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Failing that, I have to turn the principle in a rule and implement it in the
code. At first the best rule may seem "&lt;code&gt;always check for nullity&lt;/code&gt;", but
I'll show that in this case it is enough to implement half of the rule
to cover your ass: "never assign a null"&lt;/p&gt;

&lt;h2&gt;Never assign a null&lt;/h2&gt;

&lt;p&gt;Let’s begin with an example - everybody likes the bang of a popping balloon, so I have implemented a balloons collection that allows to pop many balloons at once for a bigger, better bang.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Balloons&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Balloon&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;balloons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Balloon&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addBalloon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Balloon&lt;/span&gt; &lt;span class="n"&gt;balloon&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;balloons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;balloon&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pinchAll&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Balloon&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;balloons&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                   &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pinch&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Balloons&lt;/span&gt; &lt;span class="n"&gt;balloons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Balloons&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;balloons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addBalloon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Balloon&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;balloons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addBalloon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// one of your little helpers has run out of gas&lt;/span&gt;
        &lt;span class="n"&gt;balloons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pinchAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Not only this program will end in NPE, but also the stack trace will not clarify were the null comes from:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Exception in thread "main" java.lang.NullPointerException
at Balloons.pinchAll(Balloons.java:16)
at Balloons.main(Balloons.java:23)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To get rid of the NPE, you can just add a nullcheck inside pinchAll.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pinchAll&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Balloon&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;balloons&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pinch&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;True, this version avoids the exception, but if you ignore null values, &lt;em&gt;you’re better off not putting them in your collection in the first place&lt;/em&gt;, yes?&lt;/p&gt;

&lt;p&gt;Let’s try again:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addBalloon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Balloon&lt;/span&gt; &lt;span class="n"&gt;balloon&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;balloon&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;trow&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;balloon&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;balloons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;balloon&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Much better now: the output will actually help to pin down the cause of the problem.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Exception in thread "main" java.lang.IllegalArgumentException: 
    balloon must not be null
at Balloons.addBalloon(Balloons.java:10)
at Balloons.main(Balloons.java:22)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Additionally, since you have protected your code so that balloons will never
contain a null, we can remove the check in pinchAll() making the code a little
neater.&lt;/p&gt;

&lt;p&gt;I know, adding &lt;code&gt;!= null&lt;/code&gt; all over your code is hardly neat, so I use some
helper methods to make it less ugly. Here some example of how I use the "Protect" class" (full code at the bottom of the post):&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addBalloon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Balloon&lt;/span&gt; &lt;span class="n"&gt;balloon&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Protect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;balloon&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;balloons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;balloon&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addMany&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Balloon&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Balloon&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Protect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;//....&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addWithLabel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Balloon&lt;/span&gt; &lt;span class="n"&gt;balloon&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// this will also check for empty strings&lt;/span&gt;
    &lt;span class="n"&gt;Protect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;balloon&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;//....&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I have picked up the habit of testing all arguments with Protect.notNull, and
&lt;em&gt;then&lt;/em&gt; think if I really need it or if this code is implicitly protected by it
call hierarchy.&lt;/p&gt;

&lt;p&gt;Once the check is in place in most of your methods, the way all the tests
interlock makes for a warm feeling.&lt;/p&gt;

&lt;p&gt;Yes, it’s bulky and your lean and clean code will look bloated, but mind that
you'll save a lot of &lt;code&gt;!=null&lt;/code&gt; checks after invoking methods. Once you get
used to it, it also doubles as a form of documentation as any reader will
quickly get that  nulls are not accepted.&lt;/p&gt;

&lt;p&gt;Null protection is probably at its best when used at the constructor of an
immutable class: you &lt;em&gt;know&lt;/em&gt; that all instances of that class do not contain
nulls&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="c1"&gt;// a bunga bunga you can trust&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BungaBunga&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;secretLocation&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;BungaBunga&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;secretLocation&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Protect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secretLocation&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;secretLocation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secretLocation&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// ....&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Beware, testing for nullity will waste some cpu - on my laptop about a ns for
the simple check (object == null) and maybe 10 for the version with varargs.
It’s not much but they may add up, so in you may want to skip the checks in
some regions of your codes, especially method invocations in loops. As most
things in life, don't overdo it.&lt;/p&gt;

&lt;p&gt;It's possible to add more complex checks or other kinds. In a recent piece of
code I was enforcing all the calls to a class to happen from one single
thread. In another app that was using some simple spatial geometry I enforced
all the ints in some classes to be positive.&lt;/p&gt;

&lt;p&gt;My Protect class is a very crude piece of code, but it does the job and it's easy to understand. Note how empty strings are treated as nulls.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Protect&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Object in position 0 is null&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;        
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Str in pos 0 is null or empty&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Str in pos 0 is null or empty&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Str in pos 1 is null or empty&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Str in pos &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; is null or empty&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Obj in pos 0 is null or empty&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Obj in pos 1 is null or empty&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Str in pos 0 is null or empty&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Str in pos 1 is null or empty&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    
    &lt;span class="c1"&gt;// beware, this is maybe 10 times slower than the non-varargs version&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Obj in pos &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; is null&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]).&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Str in pos &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; is null or empty&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;                
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Thanks for reading this far, and always test your code, better if before
writing it.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/nlOGJYNM1tw" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/enforcing-design-principles-in-software</feedburner:origLink></entry>
 
 <entry>
   <title>Java bytecode, string concatenation and StringBuilder</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/OUAKh_w2Vd8/java-bytecode-string-concatenation-and-stringbuilder" />
   <updated>2011-06-23T10:08:43+00:00</updated>
   <id>http://caprazzi.net//posts/java-bytecode-string-concatenation-and-stringbuilder</id>
   <content type="html">&lt;p&gt;In my &lt;a href="http://caprazzi.net/posts/evaluating-relative-speed-of-java-digest-hashing-algorithms/"&gt;earlier
post&lt;/a&gt;
I was making a fuss over picking the faster hash algorithm, when I realised I
was using + to concatenate strings. Should I always use a
&lt;a href="http://download.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuilder.html"&gt;StringBuilder&lt;/a&gt;? Should I care even for small strings? Heck, if I use the&lt;code&gt;StringBuilder&lt;/code&gt; I'll be creating one extra object anyway?&lt;/p&gt;

&lt;p&gt;I tried some variations of the test and I did not find any performance
difference when comparing simple concatenation to using the string builder,
even when trying with bigger strings and other silly combinations. I got
curious and wrote a very simple class and looked at the resulting bytecode.&lt;/p&gt;

&lt;p&gt;This java code:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;cip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;cip&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;ciop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;ciop&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;plus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ciop&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cip&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciop&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Generates this - see how the two concatenation styles lead to the very same bytecode:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt; &lt;span class="n"&gt;L0&lt;/span&gt;
    &lt;span class="n"&gt;LINENUMBER&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt; &lt;span class="n"&gt;L0&lt;/span&gt;
    &lt;span class="n"&gt;LDC&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;cip&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;ASTORE&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
   &lt;span class="n"&gt;L1&lt;/span&gt;
    &lt;span class="n"&gt;LINENUMBER&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="n"&gt;L1&lt;/span&gt;
    &lt;span class="n"&gt;LDC&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;ciop&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;ASTORE&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="c1"&gt;// cip + ciop&lt;/span&gt;
   &lt;span class="n"&gt;L2&lt;/span&gt;
    &lt;span class="n"&gt;LINENUMBER&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="n"&gt;L2&lt;/span&gt;

    &lt;span class="n"&gt;NEW&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;
    &lt;span class="n"&gt;DUP&lt;/span&gt;
    &lt;span class="n"&gt;ALOAD&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;INVOKESTATIC&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;INVOKESPECIAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;.&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;
    &lt;span class="n"&gt;ALOAD&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;INVOKEVIRTUAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;INVOKEVIRTUAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;ASTORE&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="c1"&gt;// new StringBuilder(cip).append(ciop).toString()&lt;/span&gt;
   &lt;span class="n"&gt;L3&lt;/span&gt;
    &lt;span class="n"&gt;LINENUMBER&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;L3&lt;/span&gt;

    &lt;span class="n"&gt;NEW&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;
    &lt;span class="n"&gt;DUP&lt;/span&gt;
    &lt;span class="n"&gt;ALOAD&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;INVOKESPECIAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;.&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;
    &lt;span class="n"&gt;ALOAD&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;INVOKEVIRTUAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;INVOKEVIRTUAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;ASTORE&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
   &lt;span class="n"&gt;L4&lt;/span&gt;
    &lt;span class="n"&gt;LINENUMBER&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="n"&gt;L4&lt;/span&gt;
    &lt;span class="n"&gt;RETURN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The compiler has transformed "cip+ciop" into "new StringBuilder(cip).append(ciop).toString()".
In other words, &lt;strong&gt;"+" is effectively a shorthand for the more verbose &lt;code&gt;StringBuilder&lt;/code&gt; idiom.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Update:
Javadoc for &lt;a href="(http://download.oracle.com/javase/1.4.2/docs/api/java/lang/String.html"&gt;java 1.4&lt;/a&gt; says "String concatenation is implemented through the &lt;em&gt;StringBuffer&lt;/em&gt; class",
while in &lt;a href="http://download.oracle.com/javase/1,5.0/docs/api/java/lang/String.html"&gt;java 1.5&lt;/a&gt; it's "String concatenation is implemented through the &lt;em&gt;StringBuilder(or StringBuffer)&lt;/em&gt;
class". It makes sense, since StringBuilder was introduced in 1.5 as a faster (non thread-safe) version of StringBuffer.&lt;/p&gt;

&lt;p&gt;The compiler will do same trick for cip + "ciop" and "cip" + ciop. (In case you wonder, "cip" + "ciop" will just be compiled as "cipciop").&lt;/p&gt;

&lt;p&gt;This is great, but beware, the compiler is not a worthy substitute for you thinking at what you do.&lt;/p&gt;

&lt;p&gt;This code&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;both&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;cip&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;ciop&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Will be compiled into&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;both&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bag&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cip&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bag&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciop&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;While of course the most efficient way is&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;both&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cip&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciop&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;One more example:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;boo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;both&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt;
     &lt;span class="n"&gt;boo&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;cip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ciop&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now the compiler will do the obvious thing and instantiate one new StringBuilder at each iteration, as if I had written&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;boo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;both&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt;
     &lt;span class="n"&gt;boo&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;boo&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cip&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciop&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;For better efficiency, I should have done this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;both&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt;
    &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cip&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ciop&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;boo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Following Christian comment below, I had a look at how string.concat is handled:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;baz&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;foobarbaz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;concat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;concat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;        
&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;foobarbazX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Gets compiled in:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="c1"&gt;// .. snip&lt;/span&gt;
   &lt;span class="n"&gt;LINENUMBER&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="n"&gt;L3&lt;/span&gt;
    &lt;span class="n"&gt;ALOAD&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;ALOAD&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;INVOKEVIRTUAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;concat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;ALOAD&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;INVOKEVIRTUAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;concat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;ASTORE&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
   &lt;span class="n"&gt;L4&lt;/span&gt;
    &lt;span class="n"&gt;LINENUMBER&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="n"&gt;L4&lt;/span&gt;
    &lt;span class="n"&gt;NEW&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;
    &lt;span class="n"&gt;DUP&lt;/span&gt;
    &lt;span class="n"&gt;ALOAD&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;INVOKESTATIC&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;INVOKESPECIAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;.&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;
    &lt;span class="n"&gt;ALOAD&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;INVOKEVIRTUAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;ALOAD&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;INVOKEVIRTUAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;)&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;INVOKEVIRTUAL&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="n"&gt;Ljava&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;ASTORE&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="c1"&gt;// .. snip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;So, is String.concat the best choice in terms of bytecode size?&lt;/p&gt;

&lt;p&gt;-teo&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/OUAKh_w2Vd8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder</feedburner:origLink></entry>
 
 <entry>
   <title>Evaluating relative speed of java digest (hashing) algorithms</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/olA7GAOk7ps/evaluating-relative-speed-of-java-digest-hashing-algorithms" />
   <updated>2011-06-22T14:27:20+00:00</updated>
   <id>http://caprazzi.net//posts/evaluating-relative-speed-of-java-digest-hashing-algorithms</id>
   <content type="html">&lt;p&gt;It's best practice to encrypt security tokens such as passwords and sessions ids in your database. I was just doing that to the session tokens for a project at work, and I wondered which algorithm to pick if speed was the only consideration.&lt;/p&gt;

&lt;p&gt;I cranked up some code that measures the wall-clock that it takes for each algorithm to hash a bunch of strings (10 millions). I found that MD5 is the fastest, and MD2 is the slowest, taking roughly twice the time. I would have gone for MD5 anyway as it is the standard choice, but it's good to see that it's quick too.&lt;/p&gt;

&lt;p&gt;The usual disclaimers apply: this test is very un-scientific and is only relevant for my specific use case (the tokens I handle are the same length of the random strings in the test) so don't plan your business on it. That's pretty quick stuff anyway (15 to 30 microsecond each encryption), so you may want to pick an algorithms for its security features rather then for its execution speed. See &lt;a href="//%20see%20http://download.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html#AppA"&gt;the docs&lt;/a&gt; for more info.&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;pre class="terminal"&gt;
Creating 10000000 random strings... Created.
Testing algo MD2... Completed in 339126 milliseconds
Testing algo MD5... Completed in 169690 milliseconds
Testing algo SHA-1...   Completed in 200398 milliseconds
Testing algo SHA-256... Completed in 211560 milliseconds
Testing algo SHA-384... Completed in 303999 milliseconds
Testing algo SHA-512... Completed in 316265 milliseconds
Test Complete.
&lt;/pre&gt;


&lt;p&gt;And code:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.math.BigInteger&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.MessageDigest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.SecureRandom&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompareHashFunctions&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;SecureRandom&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;SecureRandom&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10000000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;               

        &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Creating &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot; random strings... &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;randomString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;randomString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Created. &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;    

        &lt;span class="n"&gt;runTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;MD2&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;runTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;MD5&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;runTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;SHA-1&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;runTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;SHA-256&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;runTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;SHA-384&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;runTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;SHA-512&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;        

        &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Test Complete.&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;runTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Testing algo &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;algo&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;...\t&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;MessageDigest&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MessageDigest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;algo&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nanoTime&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]).&lt;/span&gt;&lt;span class="na"&gt;getBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;MessageDigest&lt;/span&gt; &lt;span class="n"&gt;clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MessageDigest&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clone&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nanoTime&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Completed in &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;  &lt;span class="s"&gt;&amp;quot; milliseconds &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;        

    &lt;span class="cm"&gt;/**&lt;/span&gt;
&lt;span class="cm"&gt;    * Random string&lt;/span&gt;
&lt;span class="cm"&gt;    * @return a random string of 25 or 26 chars&lt;/span&gt;
&lt;span class="cm"&gt;    */&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;randomString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 130 bit random integer converted to string in base 32&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BigInteger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;130&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;-teo&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/olA7GAOk7ps" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/evaluating-relative-speed-of-java-digest-hashing-algorithms</feedburner:origLink></entry>
 
 <entry>
   <title>Where are generics stored in java compiled classes?</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/CpooYKeAf0Y/where-are-generics-stored-in-java-compiled-classes" />
   <updated>2011-02-24T18:00:39+00:00</updated>
   <id>http://caprazzi.net//posts/where-are-generics-stored-in-java-compiled-classes</id>
   <content type="html">&lt;p&gt;I was having a go at learning some Java bytecode and started looking at how generics were handled. As expected, the compiler was emitting cast instructions when generic types where &lt;em&gt;used&lt;/em&gt;, but nothing where the types where &lt;em&gt;declared&lt;/em&gt;: generics in&amp;nbsp;Java&amp;nbsp;are implemented using a&amp;nbsp;technique&amp;nbsp;called "erasure".&lt;/p&gt;

&lt;p&gt;Straight from the docs:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;When a generic type is instantiated, the compiler translates those types by a technique called&amp;nbsp;&lt;em&gt;type erasure&lt;/em&gt; — a process where &lt;strong&gt;the compiler removes all information
related to type parameters and type arguments&lt;/strong&gt;  within a class or method. Type erasure enables Java applications that
use generics to maintain binary compatibility with Java libraries and applications that were created before generics.
&lt;a href="http://download.oracle.com/javase/tutorial/java/generics/erasure.html"&gt;from java docs&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;But sure not ALL information about the type parameters is lost. That would mean that once I compile my code, all other developer would use it "the old way", with casts and all, but clearly this is not the case. Let's write two simple classes:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenericClass&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StandardClass&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And decompile them:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ javap -c GenericClass
public class learn.GenericClass extends java.lang.Object{
public learn.GenericClass();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."&amp;lt;init&gt;":()V
   4:   return
}
&lt;/pre&gt;




&lt;br/&gt;


&lt;pre class="terminal"&gt;
$ javap  -c StandardClass
Compiled from "StandardClass.java"
public class learn.StandardClass extends java.lang.Object{
public learn.StandardClass();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."&amp;lt;init&gt;":()V
   4:   return
}
&lt;/pre&gt;


&lt;p&gt;As it should, the bytecode looks exactly the same. No type parameters.&lt;/p&gt;

&lt;p&gt;Let's invoke the same command again with -verbose to see some more detail:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ javap -verbose StandardClass
Compiled from "StandardClass.java"
public class learn.StandardClass extends java.lang.Object
  SourceFile: "StandardClass.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = class        #2;     //  learn/StandardClass
// ... snip
const #15 = Asciz       StandardClass.java;
// ... snip
&lt;/pre&gt;


&lt;br/&gt;




&lt;pre class="terminal"&gt;
$ javap -verbose GenericClass
Compiled from "GenericClass.java"
public class learn.GenericClass extends java.lang.Object
  SourceFile: "GenericClass.java"
  &lt;strong style="color:red"&gt;Signature: length = 0x2&lt;/strong&gt;
   00 13
  minor version: 0
  major version: 50
  Constant pool:
const #1 = class        #2;     //  learn/GenericClass
// ... snip
&lt;strong style="color:red"&gt;const #19 = Asciz       &lt;T:Ljava/lang/Object;&gt;Ljava/lang/Object;;&lt;/strong&gt;
&lt;/pre&gt;


&lt;p&gt;The two outputs are different at last: the constant_pool section of a class file has an optional "signature" field. This optional can specify the full signature of the class, including type parameters. The compiler can then use this information to do the right thing when turns sources into binaries.This stuff is specified in the section "4.8.8 The Signature Attribute" of the &lt;a href="http://java.sun.com/docs/books/jvms/second_edition/jvms-clarify.html"&gt;updated JVM Specification&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/CpooYKeAf0Y" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/where-are-generics-stored-in-java-compiled-classes</feedburner:origLink></entry>
 
 <entry>
   <title>simple webserver and rest with jetty and NO XML</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/n3skkhIGu3w/simple-webserver-and-rest-with-jetty-and-no-xml" />
   <updated>2011-02-16T13:57:40+00:00</updated>
   <id>http://caprazzi.net//posts/simple-webserver-and-rest-with-jetty-and-no-xml</id>
   <content type="html">&lt;p&gt;Starting a new web project (maybe with rest?) in Java requires mastery of many complex abstract components. You need a webapp
for tomcat (fiddle with some xml files), spring (import plenty of jars and add some more xml files), pick a rest framework
like spring, resteasy, restlset (fiddle with annotations), deploy to tomcat and go.&lt;/p&gt;

&lt;p&gt;I won't deny all this components add structure, reusability and a lot of good stuff, but sometimes I have simple needs that
scream for simple solutions.&lt;/p&gt;

&lt;p&gt;Few days ago I needed just that: a simple database with a REST api, and the ability to serve a few static files.&lt;/p&gt;

&lt;p&gt;I used jetty embedded and it took was one maven dependency, 3 classes, 150 lines of java, 15 minutes and NO XML.&lt;/p&gt;

&lt;p&gt;I was so satisfied with the result work that I served myself a beer and &lt;a href="https://github.com/mcaprari/simple-webserver-and-rest-with-jetty-and-no-xml"&gt;posted the code on
github&lt;/a&gt;. The actual project implemented a
datastore on neo4j, but for sake of simplicity I released it on github as a dumb in-memory key-value store.&lt;/p&gt;

&lt;p&gt;According to apache bench, with as little as 8m memory (-Xmx8m) the server was able to handle 2k concurrent users at a rate of 1500 requests per second.&lt;/p&gt;

&lt;p&gt;The main is as simple as this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="java"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// configure the default servlet to serve static files from &amp;quot;htdocs&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInitParams&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;org.mortbay.jetty.servlet.Default.resourceBase&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;htdocs&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addServlet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ServletHolder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DefaultServlet&lt;/span&gt;&lt;span class="o"&gt;()),&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// use /uuid to get a fresh id&lt;/span&gt;
    &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addServlet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ServletHolder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;UUIDServlet&lt;/span&gt;&lt;span class="o"&gt;()),&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/uuid&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// the actual key/value store&lt;/span&gt;
    &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addServlet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ServletHolder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;KeyValueServlet&lt;/span&gt;&lt;span class="o"&gt;()),&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;/store/*&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Get the code: &lt;a href="https://github.com/mcaprari/simple-webserver-and-rest-with-jetty-and-no-xml"&gt;Simple webserver and REST with jetty and NO XML on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/n3skkhIGu3w" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/simple-webserver-and-rest-with-jetty-and-no-xml</feedburner:origLink></entry>
 
 <entry>
   <title>Most Advanced Yet Acceptable</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/lTW4hwm1dXU/most-advanced-yet-acceptable" />
   <updated>2010-05-18T09:06:08+00:00</updated>
   <id>http://caprazzi.net//posts/most-advanced-yet-acceptable</id>
   <content type="html">&lt;a href="http://en.wikipedia.org/wiki/Raymond_Loewy" target="_blank"&gt;Raymond Loewy&lt;/a&gt; believed that
&lt;blockquote&gt;The adult public's taste is not necessarily ready to accept the logical solutions to their requirements if the solution implies too vast a departure from what they have been conditioned into accepting as the norm.&lt;/blockquote&gt;
Quite a statement. He synthesised  his observation in a principle and further compressed it in acronym:&lt;strong&gt; Most Advanced Yet Acceptable - MAYA&lt;/strong&gt;

He was a radical, forward thinker so I guess he was constantly refitting his ideas into the Acceptable yet Advanced. As a industrial designer, he was trying to have his designs mass produced and sold to actual people. He succeeded and his designs reveal the tension between the future rolling in and the people holding back.

Of course,  it's common sense. Had he designed something Unacceptable, his biography would have been different.

But MAYA is also a very real constraint, the sort that makes or kills your proposition. No matter what you are selling to whom: a new song, a new recipe, a new software; to your fans, to your girlfriend, to your boss. Being advanced is not enough, it must be acceptable. Not enough advanced, it is not interesting.

You can ignore the principle and be a scientist. Or never challenge it and be an engineer or just be boring. Some would say that a &lt;a href="http://blog.acaro.org/entry/what-s-a-sciengineer-aka-science-vs-engineering" target="_blank"&gt;sciengineer&lt;/a&gt; will balance his act and live up to the MAYA principle. As a software developer and technology entusiast I find it hard to hit the sweet spot.
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/lTW4hwm1dXU" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/most-advanced-yet-acceptable</feedburner:origLink></entry>
 
 <entry>
   <title>ten principles of good design and two books</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/m3pLHku8Ln8/ten-principles-to-good-design-and-two-books" />
   <updated>2010-05-08T23:02:04+00:00</updated>
   <id>http://caprazzi.net//posts/ten-principles-to-good-design-and-two-books</id>
   <content type="html">I'm watching the first episode of &lt;a title="BBC - The Genius of Design" href="http://www.bbc.co.uk/programmes/b00sdb8x" target="_blank"&gt;The Genius of Design&lt;/a&gt;, a BBC documentary series exploring the history of design. It's not about &lt;em&gt;software&lt;/em&gt; design, but one could argue that the &lt;em&gt;process &lt;/em&gt;and the &lt;em&gt;craft &lt;/em&gt;of design are interesting not matter &lt;em&gt;what&lt;/em&gt; is being designed. Anyway. They briefly interview &lt;a title="Dieter Rams - Wikipedia" href="http://en.wikipedia.org/wiki/Dieter_Rams" target="_blank"&gt;Dieter Rams&lt;/a&gt;, a very prolific designer who made the history of industrial design and came up with ten commandments. Read them slowly. The 10th is pure genius.&lt;a href="http://caprazzi.net/wp-content/uploads/2010/05/cad-drawing-540.jpg"&gt;&lt;img class="alignright size-thumbnail wp-image-565" style="border: 0; opacity: 0.5;" title="cad-drawing-540" src="http://caprazzi.net/wp-content/uploads/2010/05/cad-drawing-540-150x150.jpg" alt="" width="170" height="200" /&gt;&lt;/a&gt;
&lt;style type="text/css"&gt; .entry ol li { color:black;} &lt;/style&gt;
&lt;ol&gt;
	&lt;li&gt;Good design is &lt;strong&gt;innovative&lt;/strong&gt;&lt;/li&gt;
	&lt;li&gt;Good design makes a product &lt;strong&gt;useful&lt;/strong&gt;&lt;/li&gt;
	&lt;li&gt;Good design is aesthetic&lt;/li&gt;
	&lt;li&gt;Good design makes a product &lt;strong&gt;understandable&lt;/strong&gt;&lt;/li&gt;
	&lt;li&gt;Good design is unobtrusive&lt;/li&gt;
	&lt;li&gt;Good design is &lt;strong&gt;honest&lt;/strong&gt;&lt;/li&gt;
	&lt;li&gt;Good design is long-lasting&lt;/li&gt;
	&lt;li&gt;Good design is thorough down to the last detail&lt;/li&gt;
	&lt;li&gt;Good design is environmentally friendly&lt;/li&gt;
	&lt;li&gt;Good design is &lt;strong&gt;as little design as possible&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style="text-align: left;"&gt;&lt;em&gt;(We are grateful to Mr Rams for such pearls of wisdom, &lt;/em&gt;&lt;em&gt;&lt;a title="1960s Braun Products Hold the Secrets to Apple's Future" href="http://gizmodo.com/343641/1960s-braun-products-hold-the-secrets-to-apples-future" target="_blank"&gt;and so is apple...&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
All this talk about design reminds me of  &lt;a title="Amazon.co.uk - The Design of Everyday Things" href="http://www.amazon.co.uk/Design-Everyday-Things-Donald-Norman/dp/0465067107" target="_blank"&gt;the design of everyday things&lt;/a&gt;. It's a brilliant book, inspiring and foundational. I keep suggesting it, especially to programmers and makers alike. &lt;a href="http://caprazzi.net/wp-content/uploads/2010/05/design_everyday_things.png"&gt;&lt;img class="alignleft size-full wp-image-555" title="the design of everyday things - cover" src="http://caprazzi.net/wp-content/uploads/2010/05/design_everyday_things.png" alt="the design of everyday things - cover" width="79" height="118" /&gt;&lt;/a&gt;Another title worth mentioning is &lt;a title="amazon.co.uk - the design of design" href="http://www.amazon.co.uk/Design-Essays-Computer-Scientist/dp/0201362988" target="_blank"&gt;the design of design&lt;/a&gt;, from the same folk who wrote "the mythical man-month". The new book is not as ground-breaking as the old one, but it's a good read of its own right.
&lt;br/&gt;&lt;br/&gt;
On the subject of &lt;em&gt;exploring &lt;/em&gt;and &lt;em&gt;finding&lt;/em&gt; a design, watch this video on ted: &lt;a title="TED.com - Tom Wujec: Build a tower, build a team" href="http://www.ted.com/talks/tom_wujec_build_a_tower.html" target="_blank"&gt;build a tower, build a team&lt;/a&gt; (6 minutes).
&lt;br/&gt;
&lt;em&gt;Is there something like imdb or wikipedia for books? I keep linking amazon but I'd prefer to link to a website with a more informational angle.&lt;/em&gt;
&lt;div&gt;&lt;span style="color: #0000ee; -webkit-text-decorations-in-effect: underline;"&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/m3pLHku8Ln8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/ten-principles-to-good-design-and-two-books</feedburner:origLink></entry>
 
 <entry>
   <title>openid authentication handler for couchdb</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/6HHPVCuEpVw/openid-authentication-handler-for-couchdb" />
   <updated>2010-01-13T17:09:09+00:00</updated>
   <id>http://caprazzi.net//posts/openid-authentication-handler-for-couchdb</id>
   <content type="html">&lt;p&gt;Over at &lt;a href="http://github.com/mcaprari/couchdb-openid"&gt;couchdb-openid&lt;/a&gt;, there is my implementation of OpenID version 1.1 for couchdb, based on http://github.com/etnt/eopenid&lt;/p&gt;
&lt;p&gt;
It seems fairly stable but has only been tested against myopenid.com, so it is definitely not production ready. 
&lt;/p&gt;
&lt;p&gt;
	I plan to add support for openid 2.0 and to make couchdb work as openid endpoint.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;
The &lt;a href="http://github.com/mcaprari/couchdb-openid/blob/master/src/couch_httpd_openid_auth.erl"&gt;handler code&lt;/a&gt; would love to be reviewed by someone with some erlang and couchdb experience.
&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Demo&lt;/h2&gt;
&lt;p&gt;
Try the &lt;a href="http://couch.caprazzi.net/fortytwo/_design/fortytwo/_show/auth"&gt;login page at fortytwo&lt;/a&gt;.
&lt;/p&gt;

&lt;h2&gt;Quick install:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; cd couchdb_install_path/lib/couchdb/erlang/lib/&lt;/li&gt;

&lt;li&gt; git clone git://github.com/mcaprari/couchdb-openid.git&lt;/li&gt;
&lt;li&gt; cd couchdb-openid&lt;/li&gt;
&lt;li&gt; make&lt;/li&gt;
&lt;li&gt; edit local.ini [httpd]/authentication_handlers (or do it form futon) and
add {couch_httpd_openid_auth, openid_authentication_handler} &lt;strong&gt;BEFORE the default handlers&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt; restart couchdb&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Quick test:&lt;/h2&gt;

&lt;p&gt;http://caprazzi.net:5984/_session?openid=auth-request&amp;amp;openid-identifier=&amp;lt;your_openid&amp;gt;&lt;/p&gt;

&lt;h2&gt;What to expect:&lt;/h2&gt;

&lt;p&gt;Only openid 1.1 is supported and it has only been tested with myopenid.com as openid provider.&lt;/p&gt;

&lt;p&gt;When a client hits the initiation url (above), it is redirected to the openid provider
and prompted to authorise the association.&lt;/p&gt;
&lt;p&gt;Then it's redirected back to the couch and&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if the client &lt;strong&gt;is not logged in&lt;/strong&gt; in and supplies a &lt;strong&gt;new openid&lt;/strong&gt;, a new user is created with username=openid and the client is logged in&lt;/li&gt;
&lt;li&gt; if the client &lt;strong&gt;is not logged in&lt;/strong&gt; in and supplies a &lt;strong&gt;mapped openid&lt;/strong&gt;,
the client is logged in as the mapped user&lt;/li&gt;

&lt;li&gt; if the client &lt;strong&gt;is logged in&lt;/strong&gt; and supplies a &lt;strong&gt;new openid&lt;/strong&gt;,
the supplied openid is added to current user, and the client keeps the current login&lt;/li&gt;
&lt;li&gt; if the client &lt;strong&gt;is logged in&lt;/strong&gt; and supplies a &lt;strong&gt;mapped openid&lt;/strong&gt;

&lt;ul&gt;

&lt;li&gt;if openid is mapped to the &lt;strong&gt;same user&lt;/strong&gt;, the client keeps the current login&lt;/li&gt;
&lt;li&gt;if openid is mapped to a &lt;strong&gt;different user&lt;/strong&gt;, the operation fails 400&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; if user &lt;strong&gt;is logged in AS ADMIN&lt;/strong&gt; and supplies a &lt;strong&gt;new openid&lt;/strong&gt; the operation fails 500&lt;/li&gt;

&lt;/ul&gt;


&lt;h2&gt;TODO:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; try erl_openid for openid 2.0 support&lt;/li&gt;
&lt;li&gt; decide if it is wise to map openids to admins (if at all possible)&lt;/li&gt;
&lt;li&gt; cleanup ets table after auth confirm (or maybe find an alternative to ets tables)&lt;/li&gt;
&lt;li&gt; reduce dependence from eopenid (dict access routines at least)&lt;/li&gt;

&lt;/ul&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/6HHPVCuEpVw" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/openid-authentication-handler-for-couchdb</feedburner:origLink></entry>
 
 <entry>
   <title>Couchdb runtime statistics viewer</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/OHOMx56qRMs/couchdb-runtime-statistics-viewer" />
   <updated>2010-01-05T14:16:49+00:00</updated>
   <id>http://caprazzi.net//posts/couchdb-runtime-statistics-viewer</id>
   <content type="html">&lt;p&gt;
	CouchDB comes with a runtime statistics module that lets you inspect how CouchDB performs.
	The statistics module collects metrics like requests per second, request sizes and a multitude of other useful stuff. &lt;em&gt;From &lt;a href="http://wiki.apache.org/couchdb/Runtime_Statistics"&gt;Couchdb wiki&lt;/a&gt;&lt;/em&gt;.
	
	I created a simple app that uses &lt;a href="http://timepedia.org/chronoscope/" title="timepedia chronoscope"&gt;chronoscope&lt;/a&gt; to display how some metrics change over time.
	
	Jump to the &lt;a href="http://caprazzi.net:5984/stats/_design/app/_list/table_multi/http_requests_hits_by_method?group_level=4" title="couchdb runtime stats viewer"&gt;demo&lt;/a&gt;, go to the &lt;a href="http://github.com/mcaprari/couchdb-stats" title="couchdb runtime stats source"&gt;source&lt;/a&gt; or use the &lt;a href="http://caprazzi.net:5984/stats/_design/app/docs/index.html" title="couchdb runtime stats documentation"&gt;docs&lt;/a&gt;.
	
	&lt;a title="couchdb runtime stats viewer" href="http://caprazzi.net:5984/stats/_design/app/_show/index/bogus"&gt;&lt;img src="http://caprazzi.net/wp-content/uploads/2010/01/couchdb_stats_screenshot.png" alt="Couchdb Stats Screenshot"&gt;&lt;/a&gt;

&lt;/p&gt;

&lt;h2&gt;Install&lt;/h2&gt;
&lt;p&gt;
	couchdb-stats is a simple couchapp plus a python script that hits /_stats and stores the results in couchdb server
	
	&lt;em&gt;Attention: this app is tested with Couchdb 0.11.x, not yet released at the time of this post.&lt;/em&gt;
&lt;/p&gt;
&lt;pre class="term"&gt;
$ git clone git://github.com/mcaprari/couchdb-stats.git
$ cd couchdb-stats
$ couchapp push app http://localhost:5984/stats
$ python stats_copy.py localhost localhost stats 60
&lt;/pre&gt;
&lt;p&gt;
	Couchdb reports metrics since server start or of the last 1, 5 or 15 minutes. There is no way to see yesterday's stats. To do that, we need to keep hitting /_stats and store results in a couchdb database.
	
	&lt;a href="http://github.com/mcaprari/couchdb-stats/blob/master/stats_copy.py" title="python couchdb _stats  consumer"&gt;stats_copy.py&lt;/a&gt; does just that.
&lt;/p&gt;
&lt;p&gt;
	At this point it's possible to write several views, each focused on a particular metric. See the &lt;a href="http://caprazzi.net:5984/stats/_design/app/docs/index.html" title="couchdb runtime stats documentation"&gt;documentation&lt;/a&gt; for more details.
&lt;p&gt;
	
&lt;p&gt;&lt;strong&gt;questions, comments and suggestions welcome&lt;/p&gt;&lt;/strong&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/OHOMx56qRMs" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/couchdb-runtime-statistics-viewer</feedburner:origLink></entry>
 
 <entry>
   <title>generating SVG charts with couchdb</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/pxtC3zJBnEw/charting-data-with-couchdb" />
   <updated>2009-12-08T14:28:43+00:00</updated>
   <id>http://caprazzi.net//posts/charting-data-with-couchdb</id>
   <content type="html">&lt;p&gt;In this article I describe how I got couchdb to produce SVG charts using &lt;a title="List functions chapter in The Definitive Guide" href="http://books.couchdb.org/relax/design-documents/lists"&gt;list functions&lt;/a&gt;&lt;p&gt;

&lt;p&gt;
	This post is long, so I'll report the results first:
&lt;/p&gt;
&lt;div style="margin-left: auto;"&gt;
&lt;div style="float:left; text-align:center; border-right: 1px solid #f0f0f0; padding-right: 1em; padding-left: 1em;"&gt;
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-1.svg"&gt;&lt;img style="padding:0; margin:0; border:0" src="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-1.thumb.png"/&gt;&lt;/a&gt;
	&lt;strong&gt;group_level=1&lt;/strong&gt;
	yearly averages
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-1.svg"&gt;svg&lt;/a&gt; - &lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-1.png"&gt;png&lt;/a&gt;
&lt;/div&gt;
&lt;div style="float:left; text-align:center; border-right: 1px solid #f0f0f0; padding-right: 1em; padding-left: 1em;"&gt;
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-2.svg"&gt;&lt;img style="padding:0; margin:0; border:0" src="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-2.thumb.png"/&gt;&lt;/a&gt;
	&lt;strong&gt;group_level=2&lt;/strong&gt;
	monthly averages
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-2.svg"&gt;svg&lt;/a&gt; - &lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-2.png"&gt;png&lt;/a&gt;
&lt;/div&gt;
&lt;div style="float:left; text-align:center; padding-left: 1em;"&gt;	
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-3.svg"&gt;&lt;img style="padding:0; margin:0; border:0" src="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-3.thumb.png"/&gt;&lt;/a&gt;
	&lt;strong&gt;group_level=3&lt;/strong&gt;
	daily values
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-3.svg"&gt;svg&lt;/a&gt; - &lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-3.png"&gt;png&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style="clear:both"&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;
	Now go and read how I did it:
	&lt;ol style="margin-left:0; padding-left:0"&gt;
		&lt;li&gt;&lt;a title="generate some test data" href="#generate"&gt;generate some test data&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a title="upload test data to couchdb" href="#upload"&gt;upload test data to couchdb&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a title="create and manage a design document with couchapp" href="#couchapp"&gt;create and manage a design document with couchapp&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a title="write a simple view with map/reduce" href="#view"&gt;write a simple view with map/reduce&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a title="write a _list function and render the charts!" href="#list"&gt;write a _list function and render the charts!&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a title="conclusions" href="#conculsions"&gt;Conclusions&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
&lt;/p&gt;

&lt;div class="xbox"&gt;&lt;em&gt; &lt;a href="http://couchdb.apache.org/"&gt;Apache CouchDB&lt;/a&gt; is a document-oriented database server, accessible via a RESTful JSON API. It has some advanced features, such as the ability to write 'views' in a map/reduce fashion and to further transform the results using javascript. It's a young but very promising project.&lt;/em&gt;&lt;/div&gt;

&lt;h2&gt;Try this at home&lt;/h2&gt;
You can browse &lt;a href="http://github.com/mcaprari/couchdb-charts-example"&gt;browse&lt;/a&gt; or  &lt;a href="http://github.com/mcaprari/couchdb-charts-example/zipball/master"&gt;download&lt;/a&gt; all code discussed here. All comments and corrections are welcome.&lt;/p&gt;

&lt;a name="generate"&gt;&lt;/a&gt;
&lt;h2&gt;Generate some test data&lt;/h2&gt;
To get started with this exploration we need some data to render, and a quick way to
visualize it before our application is ready. This Python script generates a series of data points
that simulate the goings of someone's bank account.
&lt;pre class="code"&gt;&lt;code class="python"&gt;# test_data.py. Usage: python test_data.py &amp;lt;simulation_length&amp;gt;
import sys
import random

days = int(sys.argv[1])
savings = 10000
pay = 2000
for i in range(0, days):
	if ( i%30 == 0):
		savings = savings + pay
	savings = savings - random.randint(0, pay/16) - 2
	print i, (int(savings))
&lt;/code&gt;&lt;/pre&gt;
Use the script to generate a sample set with 3000 points:
&lt;pre class="term"&gt;$ python test_data.py 3000 &amp;gt; test_data.txt
$ cat test_data.txt
0 11947
1 11882
2 11813
...&lt;/pre&gt;
Our final output will be similar to a line chart made with some bash and &lt;em&gt;gnuplot&lt;/em&gt;:
&lt;pre class="code"&gt;&lt;code class="bash"&gt;#!/bin/sh
# gnuplot.sh generates a plot of a series piped in stdin
(echo -e "set terminal png size 750, 500\nplot \"-\" using 1:2 with lines notitle"
cat -
echo -e "end") | gnuplot&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="term"&gt;$ cat test_data.txt | sh gnuplot.sh &amp;gt; &lt;a style="text-decoration:underline" href="http://caprazzi.net/wp-content/uploads/2009/12/test_data.png"&gt;test_data.png&lt;/a&gt;&lt;/pre&gt;

&lt;a name="upload"&gt;&lt;/a&gt;
&lt;h2&gt;Upload test data data to couchdb&lt;/h2&gt;
We need our data in json format so that it can be uploaded to couchdb. This python scripts converts
each input line to a json object. Each object will become a document in couchdb. All lines are collected in the 'docs' array, to make the output compatible with &lt;a href="http://wiki.apache.org/couchdb/HTTP_Bulk_Document_API"&gt;couchdb bulk document api.&lt;/a&gt; It also adds a tag to each document, so it's easier to upload and manage multiple datasets.
&lt;pre class="code"&gt;&lt;code class="python"&gt;# data_to_json.py. builds json output suitable for couchdb bulk operations
import sys
import datetime
date = datetime.datetime(2000, 01, 01)
tag = sys.argv[1]
print '{"docs":['
for line in sys.stdin:
	day, value = line.strip().split(' ')
	datestr = (date + datetime.timedelta(int(day))).strftime("%Y-%m-%d")
	if (day &amp;lt;&amp;gt; "0"): print ","
	sys.stdout.write('{"tag":"%s", "date":"%s", "amount":%s}'%(tag, datestr, value)),
print '\n]}',&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="term"&gt;$ cat test_data.txt | python data_to_json.py &lt;strong&gt;test-data&lt;/strong&gt; &amp;gt; test_data.json
$ cat test_data.json
&lt;strong&gt;{"docs":[&lt;/strong&gt;
{&lt;strong&gt;"tag":"test-data"&lt;/strong&gt;, "date":"2000-01-01", "amount":11896},
{"tag":"test-data", "date":"2000-01-02", "amount":11876},
....
{"tag":"test-data", "date":"2008-03-17", "amount":18703},
{"tag":"test-data", "date":"2008-03-18", "amount":18643}
]}&lt;/pre&gt;
Create a new database with name svg-charts-demo
&lt;pre class="term"&gt;$ curl -i -X PUT http://localhost:5984/svg-charts-demo/
HTTP/1.1 201 Created
...
{"ok":true}&lt;/pre&gt;
Upload the test data
&lt;pre class="term"&gt;$ curl -i -d @test_data.json -X POST http://localhost:5984/svg-charts-demo/_bulk_docs
HTTP/1.1 100 Continue

HTTP/1.1 201 Created
....&lt;/pre&gt;
Verify that 3000 documents are in the database.
&lt;pre class="term"&gt;$ curl http://localhost:5984/svg-charts-demo/_all_docs?limit=0
{"total_rows":3000,"offset":3000,"rows":[]}&lt;/pre&gt;

&lt;a name="couchapp"&gt;&lt;/a&gt;
&lt;h2&gt;Create and manage a design document with couchapp&lt;/h2&gt;
&lt;a title="design documents chapter on the Definitive Guide" href="http://books.couchdb.org/relax/design-documents/design-documents"&gt;Design documents&lt;/a&gt; are special couchdb documents that contain application code such as views and lists.
&lt;a href="http://wiki.github.com/couchapp/couchapp"&gt;CouchApp&lt;/a&gt; is a set of scripts that makes it easy to create and manage design documents.

In most cases installing couchapp is matter of one command. If you have any problems or want to know more, visit &lt;a href="http://books.couchdb.org/relax/example-app/design-documents"&gt;Managing Design Documents&lt;/a&gt; on the Definitive Guide.
&lt;pre class="term"&gt;$ easy_install -U couchapp&lt;/pre&gt;
This command creates a new couchapp called svg-charts and installs it in couchdb
&lt;pre class="term"&gt;$ couchapp generate svg-charts

$ ls svg-charts/
_attachments  _id  couchapp.json  lists  shows  updates  vendor  views

$ couchapp push svg-charts http://localhost:5984/svg-charts-demo/
[INFO] Visit your CouchApp here:
http://localhost:5984/svg-charts-demo/_design/svg-charts/index.html&lt;/pre&gt;

&lt;a name="view"&gt;&lt;/a&gt;
&lt;h2&gt;Write a simple view with map/reduce&lt;/h2&gt;
This view will enable us to group the test data year, month or day and see the average
for each group.
&lt;pre class="code"&gt;&lt;code class="javascript"&gt;// map.js
// key is array representing a date [year][month][day]
// value is each doc amount field (a number)
function(doc) {
	// dates are stored in the doc as 'yyyy-mm-dd'
	emit(doc.date.split('-'), doc.amount);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="code"&gt;&lt;code class="javascript"&gt;// reduce.js
// this reduce function returns an array of objects
// {tot:total_value_for_group, count:elements_in_the_group}
// clients can than do tot/count to get the average for the group
// Keys are arrays [year][month][day], so count will always be 1 when group_level=3
function(keys, values, rereduce) {
	if (rereduce) {
		var result = {tot:0, count:0};
		for (var idx in values) {
			result.tot += values[idx].tot;
			result.count += values[idx].count;
		}
		return result;
	}
	else {
		var result = {tot:sum(values), count:values.length};
		return result;
	}
}
&lt;/code&gt;&lt;/pre&gt;
Update the design document and test the different groupings
&lt;pre class="term"&gt;$ couchapp push svg-charts http://localhost:5984/svg-charts-demo/&lt;/pre&gt;
Call the view with group_level=1 to get the data grouped by year
&lt;pre class="term"&gt;$ curl http://localhost:5984/svg-charts-demo/_design/svg-charts/_view/by_date?&lt;strong&gt;group_level=1&lt;/strong&gt;
{"rows":[
{"key":&lt;strong&gt;["2000"]&lt;/strong&gt;,"value":{"tot":4247068,"count":366}},
...
{"key":&lt;strong&gt;["2008"]&lt;/strong&gt;,"value":{"tot":1529286,"count":78}}
]}&lt;/pre&gt;
Call the view with roup_level=2 to get the data grouped by month
&lt;pre class="term"&gt;$ curl http://localhost:5984/svg-charts-demo/_design/svg-charts/_view/by_date?&lt;strong&gt;group_level=2&lt;/strong&gt;
{"rows":[
{"key":&lt;strong&gt;["2000","01"]&lt;/strong&gt;,"value":{"tot":343578,"count":31}},
{"key":&lt;strong&gt;["2000","06"]&lt;/strong&gt;,"value":{"tot":345282,"count":30}},
...&lt;/pre&gt;
Call the view with roup_level=3 to get the data grouped by day. As all the keys are different at the third level, this returns a single row for each document.
&lt;pre class="term"&gt;$ curl -s http://localhost:5984/svg-charts-demo/_design/svg-charts/_view/by_date?&lt;strong&gt;group_level=3&lt;/strong&gt;
{"rows":[
{"key":&lt;strong&gt;["2000","01","01"]&lt;/strong&gt;,"value":{"tot":11896,"count":1}},
{"key":&lt;strong&gt;["2000","01","04"]&lt;/strong&gt;,"value":{"tot":11747,"count":1}},
...&lt;/pre&gt;
Same as above but limiting the response to a range of days
&lt;pre class="term"&gt;$ curl -s 'http://localhost:5984/svg-charts-demo/_design/svg-charts/_view/by_date?group_level=3
&amp;amp;startkey=\&lt;strong&gt;["2008","01","01"\]&lt;/strong&gt;&amp;amp;endkey=\&lt;strong&gt;["2008","01","04"\]&lt;/strong&gt;'
{"rows":[
{"key":&lt;strong&gt;["2008","01","01"]&lt;/strong&gt;,"value":{"tot":20050,"count":1}},
{"key":["2008","01","02"],"value":{"tot":20019,"count":1}},
{"key":["2008","01","03"],"value":{"tot":19974,"count":1}},
{"key":&lt;strong&gt;["2008","01","04"]&lt;/strong&gt;,"value":{"tot":19878,"count":1}}
]}&lt;/pre&gt;

&lt;a name="list"&gt;&lt;/a&gt;
&lt;h2&gt;Write a _list function and render the charts!&lt;/h2&gt;
&lt;p&gt;
&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code class="javascript"&gt;function(head, req) {
	start({&amp;quot;headers&amp;quot;:{&amp;quot;Content-Type&amp;quot; : &amp;quot;image/svg+xml&amp;quot;}});
	
	// some utility functions that print svg elements
	function svg(width, height) {
		return &amp;#x27;&amp;lt;svg xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; xmlns:xlink=&amp;quot;http://www.w3.org/1999/xlink&amp;quot;&amp;#x27;+
		&amp;#x27; style=&amp;quot;fill:black&amp;quot;&amp;#x27;+
		&amp;#x27; width=&amp;quot;&amp;#x27;+width+&amp;#x27;&amp;quot; height=&amp;quot;&amp;#x27;+height+&amp;#x27;&amp;quot;&amp;gt;\n&amp;#x27;;
	}
	function line(x1, y1, x2, y2, color) {
		return &amp;#x27;&amp;lt;line x1=&amp;quot;&amp;#x27;+x1+&amp;#x27;&amp;quot; y1=&amp;quot;&amp;#x27;+y1+&amp;#x27;&amp;quot; x2=&amp;quot;&amp;#x27;+x2+&amp;#x27;&amp;quot; y2=&amp;quot;&amp;#x27;+y2+&amp;#x27;&amp;quot;
			style=&amp;quot;stroke-width: 0.2; stroke:&amp;#x27;+color+&amp;#x27;&amp;quot;/&amp;gt;\n&amp;#x27;;
	}
	function rect(x, y, width, height, color, fill) {
		return &amp;#x27;&amp;lt;rect x=&amp;quot;&amp;#x27;+x+&amp;#x27;&amp;quot; y=&amp;quot;&amp;#x27;+y+&amp;#x27;&amp;quot; width=&amp;quot;&amp;#x27;+width+&amp;#x27;&amp;quot; height=&amp;quot;&amp;#x27;+height+&amp;#x27;&amp;quot;
			style=&amp;quot;fill:&amp;#x27;+fill+&amp;#x27;; stroke:&amp;#x27;+color+&amp;#x27;&amp;quot;/&amp;gt;\n&amp;#x27;;
	}
	function text(x,y, text) {
		return &amp;#x27;&amp;lt;text x=&amp;quot;&amp;#x27;+x+&amp;#x27;&amp;quot; y=&amp;quot;&amp;#x27;+y+&amp;#x27;&amp;quot; font-size=&amp;quot;11&amp;quot;
			font-family=&amp;quot;sans-serif&amp;quot;&amp;gt;&amp;#x27;+text+&amp;#x27;&amp;lt;/text&amp;gt;\n&amp;#x27;;
	}
	
	// import query parameters
	var x_size = req.query.width || 750;
	var y_size = req.query.height || 500;
	var level = parseInt(req.query.group_level);
	
	// find max and min values
	// collect values and labels
	var y_max = null;
	var y_min = null;
	var values = [];
	var labels = [];
	var count = 0;
	while(row = getRow()) {		
		var value = Math.ceil(row.value.tot/row.value.count);
		if (y_max==null || value&amp;gt;y_max) { y_max=value; }
		if (y_min==null || value&amp;lt;y_min) { y_min=value; }
		values[count] = value;
		labels[count] = row.key.join(&amp;#x27;-&amp;#x27;);
		count++;
	}
	// calculate scalig factors
	var in_width = x_size-(2*pad);
	var in_height = y_size-(2*pad);
	var in_x_scale = in_width/count;
	var in_y_scale = in_height/(y_max-y_min);
	
	// free space surrounding the actual chart
	var pad = Math.round(y_size/12);
	
	send(&amp;#x27;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;#x27;);
	send(svg(x_size, y_size));
	
	// background box	
	send(rect(1,1, x_size, y_size, &amp;#x27;#C6F1C7&amp;#x27;, &amp;#x27;#C6F1C7&amp;#x27;));
	
	// chart container box
	send(rect(pad,pad, x_size-(2*pad), y_size-(2*pad), &amp;#x27;black&amp;#x27;,&amp;#x27;white&amp;#x27;));

	// draw labels and grid
	var y_base = y_size - pad;
	var lastx = 0;
	var lasty = 0;
	for(var i=0; i&amp;lt;count; i++) {
		var x = pad+Math.round(i*in_x_scale);
		if (i==0 || x-lastx &amp;gt; (30+12*level)) {
			send(line(x, y_base+(pad/2), x, pad,&amp;#x27;gray&amp;#x27;));
			send(text(x+3, y_base + (pad/2), labels[i]));
			lastx = x;
		}	
		var y = Math.round(y_base - ( (values[i]-y_min) * in_y_scale));
		if (i==0 || lasty-y &amp;gt; 15) {
			send(line(5, y, pad+in_width, y,&amp;#x27;gray&amp;#x27;));
			send(text(5, y-2, values[i]));
			lasty = y;
		}
	}
	// draw the actual chart
	send(&amp;#x27;&amp;lt;polyline style=&amp;quot;stroke:black; stroke-width: &amp;#x27;+ (4-level) +&amp;#x27;; fill: none;&amp;quot; points=&amp;quot;&amp;#x27;);
	for(var i=0; i&amp;lt;count; i++) {
		if (i&amp;gt;0) send(&amp;#x27;,\n&amp;#x27;);
		var x = pad+Math.round(i*in_x_scale);
		var y = Math.round(y_base - ( (values[i]-y_min) * in_y_scale));
		send( x + &amp;#x27; &amp;#x27; + y);
	}
	send(&amp;#x27;&amp;quot;/&amp;gt;&amp;#x27;);
	
	send(&amp;#x27;&amp;lt;/svg&amp;gt;&amp;#x27;);
}&lt;/code&gt;&lt;/pre&gt;

&lt;a name="results"&gt;&lt;/a&gt;
Update couchapp, and execute the list function 'chart-line' against the view 'by_date'.
Use different group_level settings, to obtain different charts:

&lt;pre class="term"&gt;curl http://localhost:5984/svg-charts-demo/_design/svg-charts/\
&lt;strong&gt;_list/chart-line/by_date&lt;/strong&gt;?group_level=&lt;strong&gt;3&lt;/strong&gt; &gt; chart-line_level-3.svg

curl http://localhost:5984/svg-charts-demo/_design/\
_list/chart-line/by_date?group_level=2 &gt; chart-line_level-2.svg

curl http://localhost:5984/svg-charts-demo/_design/\
_list/chart-line/by_date?group_level=1 &gt; chart-line_level-1.svg
&lt;/pre&gt;

&lt;div style="margin-left: auto;"&gt;
&lt;div style="float:left; text-align:center; border-right: 1px solid #f0f0f0; padding-right: 1em; padding-left: 1em;"&gt;
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-1.svg"&gt;&lt;img style="padding:0; margin:0; border:0" src="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-1.thumb.png"/&gt;&lt;/a&gt;
	&lt;strong&gt;group_level=1&lt;/strong&gt;
	yearly averages
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-1.svg"&gt;svg&lt;/a&gt; - &lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-1.png"&gt;png&lt;/a&gt;
&lt;/div&gt;
&lt;div style="float:left; text-align:center; border-right: 1px solid #f0f0f0; padding-right: 1em; padding-left: 1em;"&gt;
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-2.svg"&gt;&lt;img style="padding:0; margin:0; border:0" src="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-2.thumb.png"/&gt;&lt;/a&gt;
	&lt;strong&gt;group_level=2&lt;/strong&gt;
	monthly averages
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-2.svg"&gt;svg&lt;/a&gt; - &lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-2.png"&gt;png&lt;/a&gt;
&lt;/div&gt;
&lt;div style="float:left; text-align:center; padding-left: 1em;"&gt;	
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-3.svg"&gt;&lt;img style="padding:0; margin:0; border:0" src="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-3.thumb.png"/&gt;&lt;/a&gt;
	&lt;strong&gt;group_level=3&lt;/strong&gt;
	daily values
	&lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-3.svg"&gt;svg&lt;/a&gt; - &lt;a href="http://caprazzi.net/demos/couchdb-charts-example/chart-line_level-3.png"&gt;png&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style="clear:both"&gt;&amp;nbsp;&lt;/div&gt;

&lt;a name="conclusions"&gt;&lt;/a&gt;
&lt;h2&gt;Concusions&lt;/h2&gt;
&lt;p&gt;
	It worked.
&lt;/p&gt; 
&lt;p&gt;
	I didn't expect to use a single list function for all grouping levels. I'm particularly happy of how it worked out, and even more considering
	that the whole thing is about 100 lines of code.
&lt;/p&gt;
&lt;p&gt;
	The output isn't too nice, but I think I can be made presentable with under 500 lines of code and some effort.
&lt;/p&gt;
&lt;p&gt;
	Couchdb is always a pleasure to work with and it goas a long way in minimizing "Time To something Done".
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/pxtC3zJBnEw" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/charting-data-with-couchdb</feedburner:origLink></entry>
 
 <entry>
   <title>Learning Closure: managing dependencies and compiling</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/M4_zqYvmDK8/learning-closure-managing-dependencies-and-compiling" />
   <updated>2009-12-04T10:42:36+00:00</updated>
   <id>http://caprazzi.net//posts/learning-closure-managing-dependencies-and-compiling</id>
   <content type="html">&lt;p&gt;Google's &lt;a title="Closure Library" href="http://code.google.com/closure/library/index.html"&gt;closure library&lt;/a&gt; offers semantics and tools to manage dependencies between modules. This is specially useful when building single-page javascript applications.&lt;/p&gt;

&lt;p&gt;To find out how smoothly this works, I'll build a simple javascript application that given a string, displays its MD5 hash. We'll&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;create a simple component&lt;/li&gt;
	&lt;li&gt;crate a template with &lt;a title="Closure Templates" href="http://code.google.com/closure/templates/"&gt;closure templates&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;import a third party library  (&lt;a title="jshash" href="http://pajhome.org.uk/crypt/md5/scripts.html"&gt;jshash library&lt;/a&gt;) to do the md5 hashing&lt;/li&gt;
	&lt;li&gt;build a dependency tree that includes all of the aobove using the &lt;a title="Dependency Calculation Script" href="http://code.google.com/closure/library/docs/calcdeps.html"&gt;Dependency Calculation Script&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;concatenate all dependencies in one script&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="xbox"&gt;&lt;p&gt;If you have used jQuery you'll find that this code is verbose and painfully similar to java.&lt;/p&gt;
	
&lt;p&gt;To ease your mind, think that structured libraries like Closure and &lt;a title="Yahoo User Interface Library" href="http://developer.yahoo.com/yui/"&gt;YUI&lt;/a&gt; tend to promote more readable and maintainable code (at the expense of coolness).&lt;/p&gt; 
&lt;p&gt;Closure and YUI are a better fit when the goal is to build a complex application.&lt;/p&gt;&lt;/div&gt;

&lt;h2&gt;Try this at home&lt;/h2&gt;

See the &lt;a href="http://caprazzi.net/demos/closure-dependencies-example/index_live.html"&gt;demo&lt;/a&gt; of the sample application discussed below.
You can browse &lt;a href="http://github.com/mcaprari/closure-dependencies-example"&gt;browse&lt;/a&gt; or  &lt;a href="http://github.com/mcaprari/closure-dependencies-example/zipball/master"&gt;download&lt;/a&gt; all source code&lt;/a&gt; discussed here, including all 3rd party libraries. I welcome all comments and corrections.

&lt;h2&gt;Project setup&lt;/h2&gt;

&lt;p&gt;Create an empty directory (i called mine goog-dependencies-example), enter it and download all the stuff&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Download the closure library
&lt;pre style="display:inline"&gt;svn export http://closure-library.googlecode.com/svn/trunk/ closure-library&lt;/pre&gt;
&lt;/li&gt;
	&lt;li&gt;Download &lt;a title="Closure Templates Latest" href="http://closure-templates.googlecode.com/files/closure-templates-for-javascript-latest.zip"&gt;closure template tools&lt;/a&gt; and expand it in closure-templates/&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://pajhome.org.uk/crypt/md5/jshash-2.2.zip"&gt;Download the jshash library&lt;/a&gt; and unzip it&lt;/li&gt;
&lt;/ul&gt;
You should now have a structure like this:
&lt;pre&gt;goog-dependencies-example\
  |-- closure-templates\
  |-- closure-library\
  |-- jshash-2.2\&lt;/pre&gt;
&lt;p&gt;Publish this directory on a web server.&lt;/p&gt; 

&lt;p&gt;During development, I use
&lt;a href="http://www.lighttpd.net/"&gt;lighttpd&lt;/a&gt; with this &lt;a title="lighttpd minimal config" href="http://caprazzi.net/wp-content/uploads/2009/12/lhttpd-minimal.txt"&gt;minimal configuration file&lt;/a&gt; to quickly publish just a directory. Save the file in the directory you want to publish, run &lt;strong&gt;lighttpd -D -f lhttpd-minimal.txt&lt;/strong&gt; and browse to http://localhost:3030/. Lighttpd is available on ubuntu, macos (via macports) and windows (via cygwin).&lt;/p&gt;

&lt;h2&gt;UI: template&lt;/h2&gt;

We need a ui component with a textarea to input some text, a button to execute and and a textarea to see the results. Using closure template is definitely overkill here, but it's useful to demonstrate how to load templates a dependencies.

Create the file md5.ui.template.soy
&lt;pre class="code"&gt;&lt;code class="html"&gt;{namespace net.caprazzi.md5.ui.template}

/**
 * md5 ui template
 * To retrieve its contents, invoke the function
 * net.caprazzi.md5.template.ui.main()
 */
{template .main}
&amp;lt;div class=&amp;quot;md5-ui&amp;quot;&amp;gt;
	&amp;lt;textarea class=&amp;quot;md5-input&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br/&amp;gt;
	&amp;lt;button class=&amp;quot;md5-action&amp;quot;&amp;gt;Hash It!&amp;lt;/button&amp;gt;&amp;lt;br/&amp;gt;
	&amp;lt;textarea class=&amp;quot;md5-output&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;/div&amp;gt;
{/template}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And execute this command to compile it to a javascript file:&lt;/p&gt;
&lt;pre class="term"&gt;$ java -jar closure-templates/SoyToJsSrcCompiler.jar \
	--shouldProvideRequireSoyNamespaces \
	--outputPathFormat &lt;strong&gt;js/md5.ui.template.js&lt;/strong&gt; md5.ui.template.soy&lt;/pre&gt;
&lt;pre class="code"&gt;&lt;code class="javascript"&gt;// This file was automatically generated from md5.ui.template.soy.
// Please don't edit this file by hand.

goog.provide('net.caprazzi.md5.ui.template');

goog.require('soy');
goog.require('soy.StringBuilder');

net.caprazzi.md5.ui.template.main = function(opt_data, opt_sb) {
  var output = opt_sb || new soy.StringBuilder();
  output.append('&amp;lt;div class=&amp;quot;md5-ui&amp;quot;&amp;gt;
	&amp;lt;textarea class=&amp;quot;md5-input&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br/&amp;gt;
	&amp;lt;button class=&amp;quot;md5-action&amp;quot;&amp;gt;Hash It!&amp;lt;/button&amp;gt;&amp;lt;br/&amp;gt;
	&amp;lt;textarea class=&amp;quot;md5-output&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;');
  if (!opt_sb) return output.toString();
};&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;UI: javascript&lt;/h2&gt;

Now let's write some code that hashes the contents of the first textarea when the button is clicked.
Name the file js/md5.ui.js.

&lt;pre class="code"&gt;&lt;code class="javascript"&gt;goog.provide('net.caprazzi.md5.ui');

// NOTE the inclusion of our template
goog.require('net.caprazzi.md5.ui.template');

// NOTE the inclusion of jshash
// as defined in third_party_deps.js
goog.require('jshash.md5');

goog.require('goog.events');
goog.require('goog.dom');

net.caprazzi.md5.Ui = function(parent) {
	this.parent = parent;
}

net.caprazzi.md5.Ui.prototype.render = function() {
	var html = net.caprazzi.md5.ui.template.main();
	this.parent.innerHTML = html;
	this.input = goog.dom.$$('textarea', 'md5-input', this.parent)[0];
	this.button = goog.dom.$$('button', 'md5-action', this.parent)[0];
	this.output = goog.dom.$$('textarea', 'md5-output', this.parent)[0];

	var self = this;
	goog.events.listen(this.button,
			goog.events.EventType.CLICK,
			function() { self.onButton_()});
}

net.caprazzi.md5.Ui.prototype.onButton_ = function() {
	this.output.value = hex_md5(this.input.value);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Application entry point&lt;/h2&gt;
&lt;p&gt;This file exposes the function main(), that will be executed at page load. It only requires the two modules that uses directly&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code class="javascript"&gt;goog.provide('net.caprazzi.md5.application');

goog.require('net.caprazzi.md5.ui');
goog.require('goog.dom');

net.caprazzi.md5.application.main = function() {
	var container = document.getElementById('md5-ui-container');
	var ui = new net.caprazzi.md5.Ui(container);
	ui.render();
}&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;deps.js: the dependencies file &lt;/h2&gt;

&lt;p&gt;Calcdeps.py is a script that comes with closure library. It parses the source files in search of &lt;strong&gt;goog.require()&lt;/strong&gt; and &lt;strong&gt;goog.provide()&lt;/strong&gt; declarations. It then uses those declarations to build a dependency tree.&lt;/p&gt;

&lt;p&gt;The dependency tree is stored in a file as a list of &lt;a title="addDependency documentation" href="http://closure-library.googlecode.com/svn/trunk/closure/goog/docs/closure_goog_base.js.source.html#line218"&gt;goog.addDependency&lt;/a&gt; calls. Each calls describes a file and the modules it provieds and requires. This line declares that md5.component.js will provide 'net.caprazzi.md5' and require 'net.caprazzi.md5.template' and others:
&lt;/p&gt;	
&lt;pre&gt;&lt;code class="javascript"&gt;
goog.addDependency('js/md5.component.js',
    ['net.caprazzi.md5'],
    ['net.caprazzi.md5.template', 'goog.events', 'goog.dom', 'jshash']);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Run this command in the root of the project to generate the deps.js all the dependecies (including google's). This may take a while.&lt;/p&gt;

&lt;pre class="term"&gt;$ python closure-library/closure/bin/calcdeps.py \
    -p closure-library/closure \
    -p closure-library/third_party \
    -p closure-templates \
    -p js \
    -i js /md5.* \
    -o deps \
&gt; deps.js&lt;/pre&gt;

&lt;p&gt;The option '-o deps' tells calcdeps.py to output a dependency tree. The other options specify the source directories and files. Spend a moment to review the contents of the resulting file.&lt;/p&gt;

&lt;h2&gt;Managing the third party library 'md5.js'&lt;/h2&gt;

&lt;p&gt;As I explained above, calcdeps uses special declarations in the javascript files to make sense of the dependencies. We know that by 'jshash.md5' i mean 'jshash-2.2/md5.js' but calcdeps could only figure this out if the file included a correct goog.require statement.&lt;/p&gt;

&lt;p&gt;At this point we may just add the line to the file and go on with our lives. But we all agree that editing 3rd party libraries is not a good practice.&lt;/p&gt;
&lt;p&gt;I maintain a text file 'extradeps.txt' where each line associates a module to a file, in this case the contents are&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;jshash.md5 jshash-2.2/md5-min.js&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;Then a simple python script parses that file and generates the missing addDependency() statements:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;code&gt;import sys
for mod, path in [  line.strip().split(' ') for line in file(sys.argv[1]) ]:
	print "goog.addDependency('%s',['%s'],[]);" % (path, mod)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Execute the script to see what the output looks like. Then remember to concatenate its output to deps.js each time your rebuild:&lt;/p&gt;
&lt;pre class="term"&gt;$ python fix_deps_file.py extradeps.txt &gt;&gt; deps.js&lt;/pre&gt;

&lt;h2&gt;in dev: index_dev.html&lt;/h2&gt;

&lt;p&gt;The last piece of the puzzle is the one that holds everything together: the html&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code class="html"&gt;&amp;lt;html&amp;gt;
	&amp;lt;head&amp;gt;
		&amp;lt;title&amp;gt;Hash me, hash me&amp;lt;/title&amp;gt;
		&amp;lt;script&amp;gt;
			CLOSURE_NO_DEPS=true;
			CLOSURE_BASE_PATH=&amp;quot;./&amp;quot;;
		&amp;lt;/script&amp;gt;
		&amp;lt;script src=&amp;quot;closure-library/closure/goog/base.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
		&amp;lt;script src=&amp;quot;deps.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
		&amp;lt;script&amp;gt;
			goog.require(&amp;#x27;net.caprazzi.md5.application&amp;#x27;);
		&amp;lt;/script&amp;gt;
	&amp;lt;/head&amp;gt;
	&amp;lt;body onload=&amp;quot;net.caprazzi.md5.application.main();&amp;quot;&amp;gt;
		&amp;lt;h3&amp;gt;Hash me, hash me&amp;lt;/h3&amp;gt;
		&amp;lt;div id=&amp;quot;md5-ui-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
	&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the two global directives before the inclusion of base.js: &lt;ul&gt;&lt;li&gt;&lt;strong&gt;CLOSURE_NO_DEPS&lt;/strong&gt; stops closure from loading its own deps.js&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CLOSURE_BASE_PATH&lt;/strong&gt; tells closure file loader how to build the script urls.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;

&lt;p&gt;Note that the html file only imports closure's base.js and deps.js then invokes directly code that comes from md5.ui.js&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Navigate to index.html, the application should be working.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use firebug or another network monitor, to see how the browser is downloading many different files to satisfy all the dependencies. This is the perfect behaviour for development, because separate files are easier to debug.&lt;/p&gt;

&lt;h2&gt;going live: the single js file and index_live.html&lt;/h2&gt;

&lt;p&gt;Loading many small javascript files is an evil practice in production.
We definitely want to have all our javascript files concatenated in one big blob.&lt;/p&gt;

&lt;p&gt;I previously used calcdeps.py with the option '-o deps' to build a dependency tree. Calcdeps can also concatenate all your dependancies right away, using the option '-o script'. Unfortunately if you try to run it against our code, it will terminate with an exception (&lt;pre style="display:inline"&gt;Exception: Missing provider for (jshash.md5)&lt;/pre&gt;. Clearly, again, the dependency script doesn't know which files provides that module&lt;/p&gt;

&lt;p&gt;Python to the rescue again: we'll reuse the extradeps.txt file with a new python script that takes all the external deps and puts them in a file along with the correct goog.provide() statements.&lt;/p&gt;
&lt;pre class="code"&gt;&lt;code&gt;import sys
mods = [  line.strip().split(' ') for line in file(sys.argv[1]) ];
for mod, path in mods:
	print "goog.provide('%s');" % (mod)
for mod, path in mods:
	for line in file(path):
		print line&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt; Running this script produces a calcdeps-friendly javascript file:&lt;/p&gt;
&lt;pre class="term"&gt;$ mkdir tmp/
$ python concat_extra_deps.py extradeps.txt &gt; &lt;strong&gt;tmp&lt;/strong&gt;/extra.js
&lt;/pre&gt;
&lt;p&gt; We can now tell calcdeps to look into tmp/ to find what's needed to build our big target file:&lt;/p&gt;
&lt;pre class="term"&gt;$ python closure-library/closure/bin/calcdeps.py \
	-p closure-library \
	-p &lt;strong&gt;tmp&lt;/strong&gt; \
	-p js \
	-p closure-templates \
 	-i js/md5.application.js \
    -o script \
&amp;gt; &lt;strong&gt;md5_application.js&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;Now we can produce the final artifact and go live with index_live.html:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;code class="html"&gt;&amp;lt;html&amp;gt;
	&amp;lt;head&amp;gt;
		&amp;lt;title&amp;gt;Hash me, hash me&amp;lt;/title&amp;gt;
		&amp;lt;script src=&amp;quot;md5_application.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
	&amp;lt;/head&amp;gt;
	&amp;lt;body onload=&amp;quot;net.caprazzi.md5.application.main();&amp;quot;&amp;gt;
		&amp;lt;h3&amp;gt;Hash me, hash me&amp;lt;/h3&amp;gt;
		&amp;lt;div id=&amp;quot;md5-ui-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
	&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;I've done this exercise to understand if the closure's dependency management would be usable in a production environment.&lt;/p&gt;

&lt;p&gt;There was some initial misunderstanding between calcdeps and me and I had to look at base.js to understand what was going on and to find out about the global directives that influence the loader.&lt;/p&gt;

&lt;p&gt;The  syntax is neat and serves the double purpose of managing namespaces and dependencies.&lt;/p&gt;

&lt;p&gt;My impression is that at least the goog.require/provide syntax and the calcdeps.py script can be used in production with confidence.&lt;/p&gt;

&lt;p&gt;Closure dosen't allow to specify css files as dependencies, while it's possible with YUI3 (that sports a cool dependency management mechanism of his own).&lt;/p&gt;

&lt;p&gt;As an exercise you can think about adding a compilation step using google closure compiler.&lt;/p&gt;

&lt;pre&gt;-teo&lt;/pre&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/M4_zqYvmDK8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/learning-closure-managing-dependencies-and-compiling</feedburner:origLink></entry>
 
 <entry>
   <title>Book: Programming Collective Intelligence</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/4x-tSjL8Pz4/book-programming-collective-intelligence" />
   <updated>2009-12-02T18:47:06+00:00</updated>
   <id>http://caprazzi.net//posts/book-programming-collective-intelligence</id>
   <content type="html">Programming books are seldom page turners, even for geeks like us. And programming books often fail to go beyond the technology. Programming books are rarely as good as this one. Allow me to digress for a moment.

Online there is a lot of data about you. And me. Our reactions have been logged, our desires noted. You know where I am now. I know your status. Ok, I'm being dramatic, but bear with me. I have a point.

All this data tells one story and million stories in their gritty details. And since past behaviour is a good predictor of future behaviour, I can read your ve&lt;a href="http://caprazzi.net/wp-content/uploads/2009/12/kernel_tricl.jpg"&gt;&lt;img class="size-thumbnail wp-image-148 alignright" title="kernel_tricl" src="http://caprazzi.net/wp-content/uploads/2009/12/kernel_tricl-150x150.jpg" alt="kernel_tricl" width="150" height="150" /&gt;&lt;/a&gt;ry future in those million stories.

Not so easy, of course. All those records are generated by humans and computers. It's cybernetic data, its scale and complexity are beyond belief. We can only make sense of that data using computers.

Back to the topic. This very thick yet enjoyable book is a programmer's journey in the world of machine learning and statistics.

The author, Toby Segaran, is brilliant. He will hold your hand while describing many algorithms an techniques. He'll tell you just enough theory to make sense of what's going on. And then, plain simple python, down with the implementation.

Interested in building and thinking about a recommendation engine? What about picking a good &lt;a href="http://anthony.liekens.net/images/cluster12.png"&gt;&lt;img class="alignleft size-thumbnail wp-image-149" title="music generes" src="http://caprazzi.net/wp-content/uploads/2009/12/cluster12-150x150.png" alt="music generes" width="150" height="150" /&gt;&lt;/a&gt;solution to a proble, amongst millions? Curious about genetic programming? Wanna have your own spam filter?

The last great thing about this book are the example. Real world, not your usual fictional pet shop. You'll fetch data from your delicious account, correlate live stock market data from yahoo, analyze your favorite blogs and more stuff.

Tony writing is unpretentious and the book is easy to read, but beware there is a lot of meat to digest. Don't rush.
&lt;p style="text-align: center;"&gt;&lt;a href="http://www.amazon.co.uk/gp/product/0596529325?ie=UTF8&amp;amp;tag=mattcapr-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=0596529325"&gt;&lt;img class="size-full wp-image-147 aligncenter" title="collective_intelligence" src="http://caprazzi.net/wp-content/uploads/2009/12/collective_intelligence.jpg" alt="collective_intelligence" width="122" height="160" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/4x-tSjL8Pz4" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/book-programming-collective-intelligence</feedburner:origLink></entry>
 
 <entry>
   <title>Learning Closure. Ajax with goog.net.*</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/FgwJkzIaGBA/learning-closure-ajax-with-goog-net" />
   <updated>2009-11-12T00:20:52+00:00</updated>
   <id>http://caprazzi.net//posts/learning-closure-ajax-with-goog-net</id>
   <content type="html">Google released &lt;a href="http://closure-library.googlecode.com/svn/trunk/closure/goog/docs/index.html"&gt;closure library&lt;/a&gt;, a javascript library good to make rich internet applications.

As this is going to be an important library in software developement, I decided to try it. 'Ajax' networking is a good starting point, so I looked into the package goog.net and found two promising classes, &lt;a href="http://closure-library.googlecode.com/svn/trunk/closure/goog/docs/class_goog_net_XhrLite.html"&gt;HxrIo&lt;/a&gt; and &lt;a href="http://closure-library.googlecode.com/svn/trunk/closure/goog/docs/class_goog_net_XhrManager.html"&gt;XhrManager&lt;/a&gt;, which I used for my tests.

The documentation is clear but sometimes shy about who does what. Fortunately there are plenty of links to the source code, which is well written and documented.

The interesting code is below, but there's a more extend version of my &lt;a href="http://caprazzi.net/wp-content/uploads/2009/11/closure.js"&gt;closure-library tests&lt;/a&gt;.

&lt;strong&gt;Just hit a url without waiting for a response&lt;/strong&gt;
&lt;pre class="code"&gt;&lt;code class="javascript"&gt;
// load the modules
goog.require('goog.net.XhrIo');
goog.require('goog.Uri');

// the easy way: static function call with no callback
goog.net.XhrIo.send('url/');

// using the send() method of an instance.
new goog.net.XhrIo().send('urlA'); // GET, default
new goog.net.XhrIo().send('urlB', 'POST');

// also works with an Uri object
var uri = new goog.Uri('urlC');
new goog.net.XhrIo().send(uri, 'PUT');

// no http method validation, this is a valid call
new goog.net.XhrIo().send('urlF', 'XXXX');

// send some data with the POST, works as expected
new goog.net.XhrIo().send('urlG', 'POST', 'p1=v1&amp;p2=v2);

// ATTENTION data will not be attached to a GET
// so this call won't do what you may expect.
new goog.net.XhrIo().send('urlH', 'GET', 'p1=v1&amp;p2=v2');

&lt;/code&gt;&lt;/pre&gt;
&lt;strong&gt;Request data from the server&lt;/strong&gt;
&lt;pre  class="code"&gt;&lt;code class="javascript"&gt;
// an html file as text
goog.net.XhrIo.send('sample.html', function(event) {
	var text = event.target.getResponseText());
});

// an xml file as document object
goog.net.XhrIo.send('sample.xml', function(event) {
	var document = event.target.getResponseXml());
});

// a json file as javascript object
goog.net.XhrIo.send('sample.json.js', function(event) {
	var data = event.target.getResponseJson());
});

// spot the 404
goog.net.XhrIo.send('gone_fishin', function(event) {
	var success = event.target.isSuccess()); // false
	var status = event.target.getStatus()); // 404
	var statusText = event.target.getStatusText()); // not found
});

// !!! exceptions in the callback are swallowed, so check your conditions
// (there is interesting error handling stuff in goog.debug.*)
goog.net.XhrIo.send('gone_fishin.js', function(event) {
	// I expected some data, but the file is not there
	// and this will raise an exception...
	var data = event.target.getResponseJson();
	var field_data = data.field;
	// ...so this statement will not execute...
	alert('bonk');
	// ...BUT you won't see anything in your console.
});

// a 404 using an XhrIO instance and closure event management;
var io = new goog.net.XhrIo();
goog.events.listen(io, goog.net.EventType.COMPLETE, function(event) {
	var status = event.target.getStatus()); // 404
});
io.send('gone_fishin');
&lt;/code&gt;&lt;/pre&gt;
&lt;strong&gt;Using the connection manager&lt;/strong&gt;
&lt;pre  class="code"&gt;&lt;code class="javascript"&gt;
goog.require('goog.net.XhrManager');

// goog.net.XhrManager(opt_maxRetries, opt_headers, opt_minCount, opt_maxCount, opt_timeoutInterval)
var mgr = new goog.net.XhrManager(2, null, 0, 2);
goog.events.listen(mgr, goog.net.EventType.COMPLETE, function(event) {
	// this is fired once for each send(), even if they are retried
	var xhr = event.xhrIo;
});
mgr.send('id_one','closure.js');
mgr.send('id_two','/urlTwo');
mgr.send('id_three','/urlThree');
mgr.send('id_four','/urlFour');

// reusing an id before the request is complete, causes an exception...
try { mgr.send('id_one','/x'); }
catch (e) { /*[goog.net.XhrManager] ID in use*/ }

// ...unless the connection is aborted
mgr.abort('id_one');
mgr.send('id_one','/x');

mgr.send('other_id','/someurl', null, null, null, function(event) {
	// it's ok to reuse an id an after the request completed
	mgr.send('other_id', '/fool');
});
&lt;/code&gt;&lt;/pre&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/FgwJkzIaGBA" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/learning-closure-ajax-with-goog-net</feedburner:origLink></entry>
 
 <entry>
   <title>book: forms that work</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/vj5R9EVDPiQ/book-forms-that-work" />
   <updated>2009-10-23T15:13:00+00:00</updated>
   <id>http://caprazzi.net//posts/book-forms-that-work</id>
   <content type="html">&lt;a href="http://www.amazon.co.uk/gp/product/1558607102?ie=UTF8&amp;amp;tag=mattcapr-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=1558607102"&gt;Forms that Work: Designing Web Forms for Usability&lt;/a&gt;

There is no html in this book, it's not about &lt;em&gt;programming&lt;/em&gt; forms. And that's why I liked it.

This short book clarifies what good form design is about, in plain english. Plenty of images help, too.
I'm still not too good at designing forms but at least now I know the name of the game.

-teo

&lt;a href="http://www.amazon.co.uk/gp/product/1558607102?ie=UTF8&amp;amp;tag=mattcapr-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=1558607102"&gt;&lt;img class="aligncenter size-full wp-image-20" title="forms_that_work" src="http://caprazzi.net/wp-content/uploads/2009/10/forms_that_work.jpg" alt="forms_that_work" width="324" height="400" /&gt;&lt;/a&gt;

&lt;img class=" xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna" style="border: medium none ! important; margin: 0px ! important;" src="http://www.assoc-amazon.co.uk/e/ir?t=mattcapr-21&amp;amp;l=as2&amp;amp;o=2&amp;amp;a=1558607102" border="0" alt="" width="1" height="1" /&gt;

&lt;img class=" xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl xfeavtjxflhootapcnfl yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna yjddqndlqpyttkcjyvna" style="border: medium none ! important; margin: 0px ! important;" src="http://www.assoc-amazon.co.uk/e/ir?t=mattcapr-21&amp;amp;l=as2&amp;amp;o=2&amp;amp;a=1558607102" border="0" alt="" width="1" height="1" /&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/vj5R9EVDPiQ" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/book-forms-that-work</feedburner:origLink></entry>
 
 <entry>
   <title>book: don't make me think</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/4YPobBNQFMM/book-dont-make-me-think" />
   <updated>2009-10-15T14:14:00+00:00</updated>
   <id>http://caprazzi.net//posts/book-dont-make-me-think</id>
   <content type="html">&lt;a href="http://www.amazon.co.uk/gp/product/0321344758?ie=UTF8&amp;amp;tag=mattcapr-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=0321344758"&gt;Don't Make Me Think!: A Common Sense Approach to Web Usability&lt;/a&gt;&lt;img alt="" border="0" class=" otyqdzmkhdlxnjpvinec otyqdzmkhdlxnjpvinec otyqdzmkhdlxnjpvinec otyqdzmkhdlxnjpvinec" height="1" src="http://www.assoc-amazon.co.uk/e/ir?t=mattcapr-21&amp;amp;l=as2&amp;amp;o=2&amp;amp;a=0321344758" style="border: medium none ! important; margin: 0px ! important;" width="1" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://www.amazon.co.uk/gp/product/0321344758?ie=UTF8&amp;amp;tag=mattcapr-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=0321344758" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://ecx.images-amazon.com/images/I/51W8l2Zy3WL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA240_SH20_OU02_.jpg" width="200" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Delightful one-night read. Some good common sense advice on web design and two brilliant chapters on usability testing on a budget.&lt;br /&gt;&lt;br /&gt;common sense is underrated&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/4YPobBNQFMM" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/book-dont-make-me-think</feedburner:origLink></entry>
 
 <entry>
   <title>netflix prize contest, a new one</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/T3EF6NlHyx0/netflix-prize-contest-a-new-one" />
   <updated>2009-10-08T12:57:00+00:00</updated>
   <id>http://caprazzi.net//posts/netflix-prize-contest-a-new-one</id>
   <content type="html">&lt;a href="http://www.the-ensemble.com/images/small_title.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" src="http://www.the-ensemble.com/images/small_title.jpg" style="cursor: pointer; float: right; height: 153px; margin: 0pt 0pt 10px 10px; width: 240px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;With netflix &lt;/span&gt;&lt;a href="http://www.netflixprize.com//community/viewtopic.php?id=1520" style="font-family: arial;"&gt;announcing &lt;/a&gt;&lt;span style="font-family: arial;"&gt;a new contest, it's time to look back at how the &lt;/span&gt;&lt;a href="http://www.netflixprize.com/" style="font-family: arial;"&gt;Netflix Prize&lt;/a&gt;&lt;span style="font-family: arial;"&gt; ended:&lt;/span&gt;&lt;a href="http://www.research.att.com/%7Evolinsky/netflix/bpc.html" style="font-family: arial;"&gt; BellKor's Pragmatic Chaos&lt;/a&gt;&lt;span style="font-family: arial;"&gt; team (AT&amp;amp;T Research engineers) won over &lt;/span&gt;&lt;a href="http://www.the-ensemble.com/" style="font-family: arial;"&gt;the ensemble&lt;/a&gt;&lt;span style="font-family: arial;"&gt; (a creek &lt;/span&gt;&lt;span style="font-family: arial;"&gt;of lower-ranked contestants&lt;/span&gt;&lt;span style="font-family: arial;"&gt;), just minutes before the deadline.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;Both teams blended together different algorithms to improve by 10% the hit rate of existing netflix suggestion engine.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;This is a story of monkeys and challenges, interesting beyond bytes and keyboards. Wired has good coverage, but you can google for more.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;I'm reading &lt;/span&gt;&lt;a href="http://www.amazon.co.uk/gp/product/0596529325?ie=UTF8&amp;amp;tag=mattcapr-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=6738&amp;amp;creativeASIN=0596529325" style="font-family: arial;"&gt;Programming Collective Intelligence&lt;/a&gt;&lt;span style="font-family: arial;"&gt;, which so far is ranking high: it uses easy-to-read-and-write python to build suggestion engines using many different algorithms. For programmers.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;story coverage:&lt;/span&gt;&lt;br /&gt;&lt;ul style="font-family: arial;"&gt;&lt;li style="font-family: courier new;"&gt;&lt;span style="font-size: 85%;"&gt;&lt;a href="http://www.wired.com/epicenter/2009/09/how-the-netflix-prize-was-won/"&gt;how the netflix prize was won&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="font-family: courier new;"&gt;&lt;span style="font-size: 85%;"&gt;&lt;a href="http://www.wired.com/epicenter/2009/09/bellkors-pragmatic-chaos-wins-1-million-netflix-prize/"&gt;bellkor’s pragmatic chaos wins $1 million netflix prize by mere minutes&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="font-family: courier new;"&gt;&lt;span style="font-size: 85%;"&gt;&lt;a href="http://www.wired.com/epicenter/2009/06/winning-teams-join-to-qualify-for-1-million-netflix-prize/"&gt;winning teams join to qualify for $1 million netflix prize&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: 85%;"&gt;&lt;a href="http://www.wired.com/techbiz/media/magazine/16-03/mf_netflix"&gt;this psychologist might outsmart the math brains competing for the netflix prize&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;related papers:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li style="font-family: arial;"&gt;&lt;a href="http://www.netflixprize.com/assets/grandprize2009_bpc_bellkor.pdf"&gt;the bellkor solution to the netflix grand prize&lt;/a&gt;&lt;/li&gt;&lt;li style="font-family: arial;"&gt;&lt;a href="http://www.netflixprize.com/assets/grandprize2009_bpc_bigchaos.pdf"&gt;the bigchaos solution to the netflix grand prize&lt;/a&gt;&lt;/li&gt;&lt;li style="font-family: arial;"&gt;&lt;a href="http://www.netflixprize.com/assets/grandprize2009_bpc_pragmatictheory.pdf"&gt;the pragmatic theory solution to the netflix grand prize&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://netflixkddworkshop2008.info/accepted.html" style="font-family: arial;"&gt;large-scale recommender systems and the netflix prize competition&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;&lt;br /&gt;&lt;/h1&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/T3EF6NlHyx0" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/netflix-prize-contest-a-new-one</feedburner:origLink></entry>
 
 <entry>
   <title>Above the Clouds: The View from Berkeley</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/itf8oFecsE8/above-the-clouds-the-view-from-berkeley" />
   <updated>2009-08-03T11:34:00+00:00</updated>
   <id>http://caprazzi.net//posts/above-the-clouds-the-view-from-berkeley</id>
   <content type="html">&lt;a href="http://radlab.cs.berkeley.edu/"&gt;RAD Lab&lt;/a&gt; released &lt;a href="http://d1smfj0g31qzek.cloudfront.net/abovetheclouds.pdf"&gt;Above the Clouds: The View from Berkeley&lt;/a&gt; (pdf) an high-level overview of the cloud. It's great read for anyone interested in the subject, no need to be involved in software development.&lt;br /&gt;&lt;br /&gt;It's the best text on the subject that I've read so far: the authors start and stay above the cloud,  avoid stepping on technical traps, yet they never become too theoretical.&lt;br /&gt;&lt;br /&gt;The paper will tell you what the cloud is and what is not, how it fits in today's IT ecology. It also describes the "economics of the cloud" with no-nonsense formulas and pragmatic statements, making sensible assumptions and predictions.&lt;br /&gt;&lt;br /&gt;If anything, I think it underestimates the impact of private clouds for small and medium organizations in the future. Designing your data center as cloud buys you a greater potential for scalability and flexibility.&lt;br /&gt;&lt;br /&gt;Add that even a tiny company benefits from exposing its data layer as a service with domain specific logic (that is, a SaaS with an API), and that couples perfectly with a cloud architecture.&lt;br /&gt;&lt;br /&gt;This is straightforward only for new organizations; a massive paradgim switch in an existing company could well kill it...
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/itf8oFecsE8" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/above-the-clouds-the-view-from-berkeley</feedburner:origLink></entry>
 
 <entry>
   <title>Falickaway: a flickr viewer</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/zmwrDJ4jkbI/falickaway-a-flickr-viewer" />
   <updated>2008-10-03T21:57:00+00:00</updated>
   <id>http://caprazzi.net//posts/falickaway-a-flickr-viewer</id>
   <content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family:verdana;"&gt;Available now: &lt;a href="http://flickaway.s3.amazonaws.com/flickaway.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;flickaway&lt;/span&gt;&lt;/span&gt;&lt;/a&gt; (&lt;a href="http://flickaway.s3.amazonaws.com/matteo.html"&gt;demo&lt;/a&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;I love &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;flickr&lt;/span&gt;&lt;/span&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;I also love my pictures, and sometimes &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;flickr&lt;/span&gt;&lt;/span&gt; feels too... generic? impersonal?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Anyway. I decided to spend some time coding this &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;flickr&lt;/span&gt; viewer so to have a website with my style and the same pictures I have on &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;flickr&lt;/span&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;I thought someone else might find it useful. If you like it, just go there, run the &lt;a href="http://flickaway.s3.amazonaws.com/setup.html"&gt;wizard&lt;/a&gt;, copy the generated html in an html file. Deploy to a web server. done.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Yes, the wizard is javascript-only as well.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;I almost forgot: that html page is less than 2k.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;All the javascript and the styles will be fetched from my website (or &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;google&lt;/span&gt;, or yahoo), so you'll always get the newest and best version.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;A brief on technology:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;I'm using &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;jQuery&lt;/span&gt; (from &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;googleapis&lt;/span&gt;.com), &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;google&lt;/span&gt; feed &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;apis&lt;/span&gt; and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;flickr&lt;/span&gt; rest &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;api&lt;/span&gt; (on the wizard, to discover your feeds). All files are &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;gzipped&lt;/span&gt; then deployed on &lt;a href="http://aws.amazon.com/s3/"&gt;Amazon S3.&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Matteo&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/zmwrDJ4jkbI" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/falickaway-a-flickr-viewer</feedburner:origLink></entry>
 
 <entry>
   <title>[C Testing] MinUnit - less is more</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/BwSuRlw-Vm4/c-testing-minunit-less-is-more" />
   <updated>2008-09-08T11:48:00+00:00</updated>
   <id>http://caprazzi.net//posts/c-testing-minunit-less-is-more</id>
   <content type="html">&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;- Can a whole framework be 3 lines long?&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold; "&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:Georgia;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;The C project I'm &lt;/span&gt;&lt;a href="http://code.google.com/p/codalyze/wiki/CyzRgb"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;working on&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt; is quite small in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;LOC&lt;/span&gt; and files. It won't grow much as it's deployed on a chip with 4k program space and 256 &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;bytes&lt;/span&gt; of ram.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;No matter how small, test all your code. Always. Period.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;Problem is, where to start?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Approaching unit testing may go down two different paths.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Write few functions with ifs and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;printfs&lt;/span&gt;, call them from a main(), execute and see. It's prone to code duplication and you'll soon start reinventing the wheel. You are paving your way to &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;a maintainability hell&lt;/span&gt;. Anyway, It might work for small projects and is &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;very easy to get started&lt;/span&gt; with. &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Otherwise you can embrace a framework such as &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;CppUnit&lt;/span&gt; o Check, learn it and start writing tests. You get more power and less duplication. You'll benefit from &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;standardization, automation and much more&lt;/span&gt;. It's the best approach, except for the &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;steep learning curve&lt;/span&gt;. Add that writing tests is not exciting nor easy, and you might end up being so &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;frustrated &lt;/span&gt;that you'll never get your test suite done. &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Introducing &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;the solution&lt;/span&gt;: &lt;/span&gt;&lt;a href="http://www.jera.com/techinfo/jtns/jtn002.html"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;MinUnit&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;, a unit testing framework in 3 lines of code (!!!!):&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt; &lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: italic; "&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;/* file: &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;minunit&lt;/span&gt;.h */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"   style="  ;font-family:'courier new';font-size:16px;"&gt; #define mu_assert(message, test) do { if (!(test)) return message; } while (0)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; #define mu_run_test(test) do { char *message = test(); tests_run++; \ &lt;div style="text-align: justify;"&gt;)  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;extern&lt;/span&gt; int tests_run;&lt;br /&gt;&lt;/div&gt;                                if (message) return message; } while (&lt;br /&gt;&lt;div style="text-align: justify;"&gt;0&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;(This kind of magic is why I really do miss macros in Java)&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;At least it is the solution for my small-scale project.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Just copy those few lines in a header file, include it and start writing tests. &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;It is really that easy&lt;/span&gt;. And gone is your excuse for not testing. &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Really, &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;this might be all you need&lt;/span&gt; even for a mid-sized project. &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_6"&gt;Especially&lt;/span&gt; if you are introducing unit testing in an existing project, the jump start can really pay off.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;One important feature of (some) bigger frameworks is that the test runner &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_7"&gt;executes&lt;/span&gt; your test code in a separate address space. This way if your buggy code picks the wrong pointer, it won't bring down the test runner, but only that unit. The runner will report it as a failure and move on. Do that with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;MinUnit&lt;/span&gt; and probably you'll have no clue of what hit you.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Make no excuses, test-your-code.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:Georgia;"&gt;&lt;div style="text-align: justify; "&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;For the records, I modified it a little bit, adding a specialized assert:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div style="text-align: justify; "&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;#define mu_assert_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;eq&lt;/span&gt;(expected, actual) {\&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify; "&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;int a = (expected); \&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify; "&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;int b = (actual); \&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify; "&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;do { if ((a) != (b)) { \&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify; "&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;sprintf&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;minunit&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;msg&lt;/span&gt;, "FAILURE %s:%d expected %d, got %u", __FILE__, __LINE__, a, b);\&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify; "&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;return &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;minunit&lt;/span&gt;_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;msg&lt;/span&gt;; }; \&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify; "&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style=" ;font-size:13px;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;} while(0); }&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;There is a complete example on the &lt;a href="http://www.jera.com/techinfo/jtns/jtn002.html"&gt;project page&lt;/a&gt; or have a look at a real world example: &lt;a href="http://code.google.com/p/codalyze/source/browse/cyz_rgb/trunk/test/test_ring_buffer.h"&gt;test_ring_buffer.h&lt;/a&gt; and &lt;a href="http://code.google.com/p/codalyze/source/browse/cyz_rgb/trunk/test/test.c"&gt;test.c&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Matteo&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/BwSuRlw-Vm4" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/c-testing-minunit-less-is-more</feedburner:origLink></entry>
 
 <entry>
   <title>CYZ_RGB alpha 2 - feature complete</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/p6gcy6g6GOE/cyz_rgb-alpha-2-feature-complete" />
   <updated>2008-09-07T19:03:00+00:00</updated>
   <id>http://caprazzi.net//posts/cyz_rgb-alpha-2-feature-complete</id>
   <content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: courier new;"&gt;The second release of CYZ_RGB, an alternative firmware for &lt;/span&gt;&lt;a style="font-family: courier new;" href="http://thingm.com/products/blinkm"&gt;BlinkM&lt;/a&gt;&lt;span style="font-family: courier new;"&gt;, is now ready for download.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;span style="font-weight: bold;"&gt;The latest release implements all the features of the original firmware.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The program has been slightly tested at a functional level (sitting there and watching the lights go on end off), but has no unit tests.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;I usually write loads of tests, possibly before the actual code; this time I was wandering in a completely new area and I knew most of the code was going to be highly disposable. Now that all hurdles have been surpassed, the refactoring stage will go hand-to-hand with writing a thorough test suite. Wish me good luck.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Go read the &lt;/span&gt;&lt;a style="font-family: courier new;" href="http://code.google.com/p/codalyze/wiki/CyzRgb"&gt;details&lt;/a&gt;&lt;span style="font-family: courier new;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;font-size:100%;" &gt;Goals for next release:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: courier new;font-size:100%;" &gt;Write a comprehensive test suite&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;font-size:100%;" &gt;Decouple cyz_cmd from cyz_rgb&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;font-size:100%;" &gt;Decouple usiTwiSlave from cyz_cmd&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;font-size:100%;" &gt;Reduce binary footprint (now 4072b of 4096 available)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;font-size:100%;" &gt;Add ability to write 2 scripts &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-family: courier new;"&gt;-Matteo&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/p6gcy6g6GOE" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/cyz_rgb-alpha-2-feature-complete</feedburner:origLink></entry>
 
 <entry>
   <title>How (not) to code and new functionalities</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/AFDUEYupXIk/how-not-to-code-and-new-functionalities" />
   <updated>2008-08-15T11:43:00+00:00</updated>
   <id>http://caprazzi.net//posts/how-not-to-code-and-new-functionalities</id>
   <content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;How (not) to write code for a small chip&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;The project has two main set of procedures for color control and commands execution. Loving encapsulation and separation of concerns, I built two &lt;/span&gt;structs&lt;span style="font-family:courier new;"&gt; with function pointers, to &lt;/span&gt;mimic objects:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; &lt;span style="font-style: italic;"&gt;typedef struct CYZ_CMD {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre  style="font-family:courier new;"&gt;&lt;span style="font-style: italic;"&gt; unsigned char rcv_cmd_buf[8];&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt; unsigned char rcv_cmd_buf_cnt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt; unsigned char rcv_cmd_len;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt; Cyz_rgb* cyz_rgb;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt; void (*execute)(void* this, unsigned char* buf);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt; void (*receive_one_byte)(void* this, unsigned char rcv);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;} Cyz_cmd;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family:courier new;"&gt; then allocating an "instance" with malloc, doing some initialization work and finally executing "methods" with&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;&lt;span style="font-family:courier new;"&gt;&lt;span class="oldrm"&gt;&lt;span style="font-style: italic;"&gt;cyz_cmd-&gt;execute(cyz_cmd, play);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="oldrm"  style="font-family:courier new;"&gt;Smart you say?&lt;/span&gt;&lt;span class="oldrm"&gt;&lt;span style="font-family:courier new;"&gt; &lt;span style="font-weight: bold;"&gt;Not at all&lt;/span&gt;. I only ended up &lt;span style="font-weight: bold;"&gt;eating all available memory&lt;/span&gt; (a flattering 256 Bytes).&lt;/span&gt;&lt;/span&gt;&lt;span class="oldrm"&gt;&lt;span style="font-family:courier new;"&gt; I reverted to global variables and functions, dropped all the dynamic memory thing and learnt how not write&lt;/span&gt;&lt;/span&gt;&lt;span class="oldrm"&gt;&lt;span style="font-family:courier new;"&gt; code for an embedded system. True, neat and clean code is more maintainable, but I was&lt;/span&gt;&lt;/span&gt;&lt;span class="oldrm"&gt;&lt;span style="font-family:courier new;"&gt; spending precious memory to buy only an apparent advantage.&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;b class="oldrm"&gt; &lt;/b&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="oldrm"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:courier new;"&gt;Adding new commands and functionalities&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span class="oldrm"&gt;&lt;span style="font-family:courier new;"&gt; will further reduce available memory: I'll probably &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span class="oldrm"&gt;&lt;span style="font-family:courier new;"&gt;learn some neat tricks. Can't wait...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span class="oldrm"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;font-size:130%;"  &gt;Added some commands (only in svn head)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;font-size:130%;"  &gt;'W' Write script line&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Script 0 can be modified and up to &lt;/span&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;10&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; lines added and executed. With some limitations:&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;ol style="font-family: courier new; text-align: justify;"&gt;&lt;li&gt;line duration is ignored&lt;/li&gt;&lt;li&gt;script lines only support fade to rgb and go to rgb&lt;/li&gt;&lt;li&gt;script is not persisted and will disappear at next power off&lt;/li&gt;&lt;li&gt;script number is ignored, can only write script 0 (as in original blinkm)&lt;/li&gt;&lt;li&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-weight: bold;font-family:courier new;font-size:130%;"  &gt;'p' Play script&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;After writing a script with 'W', it can be xecuted with 'p'. Only applies to script 0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;font-size:130%;"  &gt;'o' Stop script&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;No limitations here :)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a style="font-family: courier new;" href="http://code.google.com/p/codalyze/wiki/CyzRgb"&gt;See&lt;/a&gt;&lt;span style="font-family:courier new;"&gt; the project page for details.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Matteo&lt;/span&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/AFDUEYupXIk" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/how-not-to-code-and-new-functionalities</feedburner:origLink></entry>
 
 <entry>
   <title>CYZ_RGB alpha - blinkm alternative firmware</title>
   <link href="http://feedproxy.google.com/~r/MatteoCaprari/~3/fPAZm7y74xA/cyz_rgb-alpha-blinkm-alternative-firmware" />
   <updated>2008-08-11T20:33:00+00:00</updated>
   <id>http://caprazzi.net//posts/cyz_rgb-alpha-blinkm-alternative-firmware</id>
   <content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family:courier new;"&gt;The first release of CYZ_RGB, an alternative firmware for &lt;/span&gt;&lt;a style="font-family: courier new;" href="http://thingm.com/products/blinkm"&gt;BlinkM&lt;/a&gt;&lt;span style="font-family:courier new;"&gt;, is now ready for download.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Go read the &lt;/span&gt;&lt;a style="font-family: courier new;" href="http://code.google.com/p/codalyze/wiki/CyzRgb"&gt;details&lt;/a&gt;&lt;span style="font-family:courier new;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;BlinkM is a Smart LED produced by &lt;/span&gt;&lt;a style="font-family: courier new;" href="http://thingm.com/"&gt;ThingM&lt;/a&gt;&lt;span style="font-family:courier new;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;BlinkM is a “Smart LED”, a networkable and&lt;br /&gt;programmable full-color RGB LED for hobbyists,&lt;br /&gt;industrial designers, prototypers, and experimenters.&lt;/blockquote&gt;&lt;/div&gt;&lt;div style="font-family: courier new; text-align: justify;"&gt;Just connect it to an I2C bus and start sending commands like "show rgb color" or "fade to hsv value" and so on and so forth (it does much more; see the human-readable &lt;a href="http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf"&gt;data sheet&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;A bit of explanation: I liked the idea to do a few more things with the leds and decided to modify the firmware. The original firmware is actually closed source (due to legal issues) so I had to start  writing a new one from scratch. This first release is very basic but hopefully adding new features won't be that hard.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The new firmware has two interesting &lt;span style="font-weight: bold;"&gt;additional features&lt;/span&gt; in the works: the ability to &lt;span style="font-weight: bold;"&gt;act as a master on the I2C bus&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;support for dallas 1-wire protocol&lt;/span&gt;, to leave one pin free for your creativity.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Download&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you decide to download and give it a try, you'll find slave.hex and master.hex: the first is the actual blinkm firmware replacement, the other is the experimental master. You can flash the files on two different blinkms, connect them the to the same i2c bus and watch they change color together.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/codalyze/source/browse/#svn/trunk/blinkm-simulator/src/main/c/blinkm/BootCampProject"&gt;Browse&lt;/a&gt; the source code.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://codalyze.googlecode.com/files/cyz_rgb-alpha1-2008_08_11-binary.zip"&gt;Download&lt;/a&gt; the binary release.&lt;br /&gt;&lt;br /&gt;Get the sources with svn: svn checkout http://codalyze.googlecode.com/svn/cyz_rgb/trunk cyz_rgb&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Interested? I need help.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'd like to hear from you. If you have any patch to submit it will be welcome.&lt;br /&gt;&lt;span class="newadd"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="newadd"&gt;&lt;span style="font-style: italic;"&gt;Please not that &lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;" class="neweq"&gt;my experience in C is very limited. And i&lt;/span&gt;&lt;span style="font-style: italic;" class="newadd"&gt;t approache&lt;/span&gt;&lt;span style="font-style: italic;"&gt;s zero when it comes&lt;/span&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;&lt;span style="font-style: italic;"&gt;to microcontroller programming. So, if you are any good at it,&lt;/span&gt;&lt;span style="font-style: italic;" class="newadd"&gt; please be patient and &lt;/span&gt;&lt;span style="font-style: italic;"&gt;expect the worse... i'm a java programmer ;).&lt;/span&gt;&lt;span style="font-style: italic;font-size:130%;" &gt;&lt;span class="newadd"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-size:100%;" &gt;&lt;span class="newadd"&gt;When&lt;/span&gt;&lt;span class="neweq"&gt; you stop feeling sick after reading the code, well, drop&lt;/span&gt;&lt;span class="newadd"&gt; me&lt;/span&gt;&lt;span class="neweq"&gt; a line&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Matteo&lt;br /&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/MatteoCaprari/~4/fPAZm7y74xA" height="1" width="1"/&gt;</content>
 <feedburner:origLink>http://caprazzi.net/posts/cyz_rgb-alpha-blinkm-alternative-firmware</feedburner:origLink></entry>
 
 
</feed>
