<?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>Musings&#60;Biefeld&#62; &#187; Refactoring</title>
	<atom:link href="http://sbiefeld.com/category/refactoring/feed/" rel="self" type="application/rss+xml" />
	<link>http://sbiefeld.com</link>
	<description>- curiosities of development, life, the universe and everything -</description>
	<lastBuildDate>Tue, 02 Feb 2010 04:32:48 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Identifying NHibernate Refactoring Points &#8211; Utilizing DRY</title>
		<link>http://sbiefeld.com/2009/02/11/identifying-nhibernate-refactoring-points-utilizing-dry/</link>
		<comments>http://sbiefeld.com/2009/02/11/identifying-nhibernate-refactoring-points-utilizing-dry/#comments</comments>
		<pubDate>Wed, 11 Feb 2009 06:50:38 +0000</pubDate>
		<dc:creator>Sean Biefeld</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[Refactoring]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[DRY]]></category>
		<category><![CDATA[Single Responsibility Principle]]></category>

		<guid isPermaLink="false">http://sbiefeld.com/?p=81</guid>
		<description><![CDATA[Today when preparing for our code review I happened upon a few methods in our base repository. Those methods were using NHibernate to retrieve collections of objects from persistence.  I started scanning over the methods and figuring out what they were trying to accomplish.  After understanding their function I noticed that they were [...]]]></description>
			<content:encoded><![CDATA[<p>Today when preparing for our code review I happened upon a few methods in our base repository. Those methods were using NHibernate to retrieve collections of objects from persistence.  I started scanning over the methods and figuring out what they were trying to accomplish.  After understanding their function I noticed that they were prime candidates for a refactoring.</p>
<p>The methods were:</p>
<pre><span class="keyword">public</span> <span class="keyword">virtual</span> <span class="class">IList</span>&lt;Entity&gt; GetAll()
{
	<span class="keyword">return</span> Session.CreateCriteria(<span class="keyword">typeof</span> (Entity)).List&lt;Entity&gt;();
}

<span class="keyword">public</span> <span class="keyword">virtual</span> <span class="class">IList</span>&lt;Entity&gt; GetActiveItems()
{
	<span class="class">ICriteria</span> criteria = Session
		.CreateCriteria(<span class="keyword">typeof</span>(Entity))
		.Add(<span class="class">Restrictions</span>.IsNull(<span class="string">"InactiveDate"</span>));

	<span class="keyword">return</span> criteria.List&lt;Entity&gt;();
}

<span class="keyword">public</span> <span class="keyword">virtual</span> <span class="class">IList</span>&lt;Entity&gt; GetItemsLikeName(<span class="keyword">string</span> name, <span class="keyword">string</span> columnToCompareBy)
{
	<span class="class">ICriteria</span> criteria = Session.CreateCriteria(<span class="keyword">typeof</span>(Entity))
		.Add(<span class="class">Restrictions</span>.IsNull(<span class="string">"InactiveDate"</span>))
		.Add(<span class="class">Restrictions</span>.Like(columnToCompareBy, name, <span class="class">MatchMode</span>.Start).IgnoreCase());

	<span class="keyword">return</span> criteria.List&lt;Entity&gt;();
}
</pre>
<h3>Analysis:</h3>
<p>Now the first thing that tipped me off to the need for Refactoring was the <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself" target="_blank">DRY</a> (Don&#8217;t pete and repete yourself) principle, which can be extrapolated into Attwood&#8217;s <a href="http://www.codinghorror.com/blog/archives/000805.html" target="_blank">Curly&#8217;s Law</a> and even further to the <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle" target="_blank">Single Responsibility Principle</a>.  At least, I thinks DRY&#8217;s a principle, maybe it&#8217;s classified as a technique, or to be more in tune with coding hype a <a href="http://www.codinghorror.com/blog/archives/000589.html" target="_blank">code smell</a>. Lol, code smells, it may work if compared to flatulence but if you compare it to cheese, the more pungent the odor, the better the cheese.  Actually it has more to do with identifying different smells so that you know what needs to be refactored or reworked entirely. Anyway, they all pretty much are talking about the same thing, minimizing duplicate code/rules/processes.</p>
<h3>The Break Down:</h3>
<p>The first thing I noticed was the responsibility of all the methods, they are responsible for retrieving a collection of objects. I observed this by the methods&#8217; return types of <span class="class">IList</span>&lt;Entity&gt; and their names, <i>GetAll(), GetActiveItems(),GetItemsLikeName()</i>.</p>
<p>Next all of the methods are following the same basic pattern(process) of creating an <span class="class">ICriteria</span> object, setting the specified <span class="class">ICriterion</span>(where my object equals some value) on that ICriteria and finally executing the retrieval of the matching objects.  The following is some psuedo code of that pattern(process)</p>
<pre><span class="class">ICriteria</span> criteria = Session.CreateCriteria(<span class="keyword">typeof</span>(Entity))
		.Add(<span class="class">ICriterion</span>)
<span class="keyword">return</span> criteria.RetrieveMatchingObjects&lt;Entity&gt;;
</pre>
<h3>The Refactor:</h3>
<p>Now we know the reponsibility and the process of all three methods. From this knowledge we can refactor those methods to use one method, but we will want to keep the signatures of each method, because they still have a separate responsibility as well.  Let&#8217;s see the common concern is collection retrieval through different criteria. To address handling the different criteria we can utilize c#&#8217;s keyword <a href="http://msdn.microsoft.com/en-us/library/w5zay9db.aspx" target="_blank"><span class="keyword">params</span></a> to pass in a variable number of criterion. Now, our combined method signature should look like:</p>
<pre><span class="keyword">protected</span> <span class="keyword">virtual</span> <span class="class">IList</span>&lt;Entity&gt; GetAllItems(<span class="keyword">params</span> <span class="keyword">ICriterion</span>[] criterion)</pre>
<p>Our refactored method is ready to return a collection of objects and to accept n number of ICriterion.</p>
<p>Next we need to create our <span class="class">ICriteria</span> creation:</p>
<pre><span class="class">ICriteria</span> getCriteria = Session.CreateCriteria(<span class="keyword">typeof</span>(Entity));</pre>
<p>After that it&#8217;s on to handling our array of <span class="class">ICriterion</span>:</p>
<pre><span class="keyword">if</span> (criterion != <span class="keyword">null</span>)
{
	<span class="keyword">foreach</span> (<span class="keyword">var</span> criteria <span class="keyword">in</span> criterion)
	{
		getCriteria.Add(criteria);
	}
}
</pre>
<p>First we need to check if the array is null, it is always good to check for null before trying to loop through an <span class="class">IEnumrable</span>. Once we are sure that the array is not null we can loop through that bad boy and add the criterion to our <span class="class">ICriteria</span> object. At this point we can execute our query, I prefer burning at the stake, but it&#8217;s up to you. Anyway our retrieval and return will (survey says) look like:</p>
<pre><span class="class">IList</span>&lt;Entity&gt; result = getCriteria.List&lt;Entity&gt;();</pre>
<p>Next on the proverbial platter, both the <i>GetActiveItems()</i> and <i>GetItemsLikeName()</i> methods are using the same criteria in their queries, the null check of Inactive Date. Ah ha, another point to refactor, stop the repetition. Let&#8217;s create a read only<span class="class">ICriterion</span> property named <i>WhereInactiveDateIsNull</i>, remember <a href="http://www.hanselman.com/blog/TheWeeklySourceCode14FluentInterfaceEdition.aspx" target="_blank">fluent interfaces</a> are your friend. If the name is unclear now, it may make more sense in a bit, so chill.</p>
<pre><span class="keyword">protected</span> <span class="keyword">virtual</span> <span class="class">ICriterion</span> WhereInactiveDateIsNull
{
	<span class="keyword">get</span>
	{
		<span class="keyword">return</span> <span class="class">Restrictions</span>.IsNull(<span class="string">"InactiveDate"</span>);
	}
}</pre>
<p>Alright so we now have our one method to rule them all, or at least the three methods we were looking at before.</p>
<h3>The Result:</h3>
<p>So now all of our methods are going to call the method we created and tell that method their own specific responsibilites through the criterion they pass in.</p>
<pre><span class="keyword">protected</span> <span class="keyword">virtual</span> <span class="class">ICriterion</span> WhereInactiveDateIsNull
{
	<span class="keyword">get</span>
	{
		<span class="keyword">return</span> <span class="class">Restrictions</span>.IsNull(<span class="string">"InactiveDate"</span>);
	}
}

<span class="keyword">protected</span> <span class="keyword">virtual</span> <span class="class">IList</span>&lt;Entity&gt; GetAllItems(<span class="keyword">params</span> <span class="class">ICriterion</span>[] criterion)
{
	<span class="class">ICriteria</span> getCriteria = Session.CreateCriteria(<span class="keyword">typeof</span>(Entity));

	<span class="keyword">if</span> (criterion != <span class="keyword">null</span>)
	{
		<span class="keyword">foreach</span> (<span class="keyword">var</span> criteria <span class="keyword">in</span> criterion)
		{
			getCriteria.Add(criteria);
		}
	}

	<span class="keyword">return</span> getCriteria.List&lt;Entity&gt;();
}

<span class="keyword">public</span> <span class="keyword">virtual</span> <span class="class">IList</span>&lt;Entity&gt; GetAll()
{
	<span class="keyword">return</span> GetAllItems();
}

<span class="keyword">public</span> <span class="keyword">virtual</span> <span class="class">IList</span>&lt;Entity&gt; GetActiveItems()
{
	<span class="keyword">return</span> GetAllItems(WhereInactiveDateIsNull);
}

<span class="keyword">public</span> <span class="keyword">virtual</span> <span class="class">IList</span>&lt;Entity&gt; GetItemsLikeName(<span class="keyword">string</span> name, <span class="keyword">string</span> columnToCompareBy)
{
	<span class="class">ICriterion</span> whereColumnValueStartsWithNameIgnoringCase
		= <span class="class">Restrictions</span>.Like(columnToCompareBy, name, <span class="class">MatchMode</span>.Start).IgnoreCase();

       	<span class="keyword">return</span> GetAllItems
	(
		WhereInactiveDateIsNull,
		whereColumnValueStartsWithNameIgnoringCase
	);
}
</pre>
<h3>The Interlude:</h3>
<blockquote><p>&#8220;Oh, this little guy? I wouldn&#8217;t worry about this little guy.&#8221;</p></blockquote>
<p><br/>
<p>That just popped into my head, I must be astral projecting again. Seriously, if you don&#8217;t know what that quote is from, you fail at life, nah, just joking, <a href="http://en.wikiquote.org/wiki/Super_Troopers" target="_blank">look it up</a>. Hmm, it must be late, my mind is wandering. Blogging and jamming. Jamming, is that still a socially acceptable term? Jamming to <a href="http://en.wikipedia.org/wiki/The_Tangent" target="_blank">The Tangent</a>, great stuff.</p>
<h3>The Conclusion:</h3>
<p>Ah, the fruits of our labor are so sweet. Remember, I know it&#8217;s hard, but remmember when I was speaking of the fluent interface, ah now you remember. Excellent, so if we take a look at our new <i>GetItemsLikeName()</i> method we can see the fluency at work;</p>
<blockquote><p> we want to <i>GetAllItems(WhereInactiveDateIsNull,(and) whereColumnValueStartsWithNameIgnoringCase)</i>.</p></blockquote>
<p><br/>
<p> If you can&#8217;t glean what this is doing from the naming, I am sorry, but there is no hope for you, <img src='http://sbiefeld.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . This fluent interface does several things, it decreases the learning curve for new-comers, increases the readability of our code, and overall increases the maintainability.</p>
<p>I find that the best thing to do is try to contemplate the Single Responsiblity Principle, Dont Repeat Yourself Principle, or other sundry names for it; when you are satisfying your broken tests, assuming you are testing first. I know that sometimes it can be hard but it is a fracking awesome practice to achieve. Even if you can&#8217;t see the common responsibilities at first, definitely try to find them after your tests pass. Red, Green, Refactor.</p>
<p><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://sbiefeld.com/2009/02/11/identifying-nhibernate-refactoring-points-utilizing-dry/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
