<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Transient Technology &#187; software quality</title>
	<atom:link href="http://martinaharris.com/category/development/software-quality/feed/" rel="self" type="application/rss+xml" />
	<link>http://martinaharris.com</link>
	<description>Next time you look it might be gone</description>
	<lastBuildDate>Wed, 25 Apr 2012 09:52:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Achieving Test Driven Nirvana</title>
		<link>http://martinaharris.com/2010/04/test-driven-nirvana/</link>
		<comments>http://martinaharris.com/2010/04/test-driven-nirvana/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 18:47:11 +0000</pubDate>
		<dc:creator>Martin Harris</dc:creator>
				<category><![CDATA[scrum and agile]]></category>
		<category><![CDATA[software quality]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[dialog]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[leadership]]></category>
		<category><![CDATA[pair-code]]></category>
		<category><![CDATA[quality]]></category>
		<category><![CDATA[re-factor]]></category>
		<category><![CDATA[scrum]]></category>
		<category><![CDATA[scrum-master]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[teams]]></category>
		<category><![CDATA[uptake]]></category>

		<guid isPermaLink="false">http://martinaharris.com/?p=946</guid>
		<description><![CDATA[Well perhaps not Nirvana then, but at least having a suitable level of test coverage.  I wanted to write an article around the uptake of test driven development. Scrum and agile are hard to do well. If you break these &#8230; <a href="http://martinaharris.com/2010/04/test-driven-nirvana/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<div id="attachment_951" class="wp-caption alignleft" style="width: 210px"><a href="http://martinaharris.com/wp-content/uploads/2010/04/cubacar.png"><img class="size-full wp-image-951" title="cubacar" src="http://martinaharris.com/wp-content/uploads/2010/04/cubacar.png" alt="Car Cuba" width="200" height="311" /></a><p class="wp-caption-text">Cuban Car: Martin Harris</p></div>
<p>Well perhaps not <a title="Nirvana definition" href="http://en.wikipedia.org/wiki/Nirvana" target="_blank">Nirvana </a>then, but at least having a suitable level of test coverage.  <img src='http://martinaharris.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>I wanted to write an article around the uptake of test driven development.  Scrum and agile are hard to do well.  If you break these down, you often find that the components are pretty challenging too.  TDD is difficult but it has gained widespread recognition at the intellectual level.   On the ground though the practice can be patchy.  Why?</p>
<p>Before writing this article I had a look around to see what else had been written.  This article on  <a title="Resistance to TDD" href="http://regeiger.wordpress.com/2008/09/30/understanding-tdd-resistance-%E2%80%93-is-it-more-than-the-learning-curve/" target="_blank">Geiger&#8217;s Counterpoint</a> sums up my thoughts exactly.  Its such a good article that I hardly have anything left to say.  In fact neatly I can just provide some bullet points!</p>
<h2><span id="more-946"></span>Improving the uptake of Test Driven Development</h2>
<p>Programmers need help to adopt test driven practice.  So how can you go about that?</p>
<ul>
<li><strong>Lead from the front:</strong> If your senior developers are not checking in fully tested code it will destroy the practice.  Its highly demoralising to be producing well tested code only to have a senior ruin it by checking in code with partial coverage.  I can not stress hard enough that the practice must come from the top.</li>
<li><strong>Pair code and mentor the practice:</strong> I have yet to meet a developer that took to TDD right from the off.  Most people struggle to produce good code, and TDD is far from intuitive.  The best way to improve is to see good code and work with people that write good code.  So mentor and pair code to disseminate the practice.</li>
<li><strong>Use coverage reporting:</strong> Use tools like <a title="Clover Coverage Reporting." href="http://www.atlassian.com/software/clover/" target="_blank">clover</a>, <a title="Cobertura Coverage Reporting" href="http://cobertura.sourceforge.net/" target="_blank">cobertura </a> and <a title="Emma Coverage Reporting" href="http://emma.sourceforge.net/" target="_blank">emma</a> to provide reports so that you can see what lines of code are covered by tests.  Make this reporting part of your build.  Encourage developers to use coverage reports to check the quality of their testing practice.  Understand though that coverage is not everything you need to concern yourself with, sensible assertions are important too.</li>
<li><strong>Encourage discussion: </strong>Next time you find something un-tested in your codebase, create a discussion about it.  Sometimes there are reasons, its badly written making it difficult to test.  Perhaps its an  integration point.  Through discussion you will encourage the team to find a solution and write some tests.</li>
<li><strong>Set a bar: </strong>Find a way to set a bar.  i.e find the current coverage levels and don&#8217;t allow the numbers to fall.  I worked on a project where a custom build component was added.  It parsed the clover reports, found the current coverage level and broke the build if it fell after checkin.</li>
</ul>
<h2>Summary</h2>
<p>Most project suffer lower levels of test coverage than ideal.  Encourage test driven development and find ways to teach how it can be done.  Create dialog and get the teams to self organise around the goal of improving test quality and coverage.  Use tools and processes to support the team.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F&amp;title=Achieving+Test+Driven+Nirvana" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F&amp;title=Achieving+Test+Driven+Nirvana" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F&amp;title=Achieving+Test+Driven+Nirvana" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F&amp;headline=Achieving+Test+Driven+Nirvana" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Achieving+Test+Driven+Nirvana&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Achieving+Test+Driven+Nirvana&amp;u=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Achieving+Test+Driven+Nirvana&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Achieving+Test+Driven+Nirvana&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Achieving+Test+Driven+Nirvana&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F&amp;title=Achieving+Test+Driven+Nirvana&amp;summary=&amp;source=" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F04%2Ftest-driven-nirvana%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><div class="dzone_button" style="float: right; margin-left: 5px;">
<script type="text/javascript">
var dzone_url = 'http://martinaharris.com/2010/04/test-driven-nirvana/';
var dzone_title = 'Achieving Test Driven Nirvana';
var dzone_blurb = '';
var dzone_style = '2';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div>]]></content:encoded>
			<wfw:commentRss>http://martinaharris.com/2010/04/test-driven-nirvana/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>KeySet v EntrySet code tidy</title>
		<link>http://martinaharris.com/2010/03/keyset-v-entryset-code-tidy/</link>
		<comments>http://martinaharris.com/2010/03/keyset-v-entryset-code-tidy/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 18:02:25 +0000</pubDate>
		<dc:creator>Martin Harris</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[software quality]]></category>
		<category><![CDATA[entryset]]></category>
		<category><![CDATA[keyset]]></category>
		<category><![CDATA[map]]></category>

		<guid isPermaLink="false">http://martinaharris.com/?p=939</guid>
		<description><![CDATA[Its astounding how often I find maps being used like this. for(String name: names.keySet()) { mymap.put(mymap.get(name),name); }﻿ Its inefficient because you have to fetch the keys and perform a lookup in the map with the key. Instead using the EntrySet &#8230; <a href="http://martinaharris.com/2010/03/keyset-v-entryset-code-tidy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Its astounding how often I find maps being used like this.</p>
<pre class="brush: java; gutter: false; wrap-lines: false">
for(String name: names.keySet()) {
    mymap.put(mymap.get(name),name);
}﻿
</pre>
<p>Its inefficient because you have to fetch the keys and perform a lookup in the map with the key.</p>
<p>Instead using the EntrySet you can get all the keys and values in one hit.  This saves having to perform the map lookup.</p>
<pre class="brush: java; gutter: false; wrap-lines: false">
for (Entry&lt;String, String&gt; entry : entrySet) {
    mymap.put(entry.getValue(),entry.getKey());
}
</pre>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F&amp;title=KeySet+v+EntrySet+code+tidy" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F&amp;title=KeySet+v+EntrySet+code+tidy" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F&amp;title=KeySet+v+EntrySet+code+tidy" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F&amp;headline=KeySet+v+EntrySet+code+tidy" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=KeySet+v+EntrySet+code+tidy&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=KeySet+v+EntrySet+code+tidy&amp;u=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=KeySet+v+EntrySet+code+tidy&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=KeySet+v+EntrySet+code+tidy&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=KeySet+v+EntrySet+code+tidy&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F&amp;title=KeySet+v+EntrySet+code+tidy&amp;summary=&amp;source=" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F03%2Fkeyset-v-entryset-code-tidy%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><div class="dzone_button" style="float: right; margin-left: 5px;">
<script type="text/javascript">
var dzone_url = 'http://martinaharris.com/2010/03/keyset-v-entryset-code-tidy/';
var dzone_title = 'KeySet v EntrySet code tidy';
var dzone_blurb = '';
var dzone_style = '2';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div>]]></content:encoded>
			<wfw:commentRss>http://martinaharris.com/2010/03/keyset-v-entryset-code-tidy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google Objects.equal, useful but be careful.</title>
		<link>http://martinaharris.com/2010/02/google-objects-equal-useful-but-be-careful/</link>
		<comments>http://martinaharris.com/2010/02/google-objects-equal-useful-but-be-careful/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 20:20:14 +0000</pubDate>
		<dc:creator>Martin Harris</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[software quality]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[compareto]]></category>
		<category><![CDATA[equals]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://martinaharris.com/?p=818</guid>
		<description><![CDATA[Google have a nice equals method to make boiler plate equals easier to read. Particularly good if you have many attributes in the method. http://publicobject.com/2007/09/coding-in-small-with-google-collections_8175.html Be careful to check that your objects are consistent with equals though.  I have mentioned &#8230; <a href="http://martinaharris.com/2010/02/google-objects-equal-useful-but-be-careful/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Google have a nice equals method to make boiler plate equals easier to read.  Particularly good if you have many attributes in the method.  <a title="Google Object.equals method." href="http://publicobject.com/2007/09/coding-in-small-with-google-collections_8175.html" target="_blank">http://publicobject.com/2007/09/coding-in-small-with-google-collections_8175.html</a></p>
<p>Be careful to check that your objects are consistent with equals though.  I have mentioned this <a title="Equals Generation" href="/2009/10/ide-generation-of-equals-methods-has-its-moments/" target="_blank">before</a>.<br />
<span id="more-818"></span><br />
In the following method I am using the Objects.equal with a BigDecimal class.  It does not work because BigDecimal equals treats 0 and 0.0 as not equal, which is probably not what you need.</p>
<pre class="brush: java; light: true">
public boolean equals(Object obj) {
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }

    final TestEquals other = (TestEquals) obj;

    return Objects.equal(this.bigDecimal, other);
}</pre>
<p>The common solution is to use the compareTo method instead like so.</p>
<pre class="brush: java; light: true">  final TestEquals other = (TestEquals) obj;
  if (this.bigDecimal != other.bigDecimal &amp;&amp;
      (this.bigDecimal == null
      || this.bigDecimal.compareTo(other.bigDecimal) != 0)) {
    return false;
  }
  return true;</pre>
<p>I will be using this technique, especially where the object has many attributes but I will be <a title="Testing Equals" href="/2009/10/testing-java-equals-and-hashcode-methods-essential/" target="_blank">testing the equals method</a>.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F&amp;title=Google+Objects.equal%2C+useful+but+be+careful." target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F&amp;title=Google+Objects.equal%2C+useful+but+be+careful." target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F&amp;title=Google+Objects.equal%2C+useful+but+be+careful." target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F&amp;headline=Google+Objects.equal%2C+useful+but+be+careful." target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Google+Objects.equal%2C+useful+but+be+careful.&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Google+Objects.equal%2C+useful+but+be+careful.&amp;u=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Google+Objects.equal%2C+useful+but+be+careful.&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Google+Objects.equal%2C+useful+but+be+careful.&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Google+Objects.equal%2C+useful+but+be+careful.&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F&amp;title=Google+Objects.equal%2C+useful+but+be+careful.&amp;summary=&amp;source=" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F02%2Fgoogle-objects-equal-useful-but-be-careful%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><div class="dzone_button" style="float: right; margin-left: 5px;">
<script type="text/javascript">
var dzone_url = 'http://martinaharris.com/2010/02/google-objects-equal-useful-but-be-careful/';
var dzone_title = 'Google Objects.equal, useful but be careful.';
var dzone_blurb = '';
var dzone_style = '2';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div>]]></content:encoded>
			<wfw:commentRss>http://martinaharris.com/2010/02/google-objects-equal-useful-but-be-careful/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TimeUnit use it more of the Time please!</title>
		<link>http://martinaharris.com/2010/01/timeunit-its-brill/</link>
		<comments>http://martinaharris.com/2010/01/timeunit-its-brill/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 20:45:49 +0000</pubDate>
		<dc:creator>Martin Harris</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[software quality]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[setter]]></category>
		<category><![CDATA[TimeUnit]]></category>

		<guid isPermaLink="false">http://martinaharris.com/?p=600</guid>
		<description><![CDATA[Time for my first blog of the year. Yea! Mind you its a bit small, but then perhaps that is a good thing. Look at these two setters. Setter methods like the first example are very common. Take a look &#8230; <a href="http://martinaharris.com/2010/01/timeunit-its-brill/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Time for my first blog of the year.  Yea!  Mind you its a bit small, but then perhaps that is a good thing.</p>
<p>Look at these two setters.  Setter methods like the first example are very common.  Take a look at the second its so much better.  With the second the responsibility to convert is neatly delegated to another class instead of forcing the user of the api to work it out.  In addition the programmer can supply hours, minutes or any other that TimeUnit supports.</p>
<pre class="brush: java; light: true">
public void setDuration(long durationInMs) {
    this.duration = durationInMs;
}

public void setDuration(long duration, TimeUnit timeUnit) {
    this.duration = timeUnit.toMillis(duration);
}﻿
</pre>
<p>TimeUnit was brought to you by: java.util.concurrent.TimeUnit!  Its handy, so use it!  <img src='http://martinaharris.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F&amp;title=TimeUnit+use+it+more+of+the+Time+please%21" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F&amp;title=TimeUnit+use+it+more+of+the+Time+please%21" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F&amp;title=TimeUnit+use+it+more+of+the+Time+please%21" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F&amp;headline=TimeUnit+use+it+more+of+the+Time+please%21" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=TimeUnit+use+it+more+of+the+Time+please%21&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=TimeUnit+use+it+more+of+the+Time+please%21&amp;u=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=TimeUnit+use+it+more+of+the+Time+please%21&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=TimeUnit+use+it+more+of+the+Time+please%21&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=TimeUnit+use+it+more+of+the+Time+please%21&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F&amp;title=TimeUnit+use+it+more+of+the+Time+please%21&amp;summary=&amp;source=" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fmartinaharris.com%2F2010%2F01%2Ftimeunit-its-brill%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><div class="dzone_button" style="float: right; margin-left: 5px;">
<script type="text/javascript">
var dzone_url = 'http://martinaharris.com/2010/01/timeunit-its-brill/';
var dzone_title = 'TimeUnit use it more of the Time please!';
var dzone_blurb = '';
var dzone_style = '2';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div>]]></content:encoded>
			<wfw:commentRss>http://martinaharris.com/2010/01/timeunit-its-brill/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>When you can&#8217;t avoid an out parameter</title>
		<link>http://martinaharris.com/2009/12/out-parameter/</link>
		<comments>http://martinaharris.com/2009/12/out-parameter/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 05:00:05 +0000</pubDate>
		<dc:creator>Martin Harris</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[software quality]]></category>
		<category><![CDATA[builder]]></category>
		<category><![CDATA[collections]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[immutable]]></category>
		<category><![CDATA[parameter]]></category>
		<category><![CDATA[quality]]></category>

		<guid isPermaLink="false">http://martinaharris.com/?p=473</guid>
		<description><![CDATA[We all know its a good idea to avoid using out variables in Java. In almost every case the code can be split up to avoid the situation. Its bad semantics because when reading the code its not obvious which &#8230; <a href="http://martinaharris.com/2009/12/out-parameter/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>We all know its a good idea to avoid using <em>out</em> variables in Java.  In almost every case the code can be split up to avoid the situation.  Its bad semantics because when reading the code its not obvious which object passed, if any will get mutated.  So the reader is forced to open the method to find out what it does. In <a title="Clean Code Book Reference" href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1259702833&amp;sr=1-1" target="_blank">Robert C Martin&#8217;s Clean Code Book</a> he calls this forcing a double take, and suggests some ways to avoid the problem.  Rarely you find a case where you can&#8217;t avoid it, or to be more accurate, avoiding it leads to worse problems.</p>
<p>Take a look at this interface.  If I find this populate method, I am likely to have to open implementations.  I don&#8217;t know if it populates one map from the other or both maps.</p>
<pre class="brush: java; gutter: false; wrap-lines: true">import java.util.Map;

public interface NastyPopulator {

void populate(Map&lt;String, String&gt; driver, Map&lt;String, String&gt; driverHolder);

}</pre>
<p>The problem is the semantics of map are that you can read from maps or you can write to them.  I think this is a slightly better approach below.</p>
<p>I have used ImmutableMap.Builder.  The semantics of this are that it is used to build things.  I will call build() on the object later to get a map.  Next its an ImmutableMap.  So not only am I declaring that the two parameters are likely to be used to build something, that thing will ultimately be Immutable so in effect the signature declares that I am not expected to make modifications later.  Finally the method name is unambiguous buildMaps, which pretty much says what its going to do.</p>
<pre class="brush: java; gutter: false; wrap-lines: true">import com.google.common.collect.ImmutableMap;

public interface LessNastyPopulator {

void buildMaps(ImmutableMap.Builder&lt;String, String&gt;  driver, ImmutableMap.Builder&lt;String, String&gt; driverHolder);

}</pre>
<p>Feels like a stronger declaration to me.  If ImmutableMap is awkward you could define your own static builder and pass that in, at least your still declaring up front, that this method is  builds the two maps.  If the method is reading from one map and building others, how about passing an iterator and a builder?</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F&amp;title=When+you+can%27t+avoid+an+out+parameter+" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F&amp;title=When+you+can%27t+avoid+an+out+parameter+" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F&amp;title=When+you+can%27t+avoid+an+out+parameter+" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F&amp;headline=When+you+can%27t+avoid+an+out+parameter+" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=When+you+can%27t+avoid+an+out+parameter+&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=When+you+can%27t+avoid+an+out+parameter+&amp;u=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=When+you+can%27t+avoid+an+out+parameter+&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=When+you+can%27t+avoid+an+out+parameter+&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=When+you+can%27t+avoid+an+out+parameter+&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F&amp;title=When+you+can%27t+avoid+an+out+parameter+&amp;summary=&amp;source=" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F12%2Fout-parameter%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><div class="dzone_button" style="float: right; margin-left: 5px;">
<script type="text/javascript">
var dzone_url = 'http://martinaharris.com/2009/12/out-parameter/';
var dzone_title = 'When you can&#8217;t avoid an out parameter';
var dzone_blurb = '';
var dzone_style = '2';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div>]]></content:encoded>
			<wfw:commentRss>http://martinaharris.com/2009/12/out-parameter/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Test anti-patterns project, contributors wanted!</title>
		<link>http://martinaharris.com/2009/11/anti-patterns-testing/</link>
		<comments>http://martinaharris.com/2009/11/anti-patterns-testing/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 05:00:28 +0000</pubDate>
		<dc:creator>Martin Harris</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[software quality]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[quality]]></category>
		<category><![CDATA[re-factor]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://martinaharris.com/?p=236</guid>
		<description><![CDATA[I deliberately wrote a poor quality test, so that I could show how easy it is to re-factor it to a better one.  I was driven by having seen lots of such poor tests and to be honest I don't want to see another of its ilk again.  I might write a test like this myself, but I would <strong>never</strong> leave it like this.  Its part finished, littered with cut and paste, poorly named methods and hard coded values.

I show how to re-factor the test using several patterns for test fixtures.  The setup stage is often the worst bit of a bad test.  If you want to contribute some of your own bad tests and example improvements, <strong>read the blog, download the project and contribute!</strong> <a href="http://martinaharris.com/2009/11/anti-patterns-testing/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Take a look at the following test class.  I deliberately wrote this poor quality test, so that I could show how easy it is to re-factor it to a better one.  I was driven by having seen lots of such poor tests and to be honest I don&#8217;t want to see another of its ilk again.  I might write a test like this myself, but I would <strong>never</strong> leave it like this.  Its part finished.  Its littered with cut and paste, poorly named methods and hard coded values.  It&#8217;s a bit like a surgeon performing an operation and not sewing up the hole!  I would go as far as to say that leaving tests in this state is unprofessional.  There is no excuse as most of the lessons of good naming and code re-use have been written down a long time back.  More lately in <a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882">Clean Code by Robert C. Martin</a>.  I just don&#8217;t understand why people still write rubbish like this!  Possibly because they are allowed to get away with it!  Note that the test provides 100% coverage of the implementation class, but its not enough to stop there.</p>
<p>Have a read over the class, and then move on to read the steps to re-factor to better patterns.  I have several designs here that focus on the setup stage of a test.  As your tests get more complex you will find the patterns here support ever increasing complexity.  In an Agile project you might move from one system to the next as the requirements ramp up.  Then once you see where I am heading, I lay down a challenge.</p>
<h2>Test anti-patterns project, contributors wanted!</h2>
<p>If you have a Test Anti-Pattern that you would like to showcase.  Check out my code from gitHub, add the new example and examples of how to re-factor the code.  Blog it to your own blog with a reference to this page, or drop a comment.  If we get enough I will setup a page with an index to all the blogs.</p>
<p>The code can be<a href="http://help.github.com/forking/"> forked out with git</a> from gitHub <a href="http://github.com/mhgit/TerribleJavaTestingMadeGood">http://github.com/mhgit/TerribleJavaTestingMadeGood</a>.  It should be an easy start.  Its a full maven project with a small dependency set and maven site reports already built in for test coverage.  Its fully open source with the Apache 2.0 license.  Once you have your new example, tell me about it by adding a comment to this page, and following the git forking instructions for making a git pull available.</p>
<p><span id="more-236"></span></p>
<h2>I hope I never see another badly written test like this:</h2>
<p><cite>&#8230;but unfortunately I probably will&#8230; <img src='http://martinaharris.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> <cite></p>
<pre class="brush: java; gutter: false; wrap-lines: false">package org.testpatterns.dupcodeexample.lineutil.unit;

  import org.testpatterns.dupcodeexample.lineutil.SimplePage;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Set;
  import org.junit.Test;
  import static org.junit.Assert.*;

  /**
  * Terrible Test SimplePage Function.
  *
  * @author martinh
  */
  public class TerribleSimplePageTest {

    @Test
    public void testPageAssembley() {

        String item = "-23456789-";

        Map&lt;Integer, String&gt; expectedLines = new HashMap&lt;Integer, String&gt;();

        expectedLines.put(1, item + item + item + item + item);
        expectedLines.put(2, item + item + item + item + item);
        expectedLines.put(3, item + item + item + item + item);
        expectedLines.put(4, item + item + item + item + item);

        SimplePage page = SimplePage.newInstance(item, 20);
        Map&lt;Integer, String&gt; actualMap = page.getMap();

        assertEquals(expectedLines, actualMap);

    }

    @Test
    public void testPageKeySet() {

        String item = "-23456789-";

        Map&lt;Integer, String&gt; expectedLines = new HashMap&lt;Integer, String&gt;();

        expectedLines.put(1, item + item + item + item + item);
        expectedLines.put(2, item + item + item + item + item);
        expectedLines.put(3, item + item + item + item + item);
        expectedLines.put(4, item + item + item + item + item);

        SimplePage page = SimplePage.newInstance(item, 20);
        Set&lt;Integer&gt; actualKeySet = page.getKeySet();

        assertEquals(expectedLines.keySet(), actualKeySet);

    }

    @Test
    public void testAddLines() {

        String item = "-23456789-";

        SimplePage page = SimplePage.newInstance(item, 20);

        Map&lt;Integer, String&gt; additionalLines = new HashMap&lt;Integer, String&gt;();

        additionalLines.put(1, item + item + item + item + item);
        additionalLines.put(2, item + item + item + item + item);
        additionalLines.put(3, item + item + item + item + item);
        additionalLines.put(4, item + item + item + item + item);

        page.appendLines(item, 20);

        Map&lt;Integer, String&gt; actualMap = page.getMap();

        Map&lt;Integer, String&gt; expectedLines = new HashMap&lt;Integer, String&gt;();

        expectedLines.put(1, item + item + item + item + item);
        expectedLines.put(2, item + item + item + item + item);
        expectedLines.put(3, item + item + item + item + item);
        expectedLines.put(4, item + item + item + item + item);
        expectedLines.put(5, item + item + item + item + item);
        expectedLines.put(6, item + item + item + item + item);
        expectedLines.put(7, item + item + item + item + item);
        expectedLines.put(8, item + item + item + item + item);
        assertEquals(expectedLines, actualMap);

    }
}</pre>
<h2>Fixture as a normal method: ImprovedSimplePageTest</h2>
<p>I am not going to post up code for all the classes.  Check it out from gitHub for that.  So I just highlight the main steps and show the final full class.</p>
<p>The basis of the first pattern is simple.  Most small tests like this just need one method for setup, this eliminates all the cut and paste.  This might be run from an @Before, or @BeforeClass annotation, as part of the constructor or perhaps just from the test itself.  These techniques will have to be applied depending on what you need to achieve.  For instance if your setup is inserting into a database, you have to make sure your data does not violate db constraints.  So the annotations might not help, plus you have the added complexity of getting hold of your database.  A good pattern is to use an in memory db, but some of the annotations will cause the setup to get run before each test.  So in a nutshell attempt to have one setup, and its not that important which system you use to run it, that will depend on what your doing.</p>
<h3>Refactoring steps:</h3>
<ul>
<li>Rename methods.</li>
<p>Have a good strategy for your test names if they are good enough you will not need to comment the methods.  The pattern I use here is: [What is being tested]_[What is expected].  If you can&#8217;t fit it all into the name, the test is probably too big and needs breaking down.  A test should be concise.</p>
<li>Remove duplication.</li>
<ol>
There were two steps to this:</p>
<li>I Added this method: createLineExpectations to create expectations.</li>
<p>This allowed me to remove all the duplicated test setup that had been cut and pasted all through the class.  I wrote this bad test, using TDD to come up with the supporting implementation, so even as I wrote it the test went through several iterations.  During that process I left a chunk of unused map behind.  Which just goes to prove that if your test is messy, its difficult to spot problems.<br />
<strong>An unused chunk of code that hid in the duplications</strong></p>
<pre class="brush: java; light: true">  Map&lt;Integer, String&gt; additionalLines = new HashMap&lt;Integer, String&gt;();

  additionalLines.put(1, item + item + item + item + item);
  additionalLines.put(2, item + item + item + item + item);
  additionalLines.put(3, item + item + item + item + item);
  additionalLines.put(4, item + item + item + item + item);</pre>
<li>Added constants and moved all the hard coded value out.</li>
</ol>
</ul>
<h2>Collecting setup into an inner fixture class: LocalFixtureBasedPageTest</h2>
<p>Its not long before the technique starts to breakdown.  As you add more supporting methods it gets harder to see what is test, and what is setup.  So the next stage is to move the setup into an inner class.  This way, most ide&#8217;s will allow you to collapse the fixture hiding it away.  When I read a test, I am mostly interested in the expectations, not the setup.  Note that the constants have been moved into the fixture.  So the fixture becomes an inner class that supplies everything to do with setup for the test.</p>
<pre class="brush: java; light: true">    private class DataFixture {

        private final String ITEM = "-23456789-";
        private final int LINES_8 = 8;
        private final int LINES_4 = 4;

        Map&lt;Integer, String&gt; createLineExpectations(String item,
                int numLinesToCreate) {
            Map&lt;Integer, String&gt; expectedLines = Maps.newHashMap();

            StringBuilder sb = new StringBuilder();
            sb.append(item).append(item).append(item).append(item).append(item);
            String line = sb.toString();
            for (int i = 0; i &lt; numLinesToCreate; i++) {
                    expectedLines.put(i + 1, line);
            }

            return expectedLines;
        }
    }</pre>
<h2>Fixture as a spring injected component: SpringWiredSimplePageTest</h2>
<p>When a test gets more complex you sometimes end up with masses of complexity building up in inner classes.  I sometimes use inner classes to build complex data requirements using the <a href="http://www.factorypattern.com/method-chaining/">setter method chaining pattern</a> for instance.  Each inner class becoming a container for parameterized setup.  The next level of complexity is needing to share the setup over many test classes.</p>
<p><strong>These are your options.</strong></p>
<ol>
<li>Create a static helper class</li>
<p>Not a bad solution, but I hate having to access the methods via the class name.  Static classes often collect unrelated methods too.  Also, its often not possible to work with the restriction of being static.</p>
<li>Abstractions and class hierarchy.</li>
<p>This is often posed as a solution when you need to share the setup over many classes.  In this case its a terrible solution. The abstraction gets further complicated because your using the wrong OO mechanism.  It also means your test has to extend a class, in some situations, you are already extending to get at the internals of the object under test.</p>
<li>Use method injection to supply a fixture component.</li>
<p>If you break the fixture out to a component its easier to manage the complexity of the fixture away from the test with composition.  You can have many components each doing something specific for a set of tests.  You could even inject more than one component.  The design of the fixture can use other OO patterns to keep it neat.  For instance I once built a set of fixtures to supply ready made folder and file structures.  They all extended an abstract and implemented an interface.  The @Qualifier annotation was used to inject the correct implementation into the test.  On occasion a test used two of the component implementations.</ol>
<h3>Refactoring steps:</h3>
<ul>
<li>Move the Fixture inner class to its own component class.  If you get many of these its worth putting them in a separate project.</li>
<li>Add the @Component annotation from the spring project.</li>
<li>Change the type giving a more descriptive name.</li>
<li>Make the methods in the fixture public.</li>
<li>Better names for methods and types now that the fixture is not near the code that uses it.</li>
<li>Java doc for important methods.</li>
<li>Addition of getters for fields instead of direct access.</li>
<li>Improved createLineExpectations(int numLinesToCreate) by removing the dataItem, the fixture knows this data so no need to supply via method.</li>
<li>Convert to spring test. This means its possible to load in the spring configuration and autowire the test</li>
</ul>
<p>The test class markup to convert it into a spring test, and provide amongst other things auto wiring:</p>
<pre class="brush: java; light: true">
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:springAppConfig.xml")
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
public class SpringWiredSimplePageTest {
</pre>
<p>Autowire the fixture, and spring will inject it:</p>
<pre class="brush: java; light: true">
@Autowired
    private PageDataFixture dataFixture;
</pre>
<p>Your test setup is then just called like this:</p>
<pre class="brush: java; light: true">
Map&lt;Integer, String&gt; expectedLines = dataFixture.createPageExpectation(NUMBER_LINES_ON_PAGE_4, NUMBER_DATA_ITEMS_IN_LINE_5);
</pre>
<h2>Conclusions</h2>
<p>Once you have a test that gives 100% coverage, there is usually some more time that needs to be spent on cleaning the code.  There are some easy patterns that can help, there is nothing in this article that is complex or difficult to understand so there is no excuse for leaving it messy.  Bugs hide in messy code and I think you would agree, the final result is very easy to read:<a href="http://github.com/mhgit/TerribleJavaTestingMadeGood/blob/master/testing-made-good/src/test/java/org/testpatterns/dupcodeexample/lineutil/unit/SpringWiredSimplePageTest.java" TARGET="_blank">SpringWiredSimplePageTest</a></p>
<h3>Thanks to&#8230;</h3>
<p>All the people I have worked with over the years, who have shown me better ways to write and test code.  You know who you are.  Many thanks.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F&amp;title=Test+anti-patterns+project%2C+contributors+wanted%21" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F&amp;title=Test+anti-patterns+project%2C+contributors+wanted%21" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F&amp;title=Test+anti-patterns+project%2C+contributors+wanted%21" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F&amp;headline=Test+anti-patterns+project%2C+contributors+wanted%21" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Test+anti-patterns+project%2C+contributors+wanted%21&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Test+anti-patterns+project%2C+contributors+wanted%21&amp;u=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Test+anti-patterns+project%2C+contributors+wanted%21&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Test+anti-patterns+project%2C+contributors+wanted%21&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Test+anti-patterns+project%2C+contributors+wanted%21&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F&amp;title=Test+anti-patterns+project%2C+contributors+wanted%21&amp;summary=&amp;source=" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F11%2Fanti-patterns-testing%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><div class="dzone_button" style="float: right; margin-left: 5px;">
<script type="text/javascript">
var dzone_url = 'http://martinaharris.com/2009/11/anti-patterns-testing/';
var dzone_title = 'Test anti-patterns project, contributors wanted!';
var dzone_blurb = '';
var dzone_style = '2';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div>]]></content:encoded>
			<wfw:commentRss>http://martinaharris.com/2009/11/anti-patterns-testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Neat multiset in google collections API</title>
		<link>http://martinaharris.com/2009/10/neat-multiset-in-google-collections-api/</link>
		<comments>http://martinaharris.com/2009/10/neat-multiset-in-google-collections-api/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 00:14:27 +0000</pubDate>
		<dc:creator>Martin Harris</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[software quality]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[collections]]></category>
		<category><![CDATA[equals]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[quality]]></category>
		<category><![CDATA[thread]]></category>

		<guid isPermaLink="false">http://martinaharris.com/?p=113</guid>
		<description><![CDATA[This good thing was so small that I almost did not bother to blog it But the devil is in the detail so here it is anyway. I have this multi threaded application. One of the problems with integration testing &#8230; <a href="http://martinaharris.com/2009/10/neat-multiset-in-google-collections-api/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h3>This good thing was so small that I almost did not bother to blog it</h3>
<p><cite>But the devil is in the detail</cite> so here it is anyway.</p>
<p>I have this multi threaded application.  One of the problems with integration testing it is, you can&#8217;t guarantee the order that messages will be written to a stream.  So during the test I have to go to some trouble to split and order the lines written out.  If I don&#8217;t do this the test fails sometimes. It depends on which thread writes first. The output though is correct, order is not important.  Not exactly rocket science.</p>
<p>Here is the method I was using to massage the string.</p>
<pre class="brush: java; gutter: false; wrap-lines: false">
 public List&lt;String&gt; getSortedLines(String expectedString) {

        String[] splitExpectedResultLines = expectedString.toString().split("\n");
        List&lt;String&gt; resultLines = new ArrayList&lt;String&gt;();
        for (String messageLine : resultLines) {
            resultLines.add(messageLine);
        }

        Collections.sort(resultLines);
        return resultLines;
    }
</pre>
<p>There is nothing particularly wrong with the method.  It takes a string, splits it into lines, loads a List, sorts and returns it.  Thus when its used in an assertion later the expected and actual lists are the same.</p>
<p>With google collections its just three lines!  The HashMultiset is designed to be used in equals methods.  Its equal even if the order of the elements in collections being compared is different.  From the API documentation: <cite>An extension of Collection that may contain duplicate values like a List, yet has order-independent equality like a Set. One typical use for a multiset is to represent a histogram.</cite> </p>
<p>Its possible to use the HashMultiSet.create static factory method, passing in an Iterable.  i.e a Collection.  So from the original code, both the loop and the Collections.sort are no longer required.</p>
<pre class="brush: java; gutter: false; wrap-lines: false; highlight: 6">
   public HashMultiset&lt;String&gt; getOrderAgnosticCollection(String expectedString) {

        String[] splitExpectedResultLines = expectedString.toString().split("\n");
        Iterable&lt;String&gt; resultLines = Arrays.asList(splitExpectedResultLines);
        HashMultiset&lt;String&gt; orderAgnosticResultLines =
                                              HashMultiset.create(resultLines);

        return orderAgnosticResultLines;
    }
</pre>
<p>If there was something that performed the split, but returned an Iterable the method would be perfect!  <img src='http://martinaharris.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F&amp;title=Neat+multiset+in+google+collections+API" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F&amp;title=Neat+multiset+in+google+collections+API" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F&amp;title=Neat+multiset+in+google+collections+API" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F&amp;headline=Neat+multiset+in+google+collections+API" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Neat+multiset+in+google+collections+API&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Neat+multiset+in+google+collections+API&amp;u=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Neat+multiset+in+google+collections+API&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Neat+multiset+in+google+collections+API&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Neat+multiset+in+google+collections+API&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F&amp;title=Neat+multiset+in+google+collections+API&amp;summary=&amp;source=" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fneat-multiset-in-google-collections-api%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><div class="dzone_button" style="float: right; margin-left: 5px;">
<script type="text/javascript">
var dzone_url = 'http://martinaharris.com/2009/10/neat-multiset-in-google-collections-api/';
var dzone_title = 'Neat multiset in google collections API';
var dzone_blurb = '';
var dzone_style = '2';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div>]]></content:encoded>
			<wfw:commentRss>http://martinaharris.com/2009/10/neat-multiset-in-google-collections-api/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Testing java equals and hashcode methods</title>
		<link>http://martinaharris.com/2009/10/testing-java-equals-and-hashcode-methods-essential/</link>
		<comments>http://martinaharris.com/2009/10/testing-java-equals-and-hashcode-methods-essential/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 21:44:35 +0000</pubDate>
		<dc:creator>Martin Harris</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[software quality]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[equals]]></category>
		<category><![CDATA[hashcode]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[quality]]></category>

		<guid isPermaLink="false">http://www.koitok.net/?p=27</guid>
		<description><![CDATA[Equals and hashcode bugs can be difficult to track down.  So why not test them?  This blog shows how easy it is to code some tests <a href="http://martinaharris.com/2009/10/testing-java-equals-and-hashcode-methods-essential/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h3>Write a java test for the equals method!  What is the point in wasting time on that?</h3>
<p>All good java programmers know the equals and hashcode methods are vitally important.  I have seen some unpredictable behavior through bugs in these two methods.</p>
<p>If your about to click away to something more interesting fine, but first read my page with an <a href="http://www.koitok.net/2009/10/ide-generation-of-equals-methods-has-its-moments/">example equals bug</a>.  See if you can spot the problem before I show the solution.</p>
<h4>Writing a test for the equals method</h4>
<p>Writing a test for equals is so easy its tedious.  Which is perhaps why so much code gets written and not tested.  First from the javadoc what are the specifications for a good equals and hashcode implementations?</p>
<p><span id="more-27"></span></p>
<p><strong><cite>Suns javadoc for the equals method</cite></strong></p>
<ul>
<li>It is reflexive: for any non-null reference value x, x.equals(x) should return true.</li>
<li>It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.</li>
<li>It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.</li>
<li>It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.</li>
<li>For any non-null reference value x, x.equals(null) should return false.</li>
</ul>
<p><strong><cite>Suns javadoc for the hashcode method</cite></strong></p>
<ul>
<li>Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.</li>
<li>If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.</li>
<li>It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.</li>
<h4>Simple implementations for equals and hashcode</h4>
<p>These two implementations were built using the generator in netbeans.  Arguably some further optimisation could be done, especially if the class were made fully immutable.  They are fine for the purpose of this blog.</p>
<pre class="brush: java; gutter: false; wrap-lines: false">
public final class SimpleBean {
    private Integer goodInt = 0;

    public SimpleBean(final Integer goodInt) {
        this.goodInt = goodInt;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final SimpleBean other = (SimpleBean) obj;
        if (this.goodInt != other.goodInt
            &amp;&amp; (this.goodInt == null
                                || !this.goodInt.equals(other.goodInt))) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 41 * hash + (this.goodInt != null ? this.goodInt.hashCode() : 0);
        return hash;
    }
}</pre>
<h4>Test class for SimpleBean just showing the equals and hashcode tests</h4>
<pre class="brush: java; gutter: false;wrap-lines: false">
import org.junit.Test;
import static org.junit.Assert.*;

public class TestSimpleBean {

    static final class Fixture {

        static SimpleBean x = new SimpleBean(new Integer(100));
        static SimpleBean y = new SimpleBean(new Integer(100));
        static SimpleBean z = new SimpleBean(new Integer(100));
        static SimpleBean notx = new SimpleBean(new Integer(1));
    }

    @Test
    /**
     * A class is equal to itself.
     */
    public void testEqual_ToSelf() {

        assertTrue("Class equal to itself.", Fixture.x.equals(Fixture.x));
    }

    /**
     * x.equals(WrongType) must return false;
     *
     */
    @Test
    public void testPassIncompatibleType_isFalse() {
        assertFalse("Passing incompatible object to equals should return false", Fixture.x.equals("string"));
    }

    /**
     * x.equals(null) must return false;
     *
     */
    @Test
    public void testNullReference_isFalse() {
        assertFalse("Passing null to equals should return false", Fixture.x.equals(null));
    }

    /**
     * 1. x, x.equals(x) must return true.
     * 2. x and y, x.equals(y) must return true if and only if y.equals(x) returns true.
     */
    @Test
    public void testEquals_isReflexive_isSymmetric() {

        assertTrue("Reflexive test fail x,y", Fixture.x.equals(Fixture.y));
        assertTrue("Symmetric test fail y", Fixture.y.equals(Fixture.x));

    }

    /**
     * 1. x.equals(y) returns true
     * 2. y.equals(z) returns true
     * 3. x.equals(z) must return true
     */
    @Test
    public void testEquals_isTransitive() {

        assertTrue("Transitive test fails x,y", Fixture.x.equals(Fixture.y));
        assertTrue("Transitive test fails y,z", Fixture.y.equals(Fixture.z));
        assertTrue("Transitive test fails x,z", Fixture.x.equals(Fixture.z));
    }

    /**
     * Repeated calls to equals consistently return true or false.
     */
    @Test
    public void testEquals_isConsistent() {

        assertTrue("Consistent test fail x,y", Fixture.x.equals(Fixture.y));
        assertTrue("Consistent test fail x,y", Fixture.x.equals(Fixture.y));
        assertTrue("Consistent test fail x,y", Fixture.x.equals(Fixture.y));
        assertFalse(Fixture.notx.equals(Fixture.x));
        assertFalse(Fixture.notx.equals(Fixture.x));
        assertFalse(Fixture.notx.equals(Fixture.x));

    }

    /**
     * Repeated calls to hashcode should consistently return the same integer.
     */
    @Test
    public void testHashcode_isConsistent() {

        int initial_hashcode = Fixture.x.hashCode();

        assertEquals("Consistent hashcode test fails", initial_hashcode, Fixture.x.hashCode());
        assertEquals("Consistent hashcode test fails", initial_hashcode, Fixture.x.hashCode());
    }

    /**
     * Objects that are equal using the equals method should return the same integer.
     */
    @Test
    public void testHashcode_twoEqualsObjects_produceSameNumber() {

        int xhashcode = Fixture.x.hashCode();
        int yhashcode = Fixture.y.hashCode();

        assertEquals("Equal object, return equal hashcode test fails", xhashcode, yhashcode);
    }

    /**
     * A more optimal implementation of hashcode ensures
     * that if the objects are unequal different integers are produced.
     *
     */
    @Test
    public void testHashcode_twoUnEqualObjects_produceDifferentNumber() {

        int xhashcode = Fixture.x.hashCode();
        int yhashcode = Fixture.notx.hashCode();

        assertTrue("Equal object, return unequal hashcode test fails", !(xhashcode == yhashcode));
    }
}</pre>
<h3>Conclusions</h3>
<p>To me the benefit is clear.  Its very easy to break these two methods.  Converting one of the attribute types can easily break equals and possibly hashcode.  Its essential to have a test in place to prevent the bug going unnoticed.</ul>
<h3>Note on nulls</h3>
<p>In some cases extra tests may be required for null checking on both sides.  For instance in the case where an object relies upon an inner class to provide it a key, and its possible for this key to be null.:</p>
<pre class="brush: java; gutter: false;wrap-lines: false">
   /**
     * x.key = null, y.key = null, must return false.
     */
    @Test
    public void testKeysNull_NotEqual() {

        Thing noKeyAvailableA = new Thing();
        Thing noKeyAvailableB = new Thing ();
        assertFalse(noKeyAvailableA.equals(noKeyAvailableB));
    }

    /**
     * x.key= null, y.key != null, must return false.
     */
    @Test
    public void testKeyNearsideNullFarsideNotNull_NotEqual() {
        Fixture fixture = new Fixture();
        Thing noKeyAvailable = new Thing ();
        assertFalse(noKeyAvailable.equals(fixture.x));
    }

    /**
     * y.key = null, x.key != null, must return false.
     */
    @Test
    public void testKeyFarsideNotNullFarsideNull_NotEqual() {
        Fixture fixture = new Fixture();
        Thing noKeyAvailable = new Thing ();
        assertFalse(fixture.x.equals(noKeyAvailable));
    }
</pre>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F&amp;title=Testing+java+equals+and+hashcode+methods" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F&amp;title=Testing+java+equals+and+hashcode+methods" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F&amp;title=Testing+java+equals+and+hashcode+methods" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F&amp;headline=Testing+java+equals+and+hashcode+methods" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Testing+java+equals+and+hashcode+methods&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Testing+java+equals+and+hashcode+methods&amp;u=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Testing+java+equals+and+hashcode+methods&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Testing+java+equals+and+hashcode+methods&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Testing+java+equals+and+hashcode+methods&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F&amp;title=Testing+java+equals+and+hashcode+methods&amp;summary=&amp;source=" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Ftesting-java-equals-and-hashcode-methods-essential%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><div class="dzone_button" style="float: right; margin-left: 5px;">
<script type="text/javascript">
var dzone_url = 'http://martinaharris.com/2009/10/testing-java-equals-and-hashcode-methods-essential/';
var dzone_title = 'Testing java equals and hashcode methods';
var dzone_blurb = '';
var dzone_style = '2';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div>]]></content:encoded>
			<wfw:commentRss>http://martinaharris.com/2009/10/testing-java-equals-and-hashcode-methods-essential/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IDE Generation of equals methods has its moments</title>
		<link>http://martinaharris.com/2009/10/ide-generation-of-equals-methods-has-its-moments/</link>
		<comments>http://martinaharris.com/2009/10/ide-generation-of-equals-methods-has-its-moments/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 21:26:29 +0000</pubDate>
		<dc:creator>Martin Harris</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[software quality]]></category>
		<category><![CDATA[compareto]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[equals]]></category>
		<category><![CDATA[generation]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[netbeans]]></category>
		<category><![CDATA[quality]]></category>

		<guid isPermaLink="false">http://www.koitok.net/2009/10/ide-generation-of-equals-methods-has-its-moments/</guid>
		<description><![CDATA[This blog entry looks at the code generated by Eclipse and Netbeans and demonstrates why its a good idea to both test the code and review it thoroughly. <a href="http://martinaharris.com/2009/10/ide-generation-of-equals-methods-has-its-moments/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h3>Generating java bugs in equals methods using an IDE</h3>
<p>Its no revelation that Eclipse, Netbeans and others can generate code.  Its particularly useful if getters, setters or constructors are required.  Implementing an interface is very simple indeed as these IDE will stub out the interface methods.  More complex methods though require some thought.  Generation of the equals method is such a case.</p>
<p>How to write a good equals method is well documented by Joshua Bloch in <a href="http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1254412228&#038;sr=8-1" target="_blank">Effective Java, Chapter 3 by Joshua Bloch</a>.</p>
<h3>Eclipse V Netbeans who generates the best code?</h3>
<p>Before we get deeper into the code here are two efforts at generating the equals method for this class:</p>
<pre class="brush: java; gutter: false;">
public class SimpleBean  {
    private final BigDecimal bigDecimal;
    public SimpleBean(BigDecimal bigDecimal) {
        this.bigDecimal = bigDecimal;
    }
}
</pre>
<p><span id="more-19"></span></p>
<p>The results for even such a simple class are interesting.</p>
<p><strong>Netbeans</strong></p>
<pre class="brush: java; gutter: false;highlight: 6">
      @Override
      public boolean equals(Object obj) {
          if (obj == null) {
              return false;
          }
          if (getClass() != obj.getClass()) {
              return false;
          }
          final SimpleBean other = (SimpleBean) obj;
          if (this.bigDecimal != other.bigDecimal &#038;&#038;
                (this.bigDecimal == null ||
                !this.bigDecimal.equals(other.bigDecimal))) {
              return false;
          }
          return true;
     }
</pre>
<p>The Netbeans attempt is reasonable at first sight.  Even with the above there are a few observations and a bug which I will come to later on.  Can you spot it?</p>
<ul>
<li>The <strong>getClass</strong> system for checking that our object can be tested for equality is a little inflexible.  For classes that implement a common interface its nice to be able to compare across implementations.  This is often done using the <strong>if (!(obj instanceof MyType))</strong> check.  GetClass is optimal, but it would be good to have an option in the generation.</li>
<li>The style of the value check is a little compressed for some tastes.</li>
</ul>
<p><strong>Eclipse</strong></p>
<pre class="brush: java; gutter: false;highlight: 7">
  @Override
  public boolean equals(Object obj) {
      if (this == obj)
	  return true;
      if (obj == null)
	  return false;
      if (getClass() != obj.getClass())
          return false;
      SimpleBean other = (SimpleBean) obj;
      if (bigDecimal == null) {
        if (other.bigDecimal != null)
          return false;
       } else if (!bigDecimal.equals(other.bigDecimal))
          return false;
       return true;
}
</pre>
<p>Eclipse generates very similar code.  The bug is still there though, can you see it yet?</p>
<ul>
<li>Eclipse has extra options.  You can switch out that <strong>getClass</strong> for the more flexible <strong>instanceof</strong> check.</li>
<li>The style above is better and can be improved with the introduction of blocks on all if statements.</li>
<li>Eclipse does more optimization assuming that more often than not an object is passed in. </li>
</ul>
<h3>Neither are good! The generated equals bug exposed!</h3>
<p>It should be clear when I write a test that will fail for either of the above implementations.</p>
<pre class="brush: java; gutter: false; wrap-lines: false">
@Test
    public void testObjectInconsistantWithEquals_Equals() {
        SimpleBean testSimpleBean = new SimpleBean(new BigDecimal("0"));
        SimpleBean expectedEqualSimpleBean = new SimpleBean(new BigDecimal("0.0"));
        assertTrue("Equality Test Fail", testSimpleBean.equals(expectedEqualSimpleBean));
    }
}
</pre>
<p>The above test fails because BigDecimal has an equals implementation that will return false when it checks <strong>100</strong> against <strong>100.00</strong>.  Its implementation of the compare method is declared as being inconsistent with equals.  This in itself is interesting but for this example it means we can modify the generated code to provide a fix using <strong>this.bigDecimal.compareTo(other.bigDecimal) != 0</strong> instead of relying on the generated use of equals.</p>
<h3>Recommendations</h3>
<p>In light of the above I would suggest the following points.</p>
<ul>
<li>Apart from primitive and well known objects generated equals methods can be very bad indeed.</li>
<li>Always write a test for equals, do not rely on an IDE.</li>
<li>If you change your object, remember to re-visit the equals method.</li>
</ul>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F&amp;title=IDE+Generation+of+equals+methods+has+its+moments" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F&amp;title=IDE+Generation+of+equals+methods+has+its+moments" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F&amp;title=IDE+Generation+of+equals+methods+has+its+moments" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F&amp;headline=IDE+Generation+of+equals+methods+has+its+moments" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=IDE+Generation+of+equals+methods+has+its+moments&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=IDE+Generation+of+equals+methods+has+its+moments&amp;u=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=IDE+Generation+of+equals+methods+has+its+moments&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=IDE+Generation+of+equals+methods+has+its+moments&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=IDE+Generation+of+equals+methods+has+its+moments&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F&amp;title=IDE+Generation+of+equals+methods+has+its+moments&amp;summary=&amp;source=" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fmartinaharris.com%2F2009%2F10%2Fide-generation-of-equals-methods-has-its-moments%2F" target="_blank"><img class="lightsocial_img" src="http://martinaharris.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div><div class="dzone_button" style="float: right; margin-left: 5px;">
<script type="text/javascript">
var dzone_url = 'http://martinaharris.com/2009/10/ide-generation-of-equals-methods-has-its-moments/';
var dzone_title = 'IDE Generation of equals methods has its moments';
var dzone_blurb = '';
var dzone_style = '2';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div>]]></content:encoded>
			<wfw:commentRss>http://martinaharris.com/2009/10/ide-generation-of-equals-methods-has-its-moments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

