<?xml version="1.0" encoding="iso-8859-1"?>



<rdf:RDF
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  xmlns:admin="http://webns.net/mvcb/"
  xmlns:cc="http://web.resource.org/cc/"
  xmlns="http://purl.org/rss/1.0/">

<channel rdf:about="http://blogs.codehaus.org/people/rinkrank/">
<title>Aslak Hellesoy&apos;s uncommon sense</title>
<link>http://blogs.codehaus.org/people/rinkrank/</link>
<description></description>
<dc:language>en-us</dc:language>
<dc:creator></dc:creator>
<dc:date>2005-10-31T05:25:20+00:00</dc:date>
<admin:generatorAgent rdf:resource="http://www.movabletype.org/?v=2.661" />


<items>
<rdf:Seq><rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/001211_my_blog_has_moved.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/001136_release_files_on_rubyforge_and_sourceforge_with_the_xforge_library.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/001001_object_templates_in_ruby.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000995_ajax_with_javascript_templates.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000994_annotations_in_ruby.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000971_what_every_java_programmer_should_know_about_ruby.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000948_starteam_awards.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000922_books_i_have_not_written.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000860_i_hate_lotus_notes.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000844_poor_test_coverage_send_your_code_to_guantanamo.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000827_lovely_commit_messages.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000785_leaving_london_drinks.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000754_the_story_of_the_picocontainer.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000715_ejb3_red_herrings.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000676_damagecontrol_and_its_graphs.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000587_my_tracks_at_theserverside_symposium_2004.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000576_re_pico_container_ideas_are_not_new.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000565_static_or_dynamic_mock_a_brief_comparison.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000555_injection_dependency.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000551_oh_no_were_testing_the_mock.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000533_re_enough_with_the_test_driven_development_hype.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000150_qdox_attributes.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000149_ideamock.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000136_picocontainer_logo_contest.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000096_picocontainer_10alpha2_is_released.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000093_i_moved_to_codehaus.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000091_new_job.html" />
<rdf:li rdf:resource="http://blogs.codehaus.org/people/rinkrank/archives/000090_simian_refactoring_detector.html" />
</rdf:Seq>
</items>

</channel>

<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/001211_my_blog_has_moved.html">
<title>My blog has moved</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/001211_my_blog_has_moved.html</link>
<description><![CDATA[<p>It now lives at <a href="http://aslakhellesoy.com">http://aslakhellesoy.com</a></p>

<p>And I'll start blogging again. Promise.</p>]]></description>
<dc:subject></dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2005-10-31T05:25:20+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/001136_release_files_on_rubyforge_and_sourceforge_with_the_xforge_library.html">
<title>Release files on RubyForge and SourceForge with the XForge library</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/001136_release_files_on_rubyforge_and_sourceforge_with_the_xforge_library.html</link>
<description><![CDATA[<p>If you have ever hosted a project on RubyForge, SourceForge or some other clone such as GForge, you have probably experienced the pain of making a release on these systems.</p>

<p>This is because these systems only offer an ugly form based interface for releases. No web services, no scp. Just these bloody forms. -And most people interact with them manually, uploading files, pasting in release notes and so forth. There are probably some odd, unknown, project-specific scripts lying around in random places that can automate this, but I haven't seen anything reusable.</p>

<p>In fact, I hadn't seen anything at all, so 4 months ago I wrote <a href="http://svn.damagecontrol.codehaus.org/trunk/rscm/lib/rubyforge_file_publisher.rb">my own</a> script to do this. Except I couldn't get the HTTP multipart posts (attachments) to work properly. So I left it fermenting for a while...</p>

<p>But two days ago I felt the pain again, and I came across <a href="http://www.loudthinking.com">DHH</a>'s <a href="http://dev.rubyonrails.com/file/trunk/railties/Rakefile">Rake script</a> which does something very similar. -And it had the multipart code I couldn't grok myself.</p>

<p>So I decided to take the best parts of my old attempt and DHH's code from Rails' Rake script and make a proper library, so that others can use it. -Not only on RubyForge, but hopefully also on SourceForge and other sites running SourceForge clones.</p>

<p>So if you're as lazy as me, check out <a href="http://xforge.rubyforge.org/">XForge</a>.</p>

<p>XForge is released using XForge (of course!), so it works fine on RubyForge. Please let me know if you get it to work anywhere else, or if you have bugs or improvements.<br />
</p>]]></description>
<dc:subject>Ruby</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2005-07-18T18:52:58+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/001001_object_templates_in_ruby.html">
<title>Object templates in Ruby</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/001001_object_templates_in_ruby.html</link>
<description><![CDATA[<p>
The concept of templates are very common in many contexts of programming. A boiler-plate representation of something can be turned into a concrete instance by supplying some extra data. The important point is that the supplied data can vary, and that has an impact on the structure of the concrete instance of the template.
</p>
<p>
In HTML programming, common template techniques are JSP, PHP, ERB and ASP. By passing some extra data to a template engine, a template can be turned into an HTML page that displays the data, using the layout from the template.
</p>
<p>
In OO programming, the most common concept of a template is a Class. A piece of a program can supply some data to a class' constructor and get a new object.
</p>
<p>
Sometimes, instantiating a new object by simply calling a constructor with some extra data is not the optimal way to create an object though. Consider the common situation where the desired object is composed of an aggregation of several other objects. -A complex graph of objects.
</p>
<p>
One way to approach this is to design classes (aka templates) to honour Dependency Injection (DI), and use a DI container supporting a configuration file (in XML or other format). NanoContainer or Spring are two frameworks that use this approach to instantiate complex graphs of objects composed of "variable data" from a configuration file.
</p>
<p>
Assuming you want the ability to create object graphs that are configured in an external file, and your language is Java, then it doesn't get much simpler than with NanoContainer or Spring.
</p>
<p>
But in Ruby...
</p>
<p>
A similar effect that is radically simpler and extremely easy to use can be achieved with a dash of Ruby magic using YAML and eval under the covers. Consider this <b>object</b> template:
</p>

<div class="code"><pre>codehaus_project_template = Project.new
codehaus_project_template.home_page = "<span class="quote">http://\#{unix_name}.codehaus.org</span>"

jabber_publisher = JabberPublisher.new
jabber_publisher.id_resource = "<span class="quote">damagecontrol@jabber.codehaus.org/#{unix_name}</span>"

codehaus_project_template.publishers &lt;&lt; jabber_publisher</pre></div>

(The template object can also be deserialised from a YAML file if we don't wish to do this in Ruby code, but this is not important from the perspective of describing how this object template technique works).

The point I'm getting at is that I can create new instances from this template object like this:
<div class="code"><pre>project = codehaus_project_template.dupe("<span class="quote">unix_name</span>" =&gt; "<span class="quote">mooky</span>")      
assert_equal("<span class="quote">http://mooky.codehaus.org</span>", project.home_page);
assert_equal("<span class="quote">damagecontrol@jabber.codehaus.org/mooky</span>", project.publishers[0].id_resource);</pre></div>


The dupe method takes a Hash that should have one key/value pair for each variable in the object template. The dupe method simply creates a new object graph similar to the one in the template, but substitutes all variables with the values from the hash. -All the way out to the leaves of the object graph!

The object template's variables are simply backslash-escaped #{blah} s in various String instance variable values (fields). In the example there is only one (#{unix_name}), but we could use as many as we like, at any level in our object graph.

In Ruby it's ridiculously easy to make this happen. Just make the classes whose instances you want to use as templates include ObjectTemplate:

<div class="code"><pre>module ObjectTemplate
  def dupe(variables)
    template_yaml = YAML::dump(self)
    b = binding
    variables.each { |key, value| eval "<span class="quote">#{key} = variables[\</span>"#{key}\"<span class="quote">]</span>", b }
    new_yaml = eval(template_yaml.dump.gsub(/\\#/, "<span class="quote">#</span>"), b)
    YAML::load(new_yaml)
  end
end</pre></div>


A similar approach can be achieved in Java with XStream and Velocity (or Jelly, haha) and maybe a little bit of AOP - in 10 times or more as many lines of code - without the same ease of use.
]]></description>
<dc:subject>Ruby</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2005-03-09T05:28:18+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000995_ajax_with_javascript_templates.html">
<title>Ajax with JavaScript Templates</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000995_ajax_with_javascript_templates.html</link>
<description><![CDATA[<p>Rich, responsive webapps using the <a href="http://www.adaptivepath.com/publications/essays/archives/000385.php">Ajax</a> approach are chic. I've started to think about what it would be like to develop the view part of a webapp using the Ajax concepts.</p>

<p>In an Ajax web app the server sends back XML, and the XML is transformed to HTML in the browser. There are several ways to do this transformation:</p>

<p>One approach is to use <a href="http://www.xulplanet.com/references/objref/XSLTProcessor.html">XSLTProcessor</a> as described <a href="http://blogs.msdn.com/adioltean/archive/2005/02/09/370067.aspx">here</a>.</p>

<p>However, XSLT is problematic for a couple of reasons. First, not all browsers support it, and more importantly, most web ui designers don't speak XSL.</p>

<p>A second approach is to use XPath in JavaScript to pull out bits of pieces of the XML and modify small pieces of the DOM to fill them in.</p>

<p>A third (and new?) approach could be to use the familiar template approach (as in JSP, ASP, ERB, PHP templates) and generate bigger chunks of DHTML. This would make it much easier to develop nice looking views, since they can now be designed in a regular web authoring tool such as DreamWeaver or <a href="http://www.nvu.com/">NVU</a>.</p>

<p>But wait - the template engine now has to sit inside the browser! And this is where I discovered <a href="http://trimpath.com/blog/index.php?p=3">JavaScript Templates</a>.</p>

<p>JST templates could theoretically be rendered (and tested) in a build system, using <a href="http://www.mozilla.org/rhino/">Rhino</a>. Being able to test view rendering is something I consider very important, especially when systems start to get complex (which they do with Ajax).</p>

<p>I'm eager to try this out.</p>]]></description>
<dc:subject>Web</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2005-02-26T19:54:50+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000994_annotations_in_ruby.html">
<title>Annotations in Ruby</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000994_annotations_in_ruby.html</link>
<description><![CDATA[<p>A couple of days ago I wished there was a way to use annotations in Ruby. I'm writing a Ruby on Rails application that renders a lot of objects in HTML. Many of these objects are "editable" via the web interface, and in order to make it easier for the user, I wanted the web interface to have both an explanatory text and a HTML tooltip for each object's field.
</p>
<p>
Because I like simple things I also like to keep things in one place (I don't want to maintain this metadata in a separate RHTML template).
</p>
<p>
Ruby doesn't support annotations out of the box, so I opened up the Class class and added support for annotations. Now I can do:
</p>
<p>
<div class="code"><pre>require 'rscm/annotations'

  <span class="category1">class</span> EmailSender
    ann :description =&gt; "<span class="quote">IP address of the mail server</span>", :tip =&gt; "<span class="quote">Use 'localhost' if you have a good box, sister!</span>"
    attr_accessor :server
  end</pre></div>

<p>
The class' annotations can then be accessed like this:
<p>
<div class="code"><pre>  EmailSender.server[:description] # =&gt; "<span class="quote">IP address of the mail server</span>"</pre></div>

<p>
It took the Java community forever to do stuff like this. First a couple of years of XDoclet, then JSR175. And tons of code too. In Ruby it's 1 hour's work and 25 lines of code. Go figure.
</p>
<p>
For more info see http://rscm.rubyforge.org/classes/Class.html
</p>
<p>
And oh, here's the code:
<div class="code"><pre><span class="category1">class</span> <span class="category2">Class</span>
  def ann(anns)
    @@anns ||= {}
    def self.method_missing(sym, *args) #:nodoc:
      @@anns[sym]
    end
    $attr_anns ||= {}
    $attr_anns.merge!(anns)
  end

  alias old_attr_reader attr_reader #:nodoc:
  def attr_reader(*syms) #:nodoc:
    syms.each <span class="category1">do</span> |sym|
      @@anns[sym] = $attr_anns
    end
    $attr_anns = nil
    old_attr_reader(*syms)
  end

  def attr_accessor(*syms) #:nodoc:
    attr_reader(*syms)
    attr_writer(*syms)
  end
end</pre></div>


UPDATE (March 3 2005) An updated version of the Ruby annotations library is available at <a href="http://rafb.net/paste/results/ElOUmg50.html">rafb</a>]]></description>
<dc:subject>Ruby</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2005-02-25T06:05:51+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000971_what_every_java_programmer_should_know_about_ruby.html">
<title>What Every Java Programmer Should Know About Ruby</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000971_what_every_java_programmer_should_know_about_ruby.html</link>
<description><![CDATA[<p>Jim Weirich has written up an <a href="http://jimweirich.tadalist.com/lists/public/14055">excellent compilation</a> of what Javaheads should know about Ruby. I wish he had written up 2 years ago when I started to play with Ruby.</p>

<p>Java has been my language of choice for many years. Learning Ruby has opened up my eyes about what OO, agile development and extreme productivity should be like.</p>

<p>I'm not "converting" from Ruby to Java - I always try to use the best tool for the job at hand. Sometimes it's Java, sometimes it's .NET, sometimes it's Excel or PHP. More often than anything else it's not even about programming. But when it is, Ruby turns out to be the best choice for me more often than any other language. Probably because I'm an XP head. (And because I still don't know Objective-C or Smalltalk - it's on this year's TODO list).</p>

<p>Ruby - because I can get the job done fast and end up with super readable and maintainable code. And I'm worth it.</p>

<p>Now if those big corps that I tend to consult for would dare to do more things in Ruby... I reckon it will take a few years before we see them changing.</p>]]></description>
<dc:subject>Java</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2005-02-02T02:08:47+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000948_starteam_awards.html">
<title>StarTeam awards</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000948_starteam_awards.html</link>
<description><![CDATA[<p>Borland has a page about all the awards their <b>outstanding</b> SCM system has won: <a href="http://www.borland.com/starteam/awards/index.html">http://www.borland.com/starteam/awards/index.html</a>.</p>

<p>I must say I think that's exactly what StarTeam deserves. Who knows, maybe they'll even pull a <a href="http://www.darwinawards.com/">Darwin Award</a> one day?</p>]]></description>
<dc:subject>Nonsense</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2005-01-07T20:55:59+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000922_books_i_have_not_written.html">
<title>Books I have not written</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000922_books_i_have_not_written.html</link>
<description><![CDATA[<p>For some reason that is beyond me I have supposedly written 2 books:</p>

<p><a href="http://www.isbn.nu/aisbn/hellesoy%20aslak">Excel 2003 VBA Programmer's Reference</a></p>

<p><a href="http://www.lowth.com/alist/author/-/Aslak%20Hellesoy/1"> Professional Xdoclet 2.0</a></p>

<p>It is true that Ara Abrahamian, Erik Hatcher and I were thinking about writing a book about XDoclet a couple of years ago, but it never happened. But claiming that I have written a book about Excel VBA is just plain hilarious. (The <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0764556606/qid=1102932197/sr=8-1/ref=sr_8_xs_ap_i1_xgl14/002-4229440-8512826?v=glance&s=books&n=507846">Amazon</a> page for this VBA book doesn't have this incorrect information).</p>

<p>Hmm wait a minute, can I claim royalties for this?</p>]]></description>
<dc:subject>Nonsense</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-12-13T10:12:43+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000860_i_hate_lotus_notes.html">
<title>I HATE Lotus Notes</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000860_i_hate_lotus_notes.html</link>
<description><![CDATA[<p>Today, all my email but a random 4 ones mysteriously disappeared from my Lotus Notes inbox. (No, the cat didn't eat it).</p>

<p><img alt="notes.PNG" src="http://blogs.codehaus.org/people/rinkrank/archives/notes.PNG" width="584" height="272" border="0" /></p>

<p>If you hate notes like me (no, i said HATE), feel free to let it all out right here, right now. In your own language if it makes you feel better. Like <a href="http://www.humorkanari.com/art.aspx?artID=1312">this</a>.</p>]]></description>
<dc:subject>Nonsense</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-10-13T21:59:54+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000844_poor_test_coverage_send_your_code_to_guantanamo.html">
<title>Poor test coverage? Send your code to Guantanamo!</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000844_poor_test_coverage_send_your_code_to_guantanamo.html</link>
<description><![CDATA[<p>Last year, right after joining <a href="http://www.thoughtworks.com/">ThoughtWorks</a>, my colleague <a href="http://www.skizz.biz/">Chris Stevenson</a> bounced off an idea to me during a <a href="http://geeknight.thoughtworks.com/index.php/GeekNightLondon">Geek Night</a>:</p>

<p>"How about a tool that deletes all code that isn't tested?". </p>

<p>I am still not sure whether Chris was entirely serious or not, but it was an intriguing idea that I have been thinking about quite often since then.</p>

<p>Now, the idea has been materialised in a new little tool in the <a href="http://docs.codehaus.org/display/ASH/Extreme+XP+Tools">Extreme XP Tools</a> family: <a href="http://docs.codehaus.org/display/ASH/Guantanamo">Guantanamo</a>!</p>

<p>Guantanamo is eating its own dog food, and as a result, it has 100% coverage. I still haven't tried to run it over any other codebases, so it remains to see whether it is useful or not. -And whether it is something anyone would actually want to use.</p>

<p>I'll give it a try at work :-)</p>]]></description>
<dc:subject>Java</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-10-02T08:46:13+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000827_lovely_commit_messages.html">
<title>lovely commit messages</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000827_lovely_commit_messages.html</link>
<description><![CDATA[<p><a href="http://builds.codehaus.org/public/project?project_name=SiteMesh&timestamp=20040831134957">first post!</a></p>]]></description>
<dc:subject>Nonsense</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-09-02T06:44:46+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000785_leaving_london_drinks.html">
<title>Leaving London Drinks</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000785_leaving_london_drinks.html</link>
<description><![CDATA[<p>I'm off to Chicago for 6 months, and I'll have my leaving drinks at <a href="http://www.london-drinking.com/110.htm">Na Zdrowie</a> Thursday 15 July from 8pm.</p>]]></description>
<dc:subject>Nonsense</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-07-13T09:53:53+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000754_the_story_of_the_picocontainer.html">
<title>The story of the PicoContainer</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000754_the_story_of_the_picocontainer.html</link>
<description><![CDATA[<img src="http://www.picocontainer.org/pico-logo.png"/>
<p>
After a longish session pairing with <a href="http://paulhammant.com/blog/">Paul</a> we finally <a href="http://blogs.codehaus.org/archives/000753_picocontainer_10_final_has_been_released.html">released </a> <a href="http://www.picocontainer.org/">PicoContainer</a> 1.0 today.
</p>
<p>
This has been a great journey so far. Paul and I started it right after I moved to London to start working for ThoughtWorks. It all started when I asked Paul one night whether he had heard of Inversion of Control. He got this weird expression on his face when I asked, and I couldn't quite figure out whether he was excited or depressed.
</p>
<p>
<i>"It's my favourite pattern dood."</i> (Dood pronounced in his native British)
</p>
<p>
So he got all excited and told me everything about IoC (I didn't have that much of a clue), and about Avalon - a project Paul had been with for a while, but was drifting away from.
</p>
<p>
My initial reaction (a couple of hours later when Paul didn't have any more breath) was:
</p>
<p>
<i>"Why does it have to be that complicated?"</i>
</p>
<p>
We quickly decided to do a spike on a simple piece of code that could do IoC style dependency management via constructors rather than via setters and ugly container lookups from within the components. 

It's kind of blurry to me how we decided to go for constructors, as we were both drunk when we started TDDing the first lines. I think it was some kind of eureka moment where Paul was thinking about a comment made by Rachel Davies while she was reviewing our colleague Joe Walnes et al's Java Open Source Programming, and I was just being new to this and thought about simplicity. The way I remeber it we unisonely burst out:
</p>
<p>
<div style="text-align: center;">
<img src="http://fotap.org/gallery/2003/october/hausparty/.cache/320x240-IMG_0052.jpg"/>
<br/>
<b><i>"Let's do it with constructors!"</i> (Me left, Paul right)</b>
</div>
</p>
<p>
This was also my first real journey into TDD land. I had known about TDD for a couple of years, but hadn't yet had that epiphany where it fundamentally changed the way I think about code - and religiously follow the practice. I think the first test looked something like this:
</p>
<div class="code"><pre><span class="category1">public</span> <span class="category1">class</span> ContainerTestCase <span class="category1">extends</span> junit.framework.TestCase {
     <span class="category1">public</span> <span class="category1">static</span> <span class="category1">class</span> Fred {
          <span class="category1">private</span> <span class="category1">final</span> Wilma wilma;
  
          <span class="category1">public</span> Fred(Wilma wilma) {
               this.wilma = wilma;
           }
  
          <span class="category1">public</span> Wilma getWilma() {
               <span class="category1">return</span> wilma;
           }
      }
 
     <span class="category1">public</span> <span class="category1">static</span> <span class="category1">class</span> Wilma {}
     
     <span class="category1">public</span> <span class="category1">void</span> testShouldInstantiateClassesAndPassDependencies() {
          <span class="category2">Container</span> container = <span class="category1">new</span> <span class="category2">Container</span>();
          container.registerComponent(Wilma.class);
          container.registerComponent(Fred.class);
          Fred fred = (Fred) container.getComponent(Fred.class);
          assertNotNull(fred.getWilma());
      }
}</pre></div>

<p>
This was our first requirement - a container that can instantiate classes and understand what arguments to pass to the constructors. We alternated the keyboard rapidly and made the test pass. This involved some simple reflection logic and was implemented in a couple of classes.
</p>
<p>
The following days we added more features. Occasionally I would happily try to implement code without writing the test (requirement) first. It always resulted in a slap from Paul and a
</p>
<p>
<i>"You're doing up-front design again. How do you know whether that is needed or even if it's going to work?"</i>
</p>
<p>
So I gradually got the hang of TDD, thanks to Paul. (A couple of months later I was greatful for that. I was ruthelessly refactoring the entire codebase to improve the design. That would have been absolutely impossible without the extensive test suite we had built up by then.)
</p>
<p>
This was back in the days when Codehaus was a small place only hosting a handful of projects. About a week after we started Bob was kind enough to lend us a space for our new little baby, and that's when we named it PicoContainer.
</p>
<p>
PicoContainer quickly got <a href="http://blogs.codehaus.org/people/jutopia/">Jon Tirsén</a>'s attention (who I didn't know back then - he has later become a good friend and also a colleague). Jon quickly joined the project and has since been an important contributor. Much of the nice modular design we have today is owed to him. Several other people (<a href="http://joe.truemesh.com/blog/">Joe Walnes</a>, <a href="http://www.skizz.biz/">Chris Stevenson</a> and <a href="http://www.softwarecraftsmen.com/">Mike Hogan</a> to name a few) also helped us in the early days, and Rickard Öberg <a href="http://jroller.com/page/rickard/20030626">blogged</a> about it. PicoContainer was now a well-established project. This was late June 2003.
</p>
<p>
Half a year later my colleague <a href="http://www.martinfowler.com/">Martin Fowler</a> wrote an <a href="http://www.martinfowler.com/articles/injection.html">article</a> about the concepts behind IoC and PicoContainer, and this is how the term "Dependency Injection" was introduced. (Martin initially coined it "Service Injection", but <a href="http://www.springframework.org/">Rod Johnson</a> refined the term during a Geek Night in the ThoughtWorks offices in London).
</p>
<p>
Lately we have invited some carefully selected contributors, and we will hopefully invite more in the future.
</p>
<p>
PicoContainer now has pretty good documentation, we have fixed some <a href="http://jira.codehaus.org/secure/BrowseProject.jspa?id=10120&report=changelog">180</a> feature requests and bugs. It's simple to use, and the jar is no more than 50kb with no external dependencies.

There is a .NET and a Ruby port, and more in the pipe. NanoContainer is also an interesting sister project that adds scripted configuration using a multitude of script languages, as well as integration with WebWork, Hibernate and much more. (It's not that well documented yet, but we'll get there). 
</p>
<p>
The best part of this story isn't PicoContainer itself. It is how many people have learned about dependency injection as a way to decouple their code (both internally and from the container itself) and make it testable and mockable. At the end of the day that will bring us code that is easier to maintain. It's your code that counts, and you should be able to choose what container you want to deploy it in - if you need a container at all!
</p>]]></description>
<dc:subject>Java</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-06-06T03:12:59+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000715_ejb3_red_herrings.html">
<title>EJB3 red herrings</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000715_ejb3_red_herrings.html</link>
<description><![CDATA[<p>At TSSS, the EJB3 spec lead Linda de Michiel presented what EJB3 is going to look like. I'm sure you have read all the fuss about it already.</p>

<p>The nice thing about EJB3 is that the spec committee is trying to address the limitations of the EJB2 component model. The EJB3 component model is based on the following concepts and goals:</p>

<p>1) POJOs/POJIs (plain old java objects/interfaces - nothing to extend)<br />
2) Dependency Injection (setter flavour)<br />
3) Testability outside the container<br />
4) Annotations<br />
5) CMP becomes Hibernate</p>

<p>Linda mentioned 24 times during her presentation that Gavin and Hibernate had been an important source of inspiration for the EJB3 persistence model (it's true, Marcf was counting and nearly creamed his pants). That's great though. Gavin and Hibernate rock.</p>

<p>Those of you who are a little bit uptodate in Java OSS land may have recognised that the 3 first points have been popularised by three lightweight containers, namely Spring, Hivemind and PicoContainer.</p>

<p>Linda was talking about as much about POJO/DI/Testability as she was about persistence, so when she didn't mention once where the rest of the spec (the non-persistence related stuff) was inspired from, it struck me as rather strange.</p>

<p>Here are my speculations about why:</p>

<p>a) The EJB3 spec committee have invented these concepts independently and have not been inspired by the current lightweight containers.<br />
b) Other projects only get mentioned if one of its contributors are on the spec committee.<br />
c) The EJB3 spec committee is trying to hide the fact that they were inspired from other projects and sell it as their own invention.</p>

<p>Cedric utters his <a href="http://beust.com/weblog/archives/000124.html">enthusiasm</a> about the new spec. And expresses how <a href="http://beust.com/weblog/archives/000126.html">sick</a> he is of lightweight containers.</p>

<p>Well done folks!</p>]]></description>
<dc:subject></dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-05-13T01:51:36+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000676_damagecontrol_and_its_graphs.html">
<title>DamageControl and its graphs</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000676_damagecontrol_and_its_graphs.html</link>
<description><![CDATA[<p>The most important benefit from Continuous Integration tools is instant notification of build failures.</p>

<p>DamageControl supports this of course, but it also supports some interesting historic reports. You can see an example here:</p>

<p><a href="http://docs.codehaus.org/display/PICO/Statistics">DamageControl stats for PicoContainer</a></p>

<p>This kind of information will tell you wether your build process is heading in the right direction (build times going up or down). Seeing this will make it harder to ignore problems related to build time. -And hopefully encourage the development team to do something about it before it becomes too big a hassle.</p>

<p>Other similar historic reports that I'm planning to write are<br />
o JIRA activity<br />
o Download activity<br />
o Mailing list activity</p>

<p>Especially a historical JIRA activity graph can be used to determine the responsiveness of a project:</p>

<p>o Bug lifetime distribution<br />
o Open bug counts</p>

<p>Combine all these graphs in a single page, and you get a pretty good picture of the health and activity of a project, both historically and currently.</p>]]></description>
<dc:subject>Methodology</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-04-12T01:51:17+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000587_my_tracks_at_theserverside_symposium_2004.html">
<title>My tracks at TheServerSide Symposium 2004</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000587_my_tracks_at_theserverside_symposium_2004.html</link>
<description><![CDATA[<p>Last week was good. I was <a href="http://www.jroller.com/page/fate/20040130">biled</a> as a top asshat and invited to speak at <a href="http://www.theserverside.com/symposium/agenda.html">TheServerSide Symposium</a>.</p>]]></description>
<dc:subject>Nonsense</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-02-04T12:56:40+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000576_re_pico_container_ideas_are_not_new.html">
<title>RE: Pico Container ideas are not new</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000576_re_pico_container_ideas_are_not_new.html</link>
<description><![CDATA[<p><a href="http://osi.yellis.net/web/html/modules.php?op=modload&name=News&file=article&sid=8">patrah</a> says: "Pico Container ideas are not new."</p>

<p>Unfortunately, (s)he doesnt't mention *what* of the ideas are not new. (There is just "the idea"). The only thing that the authors of PicoContainer might have claimed as newness is to have a *framework* that supports constructor based dependency injection.</p>

<p>As far as I can tell, there is no prior art to that. And for the IoC stuff: We never claimed it to be our invention (there are heaps of pre-pico IoC frameworks of course); We just came up with an framework that makes DI (which is just a part of the broader pattern/principle/technique referred to as IoC) simpler than previous DI oriented frameworks/techniques.</p>

<p>Please be more specific about what isn't new (because there is more to PicoContainer than just C-DI) and blog it where people can leave comments. Oh well, leave'em here then.</p>]]></description>
<dc:subject>Methodology</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-01-25T03:09:15+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000565_static_or_dynamic_mock_a_brief_comparison.html">
<title>Static or Dynamic Mock: A brief comparison.</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000565_static_or_dynamic_mock_a_brief_comparison.html</link>
<description><![CDATA[<a href="http://crazybob.org/roller/page/crazybob/20040120">Crazybob is Mocking</a>.

It struck me that his tests could have been even shorter and IMO more readable had he used a mock library based on dynamic proxies (like <a href="http://www.jmock.org/">JMock</a>).


The static way (Bob's example with minor corrections):

<div class="code"><pre>    <span class="linecomment">// Lines of code in the body: 10</span>
    <span class="linecomment">// Number of characters in the body (minus leading indentation whitespace): 274</span>
    <span class="linecomment">// (Not counting the MockServletConfig baseclass, which also has to be coded).</span>
    <span class="category1">public</span> <span class="category1">void</span> testGetInitParameterWithStaticcMock() {
         <span class="category1">final</span> <span class="category2">String</span> expectedName = "<span class="quote">foo</span>";
         <span class="category1">final</span> <span class="category1">boolean</span>[] called = <span class="category1">new</span> <span class="category1">boolean</span>[1];
         <span class="category1">new</span> MyServlet().init(<span class="category1">new</span> MockServletConfig() {
              <span class="category1">public</span> <span class="category2">String</span> getInitParameter(<span class="category2">String</span> name) {
                   called[0] = <span class="category1">true</span>;
                   assertEquals(expectedName, name);
                   <span class="category1">return</span> <span class="category1">null</span>;
               }
          });
         assertTrue(called[0]);
     }</pre></div>



The dynamic way:

<div class="code"><pre>    <span class="linecomment">// Lines of code in the body: 4</span>
    <span class="linecomment">// Number of characters in the body (minus leading indentation whitespace): 235</span>
    <span class="category1">public</span> <span class="category1">void</span> testGetInitParameterWithDynamicMock() {
         Mock mockServletConfig = <span class="category1">new</span> Mock(ServletConfig.class);
         mockServletConfig.expectAndReturn("<span class="quote">getInitParameter</span>", C.args(C.eq("<span class="quote">foo</span>")), <span class="category1">null</span>);
         <span class="category1">new</span> MyServlet().init((ServletConfig) mockServletConfig.proxy());
         mockServletConfig.verify();
     }</pre></div>



(Some of you might argue that size isn't everything - I disagree of course - but if you have opinions about other drawbacks/benefits of each approach, let's hear it!)]]></description>
<dc:subject>Java</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-01-21T01:49:27+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000555_injection_dependency.html">
<title>Injection Dependency</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000555_injection_dependency.html</link>
<description><![CDATA[<p>Jon: Carlos Villela tells me that Dependency means "Addiction" in Portuguese.<br />
Aslak: Perhaps Fowler's <a href="http://www.martinfowler.com/articles/injection.html">new pattern name</a> is a bit unfortunate then. Haha.<br />
Jon: Nah. Pass me the needle.</p>]]></description>
<dc:subject>Nonsense</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-01-14T23:22:15+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000551_oh_no_were_testing_the_mock.html">
<title>Oh no, we&apos;re testing the Mock!</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000551_oh_no_were_testing_the_mock.html</link>
<description><![CDATA[<p>

Recently I have been working on a team where a misunderstood mocking practice is common. (It's really an antipattern). Before I delve into the details, let me recap some simple mock essentials.
</p>
<p>
A mock is an object that acts as a "dummy" placeholder for a "real" object. Its class is generally an implementation of an interface or a subclass of some class, either generated dynamically or statically coded.
</p>
<p>
For a detailed explanation of what Mocks are and what they are intended to do, see <a href="http://www.mockobjects.com/">MockObjects</a> and <a href="http://jmock.codehaus.org/">JMock</a>.
</p>
<p>
Right, the problem with the codebase developed by this team I'm referring to is that many of the "mocks" replace the wrong classes. The result of this is overly complicated tests, in addition to a false perception of what is being tested. Many of the "mocks" in this codebase are not really proper mocks, apart from having the word "Mock" in their name.
</p>
<p>
So where and how are these misunderstood "mocks" used? They are being used as substitutes for the classes that are supposed to be tested(!) In short, the unit tests are testing the "mocks".
</p>
<p>

The system consists of WebWork Actions that talk to Hibernate via DAOs (Data Access Objects). -A fairly common combination of technologies and patterns.
</p>
<p>

Most actions are following this kind of style:
</p>
<div class="code"><pre><span class="category1">public</span> <span class="category1">class</span> CheeseAction <span class="category1">extends</span> ActionSupport {
     <span class="category1">private</span> <span class="category2">String</span> cheese;
     <span class="category1">public</span> <span class="category1">void</span> setCheese(<span class="category2">String</span> cheese) { this.cheese = cheese; }
     <span class="category1">public</span> <span class="category2">String</span> getCheese() { <span class="category1">return</span> cheese; }
 
     <span class="category1">public</span> <span class="category2">String</span> execute() {
          <span class="category1">try</span> {
               <span class="linecomment">// CheeseDao is a concrete class.</span>
               saveCheese(<span class="category1">new</span> CheeseDao());
               <span class="category1">return</span> SUCCESS;
           } <span class="category1">catch</span> (<span class="category2">Exception</span> e) {
               <span class="category1">return</span> ERROR;
           }
      }
 
     <span class="category1">protected</span> <span class="category1">void</span> saveCheese(CheeseDao dao) {
          dao.saveCheese(cheese);
      }
}</pre></div>

<p>

The CheeseDao class is where the Hibernate stuff happens. Calling the 
CheeseDao.saveCheese method will hit the database.
</p>
<p>

Hitting the database when testing an Action is very time consuming. The team therefore decided to mock out the hibernate DAOs in the tests.
</p>

<p>

The tests that test the actions follow this pattern:
</p>
<div class="code"><pre><span class="category1">public</span> <span class="category1">class</span> CheeseActionTest <span class="category1">extends</span> TestCase {
 
     <span class="category1">public</span> <span class="category1">void</span> testAddCheese() {
          <span class="linecomment">// Yikes, we're testing the "mock"</span>
          MockCheeseAction action = <span class="category1">new</span> MockCheeseAction();
          action.setCheese("<span class="quote">stilton</span>");
          assertEquals(ActionSupport.SUCCESS, action.execute());
          assertEquals("<span class="quote">stilton</span>", action.getSavedCheese());
      }
 
     <span class="category1">public</span> <span class="category1">class</span> MockCheeseAction <span class="category1">extends</span> CheeseAction {
          <span class="category1">private</span> <span class="category2">String</span> savedCheese;
  
          <span class="category1">protected</span> <span class="category1">void</span> saveCheese(CheeseDao dao) {
               CheeseDao mockDao = <span class="category1">new</span> CheeseDao() {
                    <span class="category1">public</span> <span class="category1">void</span> saveCheese(<span class="category2">String</span> cheese) {
                         savedCheese = cheese;
                     }
                };
               super.saveCheese(mockDao);
           }
  
          <span class="category1">public</span> <span class="category2">String</span> getSavedCheese() {
               <span class="category1">return</span> savedCheese;
           }
      }
}</pre></div>

<p>

(The development team's primary motivation for using mocks seems to have been to reduce the test execution time. While this is a noble goal, it is not the only good reason to use mocks. Another good reason to use them - and TDD in general - is to let good designs emerge more easily. Codebases developed with TDD and Mocks generally become a lot more decoupled than others).
</p>
<p>

It must have been when someone was thinking about how to have the actions use a different DAO (a mock DAO) that this <b>mocking antipattern</b> was invented. 
</p>
<p>

(If my assumption about how this "mocking" technique was conceived is correct, it is also likely that the tests were written after the actions themselves. At least at the time of the invention of the antipattern. If the test had been written before the action, the likelyhood of having the action so tightly coupled with the Hibernate DAO would have been reduced).
</p>
<p>

There is something fundamentally wrong about the "mocking" approach used in the test above:
</p>
<p>

1) The test is not testing the *real* action, but a subclass that only exists in the test codebase. The team's established practice is to extend the action and override methods that use objects that we want to mock out. Then, a mock object is created for the DAO (this is actually more like a proper mock), and the superclass' method is called with that object instead.
</p>
<p>

In this trivial example it may not look so bad. After all, the overridden saveCheese method in the "mock" calls the superclass' method, right?
</p>
<p>

But in the real codebase the tests and overridden actions are often so complicated (with many overridings) that this easily gets out of control.  Specifically, if the superclass is refactored, there is no guarantee that the test is still valid. The derived "mock" implementation within the test may not be overriding anything in the superclass anymore, and the test may fail to execute the methods originally intended.
</p>
<p>

2) The Action class is not tested through its public interface, which is how it will be accessed when assembled in the application.
</p>
<p>

3) The test becomes overly complicated because both the class under test AND its dependencies have to be "mocked".
</p>
<p>

4) The expectations that are supposed to verify that the action invokes the dao's methods are clunky, as they require additional fields and getters on the subclass "mock".
</p>
<p>

Mocks are substitutes for real classes. It is quite common to misunderstand <b>what</b> classes they are supposed to be substituted with mocks. Mocks are supposed to replace the objects that the <b>class under test</b> depends on. You should <b>never</b> substitute the class you intend to test with a Mock. If you do, you're not testing the real thing.
</p>
<p>

Here is what the code should have looked like:
(Also note the new name of the test method. I'll cover that in a new blog entry about "Unit Test Intents").
</p>

<div class="code"><pre><span class="category1">public</span> <span class="category1">class</span> CheeseAction <span class="category1">extends</span> ActionSupport {
     <span class="category1">private</span> <span class="category1">final</span> CheeseDao dao;
     <span class="category1">private</span> <span class="category2">String</span> cheese;
     <span class="category1">public</span> <span class="category1">void</span> setCheese(<span class="category2">String</span> cheese) { this.cheese = cheese; }
     <span class="category1">public</span> <span class="category2">String</span> getCheese() { <span class="category1">return</span> cheese; }
     
     <span class="linecomment">// Yes, you can do this. See http://wiki.opensymphony.com/space/PicoContainer+Integration</span>
     <span class="category1">public</span> CheeseAction(CheeseDao dao) {
          this.dao = dao;
      }
 
     <span class="category1">public</span> <span class="category2">String</span> execute() {
          <span class="category1">try</span> {
               dao.saveCheese(cheese);
               <span class="category1">return</span> SUCCESS;
           } <span class="category1">catch</span>(<span class="category2">Exception</span> e) {
               <span class="category1">return</span> ERROR;
           }
      }
}</pre></div>

<p>

And the test (which should ideally be written before the action):
</p>

<div class="code"><pre><span class="category1">public</span> <span class="category1">class</span> CheeseActionTest <span class="category1">extends</span> TestCase {
 
     <span class="category1">public</span> <span class="category1">void</span> testExecuteCallsSaveCheeseOnDaoAndSucceedsWhenNoDaoException() {
          Mock mockDao = <span class="category1">new</span> Mock(CheeseDao.class);
          mockDao.expect("<span class="quote">saveCheese</span>", C.eq("<span class="quote">stilton</span>"));
  
          CheeseAction action = <span class="category1">new</span> CheeseAction((CheeseDao)mockDao.proxy());
          action.setCheese("<span class="quote">stilton</span>");
  
          assertEquals(ActionSupport.SUCCESS, action.execute());
          mockDao.verify();
      }
}</pre></div>


<p>
There are several benefits doing Mocking like this (the proper way):
</p>
<p>

1) The tests get a lot shorter.
</p>
<p>

2) It's more readable.
</p>
<p>

3) We're testing the right thing.
</p>
<p>

4) TDD buys us nice decoupled designs for free. This action is now a PicoComponent, honouring constructor based dependency injection.
</p>
<p>

However, in order to be able to do things properly like this, the dependencies to 
be mocked out (in this case, the CheeseDao) should ideally be interfaces. This can incur some percieved overhead in the codebase, as the developer will now have to maintain both a CheeseDao and a HibernateCheeseDao. But it's better than having to maintain a CheeseAction and a MockCheeseAction.
</p>
<p>

Recent additions to MockObjects (and soon JMock?) allow dynamic mocking 
of concrete classes too, using CGLib.
</p>
<p>

And last, but not least. If you write your tests first, using mocks, you will end up with well-designed, nicely decoupled code. Post-testing and post-mocking is actually quite evil. It tends to open up and cripple the classes even more than they were before.
</p>
]]></description>
<dc:subject>Methodology</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-01-12T18:34:43+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000533_re_enough_with_the_test_driven_development_hype.html">
<title>RE: Enough with the Test Driven Development Hype</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000533_re_enough_with_the_test_driven_development_hype.html</link>
<description><![CDATA[<p><a href="http://www.livejournal.com/users/subtlety/26652.html">Paul</a> is tired of the "TDD hype". He as many others seem to have misunderstood what it's all about. (TDD is not a testing technique). He also seems to ignore the benefits of TDD.</p>

<p><i>"You'll spend more time writing tests than code."</i></p>

<p>While in some cases this is true, or close to true, it is not a bad thing. Here is why:</p>

<p>1) You end up with less (functional) code than a with a non-TDD approach. This is because with TDD you don't write code you "think you might need". You write exactly what makes the test pass.</p>

<p>2) You know when you're done. Knowing when you're done saves time.</p>

<p>3) You gain confidence for refactoring. Being able to refactor is essential in order to obtain a maintainable and well designed codebase. It is impossible (or very time consuming at best) to refactor if you don't have tests. This is because you can't know whether your refactorings will break something without tests. Having a well designed codebase saves time.</p>

<p>So while there might be some percieved overhead in doing TDD, the design and maintainability of your codebase will improve drastically. You will catch bugs sooner rather than later. This will in the long run lead to SHORTER development time.</p>

<p>Don't get me wrong - I don't do TDD because I want to save time. I just wanted to argue that TDD does not slow you down.</p>

<p><i>"You'll spend ages writing hugely complicated test cases."</i></p>

<p>The TDD practioneers stress that unit tests shall be simple. The test fixture should be simple and the assertions few. If your tests are simple, so will your code will be.</p>

<p>Systems developed without TDD are always more complicated than the TDD ones. If your test is too complicated, you're not doing it right.</p>

<p><i>"You'll spend ages bug fixing the test harnesses that sometimes are more complicated than the code they're testing".</i></p>

<p>This is like saying that cooking is crazy because there are bad chefs. There are good and bad ways to do TDD. The good one is to keep the tests simple. So do that.</p>

<p>TDD is not easy. It is very hard to do properly until you pair with someone who knows how to do it. -Even for seasoned developers (who often have a lot of pride to swollow and a lot to unlearn). </p>

<p>Many people think they are doing TDD while they are not. There is more to it than writing the tests first. -Like always doing the simplest thing and continuosly refactor the code. Mocking is also an essential part of the whole TDD concept.<br />
</p>]]></description>
<dc:subject>Methodology</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2004-01-01T17:26:19+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000150_qdox_attributes.html">
<title>QDox Attributes</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000150_qdox_attributes.html</link>
<description><![CDATA[<p>Can't wait for attributes? Need them now? Check out QDox Attributes! http://cvs.codehaus.org/viewcvs.cgi/qdox-attributes/?root=qdox</p>

<p>Piotr JFDI'ed the long-awaited thing. An easy to use and powerful attributes package for the Java platofrm.</p>

<p>It draws the best from Ara's XRAI, Mark's Attrib4J, Jon's Nanning and Jakarta's Commons-Attributes. All of which failed to deliver a usable product, but (tribute) all contributed to Piotr's new brainchild via their ideas and code.</p>

<p>And if you don't care about attributes - just read the code and doco. It's nice. Very nice. The package scope is even com.thoughtworks even if Piotr is not a Thoughtworker.</p>

<p>This begs for an interview :-)<br />
</p>]]></description>
<dc:subject>Java</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2003-09-12T00:55:17+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000149_ideamock.html">
<title>IdeaMock</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000149_ideamock.html</link>
<description><![CDATA[<p>I'm writing an IDEA plugin. Ignorant of any other way to test it (yes, I have JUnit) than closing IDEA, reinstalling the plugin, reopening. Then HumanTesting.</p>

<p>IntelliBrains: Can you write an IdeaMock for us? So we can mock IDEA in IDEA? Or is there a way to launch IDEA from IDEA?</p>

<p>Puleeese!</p>

<p>:-)</p>]]></description>
<dc:subject>Java</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2003-09-12T00:12:38+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000136_picocontainer_logo_contest.html">
<title>PicoContainer Logo Contest</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000136_picocontainer_logo_contest.html</link>
<description><![CDATA[<p>PicoContainer needs a better logo. Get your brushes and submit your art! <a href="http://wiki.codehaus.org/picocontainer/LogoContest">http://wiki.codehaus.org/picocontainer/LogoContest</a><br />
</p>]]></description>
<dc:subject>Java</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2003-08-29T17:16:17+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000096_picocontainer_10alpha2_is_released.html">
<title>PicoContainer 1.0-alpha-2 is released</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000096_picocontainer_10alpha2_is_released.html</link>
<description><![CDATA[<p>Changes: <a href="http://www.picocontainer.org/changes-report.html">http://www.picocontainer.org/changes-report.html</a></p>

<p>Flamers: It's only 5 weeks old, so don't pick too many holes in it. Use our <a href="http://jira.codehaus.org/secure/BrowseProject.jspa?id=10120">JIRA</a> instead.</p>]]></description>
<dc:subject></dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2003-07-10T11:52:07+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000093_i_moved_to_codehaus.html">
<title>I moved to Codehaus</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000093_i_moved_to_codehaus.html</link>
<description><![CDATA[<p>I have been a <a href="http://wiki.codehaus.org/general/TheHausmates">hausmate</a> for<br />
a while now, so I am moving as much as possible of my OSS projects to<br />
<a href="http://codehaus.org/">Codehaus</a>. Then what's more natural than moving the blog too?</p>

<p>My old blogs were at <a href="href="http://www.freeroller.net/page/rinkrank">freeroller</a> and <a href="http://rinkrank.blog-city.com/">blog-city</a>. Rest in peace.</p>]]></description>
<dc:subject>Java</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2003-07-10T01:27:37+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000091_new_job.html">
<title>New job</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000091_new_job.html</link>
<description><![CDATA[<p>I needed a more challenging job. So I started in ThoughtWorks UK a month ago. I'm glad I did.</p>]]></description>
<dc:subject>Java</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2003-07-10T01:02:42+00:00</dc:date>
</item>
<item rdf:about="http://blogs.codehaus.org/people/rinkrank/archives/000090_simian_refactoring_detector.html">
<title>Simian : Refactoring detector</title>
<link>http://blogs.codehaus.org/people/rinkrank/archives/000090_simian_refactoring_detector.html</link>
<description><![CDATA[<p>A couple of weeks ago a colleague at work pointed me to a tool called <a href="http://www.redhillconsulting.com.au/products/simian/index.html">Simian</a> (Similarity Analyser). It works very much in the same way as PMD's subproject <a href="http://pmd.sourceforge.net/cpd.html">CPD</a> (Copy Paste Detector).</p>

<p>I've written a <a href="http://jira.codehaus.org/secure/ViewIssue.jspa?key=MAVEN-516">Maven plugin</a> for it. Have a look at a <a href="http://www.picocontainer.org/simian-report.html">sample report</a>.</p>

<p>With a tool like this, you quickly see candidates for refactoring.</p>]]></description>
<dc:subject>Java</dc:subject>
<dc:creator>rinkrank</dc:creator>
<dc:date>2003-07-10T00:48:25+00:00</dc:date>
</item>


</rdf:RDF>
