<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en" xml:base="http://solnic.eu/wp-atom.php">
	<title type="text">solnic.eu</title>
	<subtitle type="text">probably the best tagline in the world</subtitle>

	<updated>2012-05-12T11:14:05Z</updated>

	<link rel="alternate" type="text/html" href="http://solnic.eu" />
	<id>http://solnic.eu/feed/atom</id>
	

	<generator uri="http://wordpress.org/" version="3.3.2">WordPress</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/solnic-on-blog" /><feedburner:info uri="solnic-on-blog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
		<author>
			<name>solnic</name>
						<uri>http://solnic.eu</uri>
					</author>
		<title type="html"><![CDATA[Get Rid of That Code Smell – Duplication]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/solnic-on-blog/~3/sU-BNoAWb5Y/get-rid-of-that-code-smell-duplication.html" />
		<id>http://solnic.eu/?p=282</id>
		<updated>2012-05-12T11:14:05Z</updated>
		<published>2012-05-11T17:34:46Z</published>
		<category scheme="http://solnic.eu" term="Blog" /><category scheme="http://solnic.eu" term="metrics" /><category scheme="http://solnic.eu" term="oop" /><category scheme="http://solnic.eu" term="refactoring" /><category scheme="http://solnic.eu" term="ruby" />		<summary type="html"><![CDATA[This is a post from the Get Rid of That Code Smell series. Removing duplication from the code is a seemingly easy task. In many cases it is pretty straight-forward &#8211; you look at similar bits of code and you &#8230;<p class="read-more"><a href="http://solnic.eu/2012/05/11/get-rid-of-that-code-smell-duplication.html">Read more &#187;</a></p>]]></summary>
		<content type="html" xml:base="http://solnic.eu/2012/05/11/get-rid-of-that-code-smell-duplication.html">&lt;p&gt;This is a post from the &lt;a title="Get Rid of That Code Smell" href="http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html" target="_blank"&gt;Get Rid of That Code Smell&lt;/a&gt; series.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Removing duplication from the code is a seemingly easy task. In many cases it is pretty straight-forward &amp;#8211; you look at similar bits of code and you move them to a common method or class that is reusable in other places. Right? No, not really. It is true that code that looks similar might be an indicator that there&amp;#8217;s a duplication but it&amp;#8217;s not the definitive way of determining the smell.&lt;/p&gt;
&lt;p&gt;If we look for duplication in our code we should look for duplicated &lt;strong&gt;concepts&lt;/strong&gt; instead of similarly looking lines of code. Here I want to remind you the short definition of DRY principle that I&amp;#8217;m sure most rubyists are familiar with:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.&lt;/p&gt;
&lt;footer&gt;
  &lt;strong&gt;Andrew Hunt and David Thomas&lt;/strong&gt;&lt;br /&gt;
  &lt;cite&gt;&lt;br /&gt;
    &lt;a href="http://pragprog.com/the-pragmatic-programmer"&gt;The Pragmatic Programmer&lt;/a&gt;&lt;br /&gt;
  &lt;/cite&gt;&lt;br /&gt;
&lt;/footer&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is a fantastic presentation by David Chelimsky from RubyConf 2010 titled &amp;#8220;Maintaining Balance While Reducing Duplication&amp;#8221;. If you missed it you should definitely check it out. There&amp;#8217;s a beautiful quote in this talk:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
DRY does not mean “don’t type the same characters twice”&lt;/p&gt;
&lt;footer&gt;
  &lt;strong&gt;David Chelimsky&lt;/strong&gt;&lt;br /&gt;
  &lt;cite&gt;&lt;br /&gt;
    &lt;a href="http://www.confreaks.com/videos/434-rubyconf2010-maintaining-balance-while-reducing-duplication"&gt;Maintaining Balance While Reducing Duplication&lt;/a&gt;&lt;br /&gt;
  &lt;/cite&gt;&lt;br /&gt;
&lt;/footer&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Detecting Duplication Smell&lt;/h2&gt;
&lt;p&gt;You can use both &lt;a href="https://github.com/kevinrutherford/reek" title="reek on github" target="_blank"&gt;reek&lt;/a&gt; and &lt;a href="http://ruby.sadi.st/Flay.html" title="Flay" target="_blank"&gt;flay&lt;/a&gt; to aid you with finding duplication in your code but remember that these tools are not smart enough to find similar concepts. Both will find &lt;strong&gt;potential&lt;/strong&gt; duplication but it&amp;#8217;s your job to decide if it makes sense to do anything about it.&lt;/p&gt;
&lt;p&gt;Here is an example from &lt;a href="https://github.com/solnic/virtus" title="virtus on github" target="_blank"&gt;Virtus&lt;/a&gt; project where reducing duplication &lt;strong&gt;wasn&amp;#8217;t&lt;/strong&gt; such a good idea:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603e7b90/]&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Equalizer&lt;/code&gt; module defines a bunch of methods. Internally it has a few private &lt;code&gt;define_*&lt;/code&gt; methods which use &lt;code&gt;@keys&lt;/code&gt; ivar to map it to something else. Now the metric tools complained about all these calls to &lt;code&gt;@keys.map&lt;/code&gt;. It is true, this is a duplicated code but what&amp;#8217;s the risk that it&amp;#8217;s going to change? Very, very small. Is this a duplicated concept in the library? Nope.&lt;/p&gt;
&lt;p&gt;Nevertheless I went ahead and reduced this duplication by introducing a new method so the code looked like that:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603e7bda/]&lt;/p&gt;
&lt;p&gt;Now the metric tools won&amp;#8217;t complain. All the calls to &lt;code&gt;@keys.map&lt;/code&gt; has been replaced with a call to the new &lt;code&gt;compile_keys&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;This refactor did reduce duplication but with the price of &lt;strong&gt;increased complexity&lt;/strong&gt;. I don&amp;#8217;t think it was such a great idea &amp;#8211; the risk that these duplicated calls would have to change was so low that I should&amp;#8217;ve left this code alone despite the little duplication.&lt;/p&gt;
&lt;h2&gt;Removing Duplication&lt;/h2&gt;
&lt;p&gt;Here&amp;#8217;s another example where it actually did make sense to reduce duplication to get cleaner code and better encapsulation:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603e7c22/]&lt;/p&gt;
&lt;p&gt;I think it&amp;#8217;s easy to see duplication here. The duplicated concept is that we want to call a specific method on the value only if it&amp;#8217;s actually available. If it&amp;#8217;s not then we use an alternative String-based coercion.&lt;/p&gt;
&lt;p&gt;This logic was extracted into a new method called &lt;code&gt;coerce_with_method&lt;/code&gt; and the module looked like that:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603e7c66/]&lt;/p&gt;
&lt;p&gt;In fact this turned out to be so common that later on &lt;code&gt;coerce_with_method&lt;/code&gt; was moved to the base &lt;code&gt;Virtus::Coercion::Object&lt;/code&gt; class with a few overridden variations in other coercion sub-classes.&lt;/p&gt;
&lt;h2&gt;Summing Up&lt;/h2&gt;
&lt;p&gt;Reducing duplication should be based on finding similar concepts, not similarly looking code. The metric tools can only point you to potential duplication but you have to determine yourself if it really makes sense to do anything about it. In some cases you can just complicate your code just for the sake of reducing duplication without any real benefits.&lt;/p&gt;
&lt;p&gt;OK! Next episode will be about &amp;#8220;Primitive Obsession&amp;#8221; which is extremely common in Ruby world.&lt;/p&gt;
&lt;p&gt;&lt;a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://solnic.eu/2012/05/11/get-rid-of-that-code-smell-duplication.html" data-text="Get Rid of That Code Smell – Duplication"&gt;&lt;/a&gt;&lt;a class="a2a_button_google_plusone addtoany_special_service" data-href="http://solnic.eu/2012/05/11/get-rid-of-that-code-smell-duplication.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_facebook_like addtoany_special_service" data-href="http://solnic.eu/2012/05/11/get-rid-of-that-code-smell-duplication.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F05%2F11%2Fget-rid-of-that-code-smell-duplication.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Duplication" title="Reddit" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/&gt;&lt;/a&gt;&lt;a class="a2a_button_dzone" href="http://www.addtoany.com/add_to/dzone?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F05%2F11%2Fget-rid-of-that-code-smell-duplication.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Duplication" title="DZone" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/dzone.png" width="16" height="16" alt="DZone"/&gt;&lt;/a&gt;&lt;a class="a2a_button_linkedin" href="http://www.addtoany.com/add_to/linkedin?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F05%2F11%2Fget-rid-of-that-code-smell-duplication.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Duplication" title="LinkedIn" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/linkedin.png" width="16" height="16" alt="LinkedIn"/&gt;&lt;/a&gt;&lt;a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fsolnic.eu%2F2012%2F05%2F11%2Fget-rid-of-that-code-smell-duplication.html&amp;amp;title=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Duplication" id="wpa2a_2"&gt;Share/Bookmark&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/sU-BNoAWb5Y" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://solnic.eu/2012/05/11/get-rid-of-that-code-smell-duplication.html#comments" thr:count="1" />
		<link rel="replies" type="application/atom+xml" href="http://solnic.eu/2012/05/11/get-rid-of-that-code-smell-duplication.html/feed/atom" thr:count="1" />
		<thr:total>1</thr:total>
	<feedburner:origLink>http://solnic.eu/2012/05/11/get-rid-of-that-code-smell-duplication.html</feedburner:origLink></entry>
		<entry>
		<author>
			<name>solnic</name>
						<uri>http://solnic.eu</uri>
					</author>
		<title type="html"><![CDATA[Get Rid of That Code Smell &#8211; Control Couple]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/solnic-on-blog/~3/eH9TZtohKxE/get-rid-of-that-code-smell-control-couple.html" />
		<id>http://solnic.eu/?p=252</id>
		<updated>2012-04-11T14:18:11Z</updated>
		<published>2012-04-11T12:30:08Z</published>
		<category scheme="http://solnic.eu" term="Blog" /><category scheme="http://solnic.eu" term="metrics" /><category scheme="http://solnic.eu" term="oop" /><category scheme="http://solnic.eu" term="refactoring" /><category scheme="http://solnic.eu" term="ruby" /><category scheme="http://solnic.eu" term="srp" />		<summary type="html"><![CDATA[This is a post from the Get Rid of That Code Smell series. If you are serious about Object Oriented Design and respecting Single Responsibility Principle then you definitely want to get rid of Control Couple code smells. In this &#8230;<p class="read-more"><a href="http://solnic.eu/2012/04/11/get-rid-of-that-code-smell-control-couple.html">Read more &#187;</a></p>]]></summary>
		<content type="html" xml:base="http://solnic.eu/2012/04/11/get-rid-of-that-code-smell-control-couple.html">&lt;p&gt;This is a post from the &lt;a href="http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html" title="Get Rid of That Code Smell" target="_blank"&gt;Get Rid of That Code Smell&lt;/a&gt; series.&lt;/p&gt;
&lt;p&gt;If you are serious about Object Oriented Design and respecting Single Responsibility Principle then you definitely want to get rid of Control Couple code smells. In this post I will show you a simple example explaining how to identify and remove control coupling from your code. I like to think about that code smell also in the context of SRP because I like to apply it to every piece of my system &amp;#8211; whether it&amp;#8217;s a method, a class or a whole library. I like to be able to describe each piece with a simple sentence saying what it does, what&amp;#8217;s the responsibility. With control coupling you introduce multiple responsibilities in a single method which is against SRP and against Object Oriented Design.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-252"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;Detecting Control Couple Smell&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/kevinrutherford/reek" title="reek on github" target="_blank"&gt;Reek&lt;/a&gt; can help you with that &amp;#8211; detecting Control Couple is turned on by default. I believe that &lt;a href="https://github.com/codegram/pelusa" title="pelusa on github" target="_blank"&gt;Pelusa&amp;#8217;s&lt;/a&gt; &amp;#8220;Else Clause&amp;#8221; and &amp;#8220;Case Statement&amp;#8221; lints can also be used to find places in your code with potential control coupling.&lt;/p&gt;
&lt;p&gt;A dead-simple example of control coupling could like this:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603ed374/]&lt;/p&gt;
&lt;p&gt;Which is pretty self-explanatory. The &lt;code&gt;say&lt;/code&gt; method puts an upcased sentence if &lt;code&gt;loud&lt;/code&gt; parameter is set to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let me show you a real-world example though. Let&amp;#8217;s bring it to the class level &amp;#8211; here&amp;#8217;s a small snippet from &lt;a href="https://github.com/solnic/virtus" title="virtus on github" target="_blank"&gt;Virtus&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603ed3b9/]&lt;/p&gt;
&lt;p&gt;&lt;code&gt;DefaultValue&lt;/code&gt; is a class responsible for evaluating a default value of an attribute in Virtus. Its &lt;code&gt;#evaluate&lt;/code&gt; method, depending on &lt;code&gt;@value&lt;/code&gt; ivar, is deciding &lt;strong&gt;how&lt;/strong&gt; to evaluate the value. We have multiple cases here and all of them are handled within one method. You cannot easily describe this method&amp;#8217;s responsibility because it does different things depending on what the &lt;code&gt;@value&lt;/code&gt; ivar actually is. If it&amp;#8217;s a proc-like object responding to &lt;code&gt;#call&lt;/code&gt; we call it, if it&amp;#8217;s a duplicable object then we dup it, else we just return it as is.&lt;/p&gt;
&lt;p&gt;I found that code pretty ugly. The repercussion of Control Couple smell in this example was that every time we were setting the default value we were performing this if/else check on &lt;code&gt;@value&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Removing Control Couple Smell&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;DefaultValue&lt;/code&gt; class was refactored by splitting the evaluate logic into 3 sub-classes. Every sub-class implements a &lt;code&gt;self.handle?&lt;/code&gt; method which checks if its instance can actually handle the given value. This means that the logic inside &lt;code&gt;#evaluate&lt;/code&gt; is now performed only once, prior to deciding which &lt;code&gt;DefaultValue&lt;/code&gt; sub-class we want to initialize.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s how it looks like:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603ed401/]&lt;/p&gt;
&lt;p&gt;Now for example &lt;code&gt;FromCallable&lt;/code&gt; class implementation looks like that:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603ed442/]&lt;/p&gt;
&lt;p&gt;I liked that refactor because I could remove the if/else clause from &lt;code&gt;#evaluate&lt;/code&gt; method, split responsibilities across 3 sub-classes and gain a small performance boost too.&lt;/p&gt;
&lt;h2&gt;Summing Up&lt;/h2&gt;
&lt;p&gt;Even if removing Control Couple smell requires writing a bit more code &amp;#8211; it&amp;#8217;s worth that price. Getting rid of that smell leads to better Object Oriented Design and helps you with respecting Single Responsibility Principle. I also like that it&amp;#8217;s easier to understand what the code does because responsibilities are shared across the objects rather than jamming everything into a few methods that couple the logic to the received arguments.&lt;/p&gt;
&lt;p&gt;In the next post we&amp;#8217;ll see how to deal with Duplication in our code. Stay tuned.&lt;/p&gt;
&lt;p&gt;&lt;a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://solnic.eu/2012/04/11/get-rid-of-that-code-smell-control-couple.html" data-text="Get Rid of That Code Smell &amp;#8211; Control Couple"&gt;&lt;/a&gt;&lt;a class="a2a_button_google_plusone addtoany_special_service" data-href="http://solnic.eu/2012/04/11/get-rid-of-that-code-smell-control-couple.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_facebook_like addtoany_special_service" data-href="http://solnic.eu/2012/04/11/get-rid-of-that-code-smell-control-couple.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F04%2F11%2Fget-rid-of-that-code-smell-control-couple.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Control%20Couple" title="Reddit" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/&gt;&lt;/a&gt;&lt;a class="a2a_button_dzone" href="http://www.addtoany.com/add_to/dzone?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F04%2F11%2Fget-rid-of-that-code-smell-control-couple.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Control%20Couple" title="DZone" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/dzone.png" width="16" height="16" alt="DZone"/&gt;&lt;/a&gt;&lt;a class="a2a_button_linkedin" href="http://www.addtoany.com/add_to/linkedin?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F04%2F11%2Fget-rid-of-that-code-smell-control-couple.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Control%20Couple" title="LinkedIn" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/linkedin.png" width="16" height="16" alt="LinkedIn"/&gt;&lt;/a&gt;&lt;a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fsolnic.eu%2F2012%2F04%2F11%2Fget-rid-of-that-code-smell-control-couple.html&amp;amp;title=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Control%20Couple" id="wpa2a_4"&gt;Share/Bookmark&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/eH9TZtohKxE" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://solnic.eu/2012/04/11/get-rid-of-that-code-smell-control-couple.html#comments" thr:count="16" />
		<link rel="replies" type="application/atom+xml" href="http://solnic.eu/2012/04/11/get-rid-of-that-code-smell-control-couple.html/feed/atom" thr:count="16" />
		<thr:total>16</thr:total>
	<feedburner:origLink>http://solnic.eu/2012/04/11/get-rid-of-that-code-smell-control-couple.html</feedburner:origLink></entry>
		<entry>
		<author>
			<name>solnic</name>
						<uri>http://solnic.eu</uri>
					</author>
		<title type="html"><![CDATA[Get Rid of That Code Smell &#8211; Attributes]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/solnic-on-blog/~3/kZVl0KLxqBs/get-rid-of-that-code-smell-attributes.html" />
		<id>http://solnic.eu/?p=204</id>
		<updated>2012-04-04T12:53:20Z</updated>
		<published>2012-04-04T09:30:25Z</published>
		<category scheme="http://solnic.eu" term="Blog" /><category scheme="http://solnic.eu" term="metrics" /><category scheme="http://solnic.eu" term="oop" /><category scheme="http://solnic.eu" term="refactoring" /><category scheme="http://solnic.eu" term="ruby" />		<summary type="html"><![CDATA[In this post I will show you why using attribute accessors is a code smell in most of the cases. This is a very convenient feature of Ruby but you should only consider using it if you&#8217;re implementing a data-like &#8230;<p class="read-more"><a href="http://solnic.eu/2012/04/04/get-rid-of-that-code-smell-attributes.html">Read more &#187;</a></p>]]></summary>
		<content type="html" xml:base="http://solnic.eu/2012/04/04/get-rid-of-that-code-smell-attributes.html">&lt;p&gt;In this post I will show you why using attribute accessors is a code smell in most of the cases. This is a very convenient feature of Ruby but you should only consider using it if you&amp;#8217;re implementing a data-like objects which expose, well, data to other parts of your system. A good example is an Active Record object which exposes its attributes. Another good example could be an object which wraps a response from a remote API and through attribute readers gives you access to data returned in that response. Probably every other use case should be considered as a code smell.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-204"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;Detecting Attribute Smell&lt;/h2&gt;
&lt;p&gt;It&amp;#8217;s pretty easy to find the attribute smell in your code. Just grep for usage of attr_* in your classes. &lt;a href="https://github.com/codegram/pelusa" title="pelusa on github" target="_blank"&gt;Pelusa&lt;/a&gt; does that for you. &lt;a href="https://github.com/kevinrutherford/reek" title="reek on github" target="_blank"&gt;Reek&lt;/a&gt; can also detect this smell although this check is turned off by default.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s an attribute class which you can instantiate with a name and set its reader visibility. This is an actual piece of code that we used to have in &lt;a href="https://github.com/solnic/virtus" title="virtus on github" target="_blank"&gt;Virtus&lt;/a&gt;. The information about reader visibility needed to be public. Initially we had a public &lt;code&gt;attr_reader&lt;/code&gt; for the &lt;code&gt;reader_visibility&lt;/code&gt; instance variable that was set in the constructor. It was an easy and convenient solution. The related piece of code looked like that:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603f1a74/] &lt;/p&gt;
&lt;p&gt;Now in other places we were using the value of &lt;code&gt;reader_visibility&lt;/code&gt; so we had pieces of code like this:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603f1ab8/]&lt;/p&gt;
&lt;p&gt;This means that we had an instance variable exposed to the other objects which were relying on its value. This was a mistake and definitely a code smell.&lt;/p&gt;
&lt;h2&gt;Removing Attribute Smell&lt;/h2&gt;
&lt;p&gt;You probably know how to get rid of that smell, right? We should simply implement a predicate method and this is exactly what was done:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603f1afa/]&lt;/p&gt;
&lt;p&gt;This is much better because of two reasons. First of all we hide the private state of an object behind a public predicate method which is simply cleaner. Secondly if, for some reason, the logic for calculating the value of &lt;code&gt;reader_visibility&lt;/code&gt; becomes more complex we will simply implement that in the predicate method. Well, it&amp;#8217;s probably not going to be the case here but you get the idea.&lt;/p&gt;
&lt;h2&gt;What about &amp;#8220;Tell, Don&amp;#8217;t Ask&amp;#8221;?&lt;/h2&gt;
&lt;p&gt;This rule is also related to the attribute smell. Whenever you rely on an object&amp;#8217;s attribute to make a decision what to do next &amp;#8211; you&amp;#8217;re violating &amp;#8220;Tell, Don&amp;#8217;t Ask&amp;#8221; and you&amp;#8217;re introducing the attribute smell. Here&amp;#8217;s a quick example:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4603f1b3d/]&lt;/p&gt;
&lt;p&gt;This subtle difference is important because the library object should know how to deal with an empty books array and it should not be a concern &amp;#8220;outside&amp;#8221; of the library object. We also rely on the books property which indicates the attribute smell.&lt;/p&gt;
&lt;h2&gt;Summing Up&lt;/h2&gt;
&lt;p&gt;As you can see the attribute smell is easy to find and fix. The important thing to remember is that when you rely on the internal state of the objects you make future refactorings very difficult. So just don&amp;#8217;t do that. Objects should expose as little information about their internal state as possible. Make things publicly visible only if you&amp;#8217;re certain it&amp;#8217;s really really needed. Rely on API that your objects provide instead of their internal state. This will make your life much easier.&lt;/p&gt;
&lt;p&gt;In the next post we&amp;#8217;ll deal with the &amp;#8220;Control Couple&amp;#8221; smell.&lt;/p&gt;
&lt;p&gt;&lt;a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://solnic.eu/2012/04/04/get-rid-of-that-code-smell-attributes.html" data-text="Get Rid of That Code Smell &amp;#8211; Attributes"&gt;&lt;/a&gt;&lt;a class="a2a_button_google_plusone addtoany_special_service" data-href="http://solnic.eu/2012/04/04/get-rid-of-that-code-smell-attributes.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_facebook_like addtoany_special_service" data-href="http://solnic.eu/2012/04/04/get-rid-of-that-code-smell-attributes.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F04%2F04%2Fget-rid-of-that-code-smell-attributes.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Attributes" title="Reddit" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/&gt;&lt;/a&gt;&lt;a class="a2a_button_dzone" href="http://www.addtoany.com/add_to/dzone?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F04%2F04%2Fget-rid-of-that-code-smell-attributes.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Attributes" title="DZone" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/dzone.png" width="16" height="16" alt="DZone"/&gt;&lt;/a&gt;&lt;a class="a2a_button_linkedin" href="http://www.addtoany.com/add_to/linkedin?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F04%2F04%2Fget-rid-of-that-code-smell-attributes.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Attributes" title="LinkedIn" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/linkedin.png" width="16" height="16" alt="LinkedIn"/&gt;&lt;/a&gt;&lt;a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fsolnic.eu%2F2012%2F04%2F04%2Fget-rid-of-that-code-smell-attributes.html&amp;amp;title=Get%20Rid%20of%20That%20Code%20Smell%20%E2%80%93%20Attributes" id="wpa2a_6"&gt;Share/Bookmark&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/kZVl0KLxqBs" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://solnic.eu/2012/04/04/get-rid-of-that-code-smell-attributes.html#comments" thr:count="13" />
		<link rel="replies" type="application/atom+xml" href="http://solnic.eu/2012/04/04/get-rid-of-that-code-smell-attributes.html/feed/atom" thr:count="13" />
		<thr:total>13</thr:total>
	<feedburner:origLink>http://solnic.eu/2012/04/04/get-rid-of-that-code-smell-attributes.html</feedburner:origLink></entry>
		<entry>
		<author>
			<name>solnic</name>
						<uri>http://solnic.eu</uri>
					</author>
		<title type="html"><![CDATA[Get Rid of That Code Smell]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/solnic-on-blog/~3/PHmMT2Z8DqU/get-rid-of-that-code-smell.html" />
		<id>http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html</id>
		<updated>2012-05-11T17:43:03Z</updated>
		<published>2012-03-30T11:30:19Z</published>
		<category scheme="http://solnic.eu" term="Blog" /><category scheme="http://solnic.eu" term="datamapper" /><category scheme="http://solnic.eu" term="metrics" /><category scheme="http://solnic.eu" term="ruby" />		<summary type="html"><![CDATA[While working on DataMapper 2 libraries we are measuring quality of our code with various code metric tools. Dan Kubb has been using this approach successfully for over 2 years in Veritas which resulted in a beautiful and clean code. &#8230;<p class="read-more"><a href="http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html">Read more &#187;</a></p>]]></summary>
		<content type="html" xml:base="http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html">&lt;p&gt;While working on DataMapper 2 libraries we are measuring quality of our code with various code metric tools. &lt;a href="https://github.com/dkubb"&gt;Dan Kubb&lt;/a&gt; has been using this approach successfully for over 2 years in &lt;a href="https://github.com/dkubb/veritas"&gt;Veritas&lt;/a&gt; which resulted in a beautiful and clean code. When I started working on &lt;a href="https://github.com/solnic/virtus"&gt;Virtus&lt;/a&gt; I decided to embrace all the practices that Dan introduced in his projects. It was a fantastic experience because Virtus was not a green-field project &amp;#8211; I extracted a piece of DataMapper 1 and turned it into a standalone library. The code was already pretty awesome and easy to work with but this didn&amp;#8217;t change the fact that most of it was completely refactored after we realized how many code smells were there. Based on this experience I&amp;#8217;m starting a small series of blog posts about dealing with various common code smells.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-3"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There are a lot of great ruby tools for finding smells in your code. In DM2 projects we use &lt;a title="metric-fu on github" href="https://github.com/jscruggs/metric_fu"&gt;metric-fu&lt;/a&gt; which incorporates usage of Flog, Flay, Reek and Roodi. Recently I also started experimenting with &lt;a title="pelusa on github" href="https://github.com/codegram/pelusa" target="_blank"&gt;Pelusa&lt;/a&gt; (I&amp;#8217;m hoping to replace *all* the metric tools with Pelusa at some point in the future).&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a list of most common code smells that we&amp;#8217;ve identified and removed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="line-height: 22px;"&gt;&lt;a href="http://solnic.eu/2012/04/04/get-rid-of-that-code-smell-attributes.html" title="Get Rid of That Code Smell – Attributes"&gt;Attribute&lt;/a&gt; (using attribute getters/setters)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="line-height: 22px;"&gt;&lt;a href="http://solnic.eu/2012/04/11/get-rid-of-that-code-smell-control-couple.html" title="Get Rid of That Code Smell – Control Couple"&gt;Control Couple&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="line-height: 22px;"&gt;&lt;a href="http://solnic.eu/2012/05/11/get-rid-of-that-code-smell-duplication.html" title="Get Rid of That Code Smell – Duplication"&gt;Duplication&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="line-height: 22px;"&gt;Primitive Obsession&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="line-height: 22px;"&gt;Feature Envy&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="line-height: 22px;"&gt;Utility Function&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="line-height: 22px;"&gt;Large Class&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="line-height: 22px;"&gt;Long Method&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the near future I&amp;#8217;ll describe each of these code smells with simple code examples showing you how you can deal with them. This will show what we&amp;#8217;ve done but I&amp;#8217;m not saying that there are no better ways and as always I&amp;#8217;m open for discussions.&lt;/p&gt;
&lt;p&gt;What&amp;#8217;s the result of removing these (and probably a few more that I don&amp;#8217;t recall at the moment) code smells? Really clean and well designed codebase that&amp;#8217;s a great pleasure to work with. You can actually see a visual result on Virtus&amp;#8217; CodeClimate profile &lt;a title="Virtus on CodeClimate" href="https://codeclimate.com/github/solnic/virtus" target="_blank"&gt;here&lt;/a&gt;. Entire codebase has &amp;#8220;A&amp;#8221; grade. How awesome is that?&lt;/p&gt;
&lt;p&gt;If you want to know how we&amp;#8217;ve pushed Virtus to the high level of code quality &amp;#8211; watch this space.&lt;/p&gt;
&lt;p&gt;&lt;a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html" data-text="Get Rid of That Code Smell"&gt;&lt;/a&gt;&lt;a class="a2a_button_google_plusone addtoany_special_service" data-href="http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_facebook_like addtoany_special_service" data-href="http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F03%2F30%2Fget-rid-of-that-code-smell.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell" title="Reddit" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/&gt;&lt;/a&gt;&lt;a class="a2a_button_dzone" href="http://www.addtoany.com/add_to/dzone?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F03%2F30%2Fget-rid-of-that-code-smell.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell" title="DZone" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/dzone.png" width="16" height="16" alt="DZone"/&gt;&lt;/a&gt;&lt;a class="a2a_button_linkedin" href="http://www.addtoany.com/add_to/linkedin?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F03%2F30%2Fget-rid-of-that-code-smell.html&amp;amp;linkname=Get%20Rid%20of%20That%20Code%20Smell" title="LinkedIn" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/linkedin.png" width="16" height="16" alt="LinkedIn"/&gt;&lt;/a&gt;&lt;a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fsolnic.eu%2F2012%2F03%2F30%2Fget-rid-of-that-code-smell.html&amp;amp;title=Get%20Rid%20of%20That%20Code%20Smell" id="wpa2a_8"&gt;Share/Bookmark&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/PHmMT2Z8DqU" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html#comments" thr:count="5" />
		<link rel="replies" type="application/atom+xml" href="http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html/feed/atom" thr:count="5" />
		<thr:total>5</thr:total>
	<feedburner:origLink>http://solnic.eu/2012/03/30/get-rid-of-that-code-smell.html</feedburner:origLink></entry>
		<entry>
		<author>
			<name>solnic</name>
						<uri>http://solnic.eu</uri>
					</author>
		<title type="html"><![CDATA[DataMapper-2 Presentation From wroc_love.rb Conference]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/solnic-on-blog/~3/Vpsc0uqyjrY/datamapper-2-presentation-from-wroc-love-rb-conference.html" />
		<id>http://solnic.eu/2012/03/13/datamapper-2-presentation-from-wroc-love-dot-rb-conference</id>
		<updated>2012-03-26T17:59:25Z</updated>
		<published>2012-03-13T14:13:00Z</published>
		<category scheme="http://solnic.eu" term="Blog" /><category scheme="http://solnic.eu" term="conferences" /><category scheme="http://solnic.eu" term="datamapper" /><category scheme="http://solnic.eu" term="ruby" />		<summary type="html"><![CDATA[Once again thank you for the awesome event that took place in Wrocław last weekend &#8211; the wroc_love.rb conference. We’ve had fantastic and inspiring talks and many great discussions. It’s clear to me that a new era in our community &#8230;<p class="read-more"><a href="http://solnic.eu/2012/03/13/datamapper-2-presentation-from-wroc-love-rb-conference.html">Read more &#187;</a></p>]]></summary>
		<content type="html" xml:base="http://solnic.eu/2012/03/13/datamapper-2-presentation-from-wroc-love-rb-conference.html">&lt;p&gt;Once again thank you for the awesome event that took place in Wrocław last weekend &amp;#8211; &lt;a href="http://wrocloverb.com"&gt;the wroc_love.rb conference&lt;/a&gt;. We’ve had fantastic and inspiring talks and many great discussions. It’s clear to me that a new era in our community has started and people are willing to learn and embrace patterns from other languages without being scared that we’re going to lose the “agile” aspect of programming in Ruby and Rails.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-146"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;My personal favorite presentations were Piotr Szotkowski’s &lt;a href="http://decoupling-wrocloverb-2012.heroku.com/"&gt;“Decoupling Persistence”&lt;/a&gt; and Jim Gay’s &lt;a href="http://www.saturnflyer.com/blog/jim/2012/03/13/wroclove-rb-presentation/"&gt;“It’s Business Time”&lt;/a&gt;. We also had a very interesting panel discussion about OOP and Rails.&lt;/p&gt;
&lt;p&gt;Most of the talks and discussions should be available online soon. If you’re interested in seeing them make sure to follow wroc_love.rb on &lt;a href="http://twitter.com/wrocloverb"&gt;twitter&lt;/a&gt; and/or watch their &lt;a href="http://blog.wrocloverb.com/"&gt;blog&lt;/a&gt; for any future announcements.&lt;/p&gt;
&lt;p&gt;Meanwhile here are the slides from the talk I gave about development of DataMapper 2:&lt;/p&gt;
&lt;p&gt;&lt;script src="http://speakerdeck.com/embed/4f5cada96e13db027c00de5b.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://solnic.eu/2012/03/13/datamapper-2-presentation-from-wroc-love-rb-conference.html" data-text="DataMapper-2 Presentation From wroc_love.rb Conference"&gt;&lt;/a&gt;&lt;a class="a2a_button_google_plusone addtoany_special_service" data-href="http://solnic.eu/2012/03/13/datamapper-2-presentation-from-wroc-love-rb-conference.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_facebook_like addtoany_special_service" data-href="http://solnic.eu/2012/03/13/datamapper-2-presentation-from-wroc-love-rb-conference.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F03%2F13%2Fdatamapper-2-presentation-from-wroc-love-rb-conference.html&amp;amp;linkname=DataMapper-2%20Presentation%20From%20wroc_love.rb%20Conference" title="Reddit" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/&gt;&lt;/a&gt;&lt;a class="a2a_button_dzone" href="http://www.addtoany.com/add_to/dzone?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F03%2F13%2Fdatamapper-2-presentation-from-wroc-love-rb-conference.html&amp;amp;linkname=DataMapper-2%20Presentation%20From%20wroc_love.rb%20Conference" title="DZone" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/dzone.png" width="16" height="16" alt="DZone"/&gt;&lt;/a&gt;&lt;a class="a2a_button_linkedin" href="http://www.addtoany.com/add_to/linkedin?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F03%2F13%2Fdatamapper-2-presentation-from-wroc-love-rb-conference.html&amp;amp;linkname=DataMapper-2%20Presentation%20From%20wroc_love.rb%20Conference" title="LinkedIn" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/linkedin.png" width="16" height="16" alt="LinkedIn"/&gt;&lt;/a&gt;&lt;a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fsolnic.eu%2F2012%2F03%2F13%2Fdatamapper-2-presentation-from-wroc-love-rb-conference.html&amp;amp;title=DataMapper-2%20Presentation%20From%20wroc_love.rb%20Conference" id="wpa2a_10"&gt;Share/Bookmark&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/Vpsc0uqyjrY" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://solnic.eu/2012/03/13/datamapper-2-presentation-from-wroc-love-rb-conference.html#comments" thr:count="2" />
		<link rel="replies" type="application/atom+xml" href="http://solnic.eu/2012/03/13/datamapper-2-presentation-from-wroc-love-rb-conference.html/feed/atom" thr:count="2" />
		<thr:total>2</thr:total>
	<feedburner:origLink>http://solnic.eu/2012/03/13/datamapper-2-presentation-from-wroc-love-rb-conference.html</feedburner:origLink></entry>
		<entry>
		<author>
			<name>solnic</name>
						<uri>http://solnic.eu</uri>
					</author>
		<title type="html"><![CDATA[New Virtus Release With Truly Awesome Features]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/solnic-on-blog/~3/L6w_yELfS3k/new-virtus-release-with-truly-awesome-features.html" />
		<id>http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features</id>
		<updated>2012-03-26T18:00:08Z</updated>
		<published>2012-02-08T10:18:00Z</published>
		<category scheme="http://solnic.eu" term="Blog" /><category scheme="http://solnic.eu" term="datamapper" /><category scheme="http://solnic.eu" term="patterns" /><category scheme="http://solnic.eu" term="ruby" />		<summary type="html"><![CDATA[Just a quick announcement that I just pushed a new version of Virtus with support for long awaited features: EmbeddedValue, member type coercions for array/set attributes and ValueObject. Current version is 0.2.0, please give it a try and tell me &#8230;<p class="read-more"><a href="http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features.html">Read more &#187;</a></p>]]></summary>
		<content type="html" xml:base="http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features.html">&lt;p&gt;Just a quick announcement that I just pushed a &lt;a href="https://rubygems.org/gems/virtus/versions/0.2.0"&gt;new version&lt;/a&gt; of &lt;a href="https://github.com/solnic/virtus"&gt;Virtus&lt;/a&gt; with support for long awaited features: EmbeddedValue, member type coercions for array/set attributes and ValueObject. Current version is 0.2.0, please give it a try and tell me what you think.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-147"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a quick sneak-preview of what you can do with Virtus:&lt;/p&gt;
&lt;p&gt;[crayon-4fae460400e34/]&lt;/p&gt;
&lt;p&gt;I hope you&amp;#8217;re going to enjoy it and find it useful in your projects. In case of any issues please report them on &lt;a href="https://github.com/solnic/virtus/issues"&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Huge props go to &lt;a href="https://github.com/dkubb"&gt;Dan Kubb&lt;/a&gt;, &lt;a href="https://github.com/emmanuel"&gt;Emmanuel Gomez&lt;/a&gt; and &lt;a href="https://github.com/senny"&gt;Yves Senn&lt;/a&gt; for helping me with recent releases! Thanks guys!&lt;/p&gt;
&lt;p&gt;&lt;a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features.html" data-text="New Virtus Release With Truly Awesome Features"&gt;&lt;/a&gt;&lt;a class="a2a_button_google_plusone addtoany_special_service" data-href="http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_facebook_like addtoany_special_service" data-href="http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F02%2F08%2Fnew-virtus-release-with-truly-awesome-features.html&amp;amp;linkname=New%20Virtus%20Release%20With%20Truly%20Awesome%20Features" title="Reddit" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/&gt;&lt;/a&gt;&lt;a class="a2a_button_dzone" href="http://www.addtoany.com/add_to/dzone?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F02%2F08%2Fnew-virtus-release-with-truly-awesome-features.html&amp;amp;linkname=New%20Virtus%20Release%20With%20Truly%20Awesome%20Features" title="DZone" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/dzone.png" width="16" height="16" alt="DZone"/&gt;&lt;/a&gt;&lt;a class="a2a_button_linkedin" href="http://www.addtoany.com/add_to/linkedin?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F02%2F08%2Fnew-virtus-release-with-truly-awesome-features.html&amp;amp;linkname=New%20Virtus%20Release%20With%20Truly%20Awesome%20Features" title="LinkedIn" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/linkedin.png" width="16" height="16" alt="LinkedIn"/&gt;&lt;/a&gt;&lt;a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fsolnic.eu%2F2012%2F02%2F08%2Fnew-virtus-release-with-truly-awesome-features.html&amp;amp;title=New%20Virtus%20Release%20With%20Truly%20Awesome%20Features" id="wpa2a_12"&gt;Share/Bookmark&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/L6w_yELfS3k" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features.html#comments" thr:count="8" />
		<link rel="replies" type="application/atom+xml" href="http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features.html/feed/atom" thr:count="8" />
		<thr:total>8</thr:total>
	<feedburner:origLink>http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features.html</feedburner:origLink></entry>
		<entry>
		<author>
			<name>solnic</name>
						<uri>http://solnic.eu</uri>
					</author>
		<title type="html"><![CDATA[Yes, You Should Write Controller Tests!]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/solnic-on-blog/~3/TeAFSW_V-vs/yes-you-should-write-controller-tests.html" />
		<id>http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests</id>
		<updated>2012-03-26T18:00:21Z</updated>
		<published>2012-02-02T11:25:00Z</published>
		<category scheme="http://solnic.eu" term="Blog" /><category scheme="http://solnic.eu" term="rails" /><category scheme="http://solnic.eu" term="rspec" /><category scheme="http://solnic.eu" term="ruby" /><category scheme="http://solnic.eu" term="tdd" />		<summary type="html"><![CDATA[It really surprises me that there are people arguing that writing controller tests doesn&#8217;t make sense. Probably the most common argument is that actions are covered in acceptence tests along with checking if views are properly rendered. Right? Right&#8230;well that&#8217;s &#8230;<p class="read-more"><a href="http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests.html">Read more &#187;</a></p>]]></summary>
		<content type="html" xml:base="http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests.html">&lt;p&gt;It really surprises me that there are people arguing that writing controller tests doesn&amp;#8217;t make sense. Probably the most common argument is that actions are covered in acceptence tests along with checking if views are properly rendered. Right? Right&amp;#8230;well that&amp;#8217;s just wrong! Are you trying to say that your slow acceptance tests are covering every possible controller action scenario? Are you trying to say that, for instance, every redirect that should take place is tested within an &lt;em&gt;acceptance test&lt;/em&gt;? Are you also checking every invalid request in acceptance tests? Are you telling me that your acceptance test suite takes 27 hours and 13 minutes to finish because you fully test your controllers there?! Oh I&amp;#8217;m sure that your acceptance test suite runs faster and you probably cover only &amp;#8216;the happy scenarios&amp;#8217; there&amp;#8230;which basically means you miss A LOT of test coverage.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-148"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;A Simple Fact About a Controller&lt;/h2&gt;
&lt;p&gt;Here&amp;#8217;s a simple fact about a controller &amp;#8211; &lt;em&gt;it&amp;#8217;s a class with methods&lt;/em&gt;! Yes, it&amp;#8217;s a class with methods I repeat. It should have tests. Every method (action) should be covered by a test.&lt;/p&gt;
&lt;p&gt;Why? Well, for the same reason that you write tests for any other class in your application. We want to make sure that our code behaves like expected. It&amp;#8217;s also much easier to keep your controllers thin when you have tests. If it&amp;#8217;s trivial to write a test for a controller then it&amp;#8217;s probably a well implemented controller. If you&amp;#8217;re drowning in mocks then you probably want to refactor your controller.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s an example of a users controller with a sample create action:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4604025a3/]&lt;/p&gt;
&lt;p&gt;As you can see we load a group object in the before filter and then we use that object to create a new user. Pretty dead-simple. If you just write an acceptance spec for this controller I bet you will not cover the case when the group cannot be found. After all people usually write acceptance tests for optimistic scenarios. If they want to cover every case then I&amp;#8217;m sure they will miss the deadline ;)&lt;/p&gt;
&lt;p&gt;But it&amp;#8217;s not just about covering every path! It&amp;#8217;s also about the quality of the code. When you look at the example above you probably won&amp;#8217;t see any code smells, right? OK so let me write a spec for the create action:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4604025ec/]&lt;/p&gt;
&lt;p&gt;What happens there? Because we reach deeper into group object, get its users and then use it to build a new user the spec requires more mocks then it should. This is a trivial example but you can probably imagine how a spec would look like if the action was more complicated, had more branching logic and even more &lt;em&gt;structural coupling&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s quickly make a small refactor of the action:&lt;/p&gt;
&lt;p&gt;[crayon-4fae460402634/]&lt;/p&gt;
&lt;p&gt;Now the spec will be a bit simpler:&lt;/p&gt;
&lt;p&gt;[crayon-4fae460402675/]&lt;/p&gt;
&lt;p&gt;We should also add an example checking the case where a group is not found. This is going to be a rather rare case but this doesn&amp;#8217;t change the fact that we should have a test for it:&lt;/p&gt;
&lt;p&gt;[crayon-4fae4604026b9/]&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s it! Small test, fast test. Code is covered. Controller is thin. Now it&amp;#8217;s probably a good idea to write some views specs for users controller too but I&amp;#8217;m not going to write about it here, that&amp;#8217;s boring ;)&lt;/p&gt;
&lt;h2&gt;Summing up&lt;/h2&gt;
&lt;p&gt;Yes, you should write tests for controllers. Whenever somebody asks you if he/she should write them, your answer should be &amp;#8216;yes!&amp;#8217;. There are no good arguments against writing controller tests. It&amp;#8217;s code after all, it should be covered by tests. Let the tests drive your design and you will be happy with your controllers, otherwise you might end up with a mess. Without proper tests you won&amp;#8217;t be able to truly verify if your controllers are thin and well designed. So please go and write controller tests!&lt;/p&gt;
&lt;p&gt;In case you missed it you might want to read Avdi&amp;#8217;s great post about &lt;a href="http://avdi.org/devblog/2011/07/05/demeter-its-not-just-a-good-idea-its-the-law/"&gt;&amp;#8220;Law of Demeter&amp;#8221;&lt;/a&gt; where he writes about structural coupling which is mentioned in this post too.&lt;/p&gt;
&lt;p&gt;&lt;a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests.html" data-text="Yes, You Should Write Controller Tests!"&gt;&lt;/a&gt;&lt;a class="a2a_button_google_plusone addtoany_special_service" data-href="http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_facebook_like addtoany_special_service" data-href="http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F02%2F02%2Fyes-you-should-write-controller-tests.html&amp;amp;linkname=Yes%2C%20You%20Should%20Write%20Controller%20Tests%21" title="Reddit" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/&gt;&lt;/a&gt;&lt;a class="a2a_button_dzone" href="http://www.addtoany.com/add_to/dzone?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F02%2F02%2Fyes-you-should-write-controller-tests.html&amp;amp;linkname=Yes%2C%20You%20Should%20Write%20Controller%20Tests%21" title="DZone" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/dzone.png" width="16" height="16" alt="DZone"/&gt;&lt;/a&gt;&lt;a class="a2a_button_linkedin" href="http://www.addtoany.com/add_to/linkedin?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F02%2F02%2Fyes-you-should-write-controller-tests.html&amp;amp;linkname=Yes%2C%20You%20Should%20Write%20Controller%20Tests%21" title="LinkedIn" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/linkedin.png" width="16" height="16" alt="LinkedIn"/&gt;&lt;/a&gt;&lt;a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fsolnic.eu%2F2012%2F02%2F02%2Fyes-you-should-write-controller-tests.html&amp;amp;title=Yes%2C%20You%20Should%20Write%20Controller%20Tests%21" id="wpa2a_14"&gt;Share/Bookmark&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/TeAFSW_V-vs" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests.html#comments" thr:count="40" />
		<link rel="replies" type="application/atom+xml" href="http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests.html/feed/atom" thr:count="40" />
		<thr:total>40</thr:total>
	<feedburner:origLink>http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests.html</feedburner:origLink></entry>
		<entry>
		<author>
			<name>solnic</name>
						<uri>http://solnic.eu</uri>
					</author>
		<title type="html"><![CDATA[Ruby DataMapper Status]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/solnic-on-blog/~3/Jlg-obA72wU/ruby-datamapper-status.html" />
		<id>http://solnic.eu/2012/01/10/ruby-datamapper-status</id>
		<updated>2012-03-28T18:12:51Z</updated>
		<published>2012-01-10T00:00:00Z</published>
		<category scheme="http://solnic.eu" term="Blog" /><category scheme="http://solnic.eu" term="datamapper" /><category scheme="http://solnic.eu" term="orm" /><category scheme="http://solnic.eu" term="patterns" /><category scheme="http://solnic.eu" term="ruby" />		<summary type="html"><![CDATA[In my recent post I gave you a brief overview of what I think about the state of Ruby ORMs. Since I’m involved in the development of DataMapper project I want to write a little more lines of text to &#8230;<p class="read-more"><a href="http://solnic.eu/2012/01/10/ruby-datamapper-status.html">Read more &#187;</a></p>]]></summary>
		<content type="html" xml:base="http://solnic.eu/2012/01/10/ruby-datamapper-status.html">&lt;p&gt;In my recent post I gave you a brief overview of what I think about &lt;a href="http://solnic.eu/2011/11/29/the-state-of-ruby-orm.html"&gt;the state of Ruby ORMs&lt;/a&gt;. Since I’m involved in the development of &lt;a href="http://datamapper.org"&gt;DataMapper&lt;/a&gt; project I want to write a little more lines of text to give you a good overview of the current state of DataMapper project and how the future version 2.0 is going to look like.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-149"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;DataMapper 1.x&lt;/h2&gt;
&lt;p&gt;Let’s get this straight once and for all: DataMapper was never a pure implementation of the Data Mapper pattern. It has elements of both Data Mapper and Active Record patterns. It has a mapping layer where you can configure mappings between model properties and database columns but this doesn’t change the fact that your models have direct access to the persistence layer and a lot of persistence-related functionality is mixed into them. This is what makes DataMapper an ‘ActiveRecord-ish’ library. After a few years of development it’s become clear that this approach, despite its advantages over ActiveRecord, is still not good enough.&lt;/p&gt;
&lt;p&gt;Probably one of the biggest wins of DataMapper is support for many different kinds of data stores. Apart from supporting most common RDBMS databases there are adapters for various key-value stores, NoSQL databases and more. The flip side is that working with multiple data stores at once is not very stable at the moment and that you can’t easily use the full power of various databases, like MongoDB, due to limitations in DataMapper’s API.&lt;/p&gt;
&lt;p&gt;The good news is that while working on DataMapper and many of its adapters we’ve learned our lessons. With all that knowledge and experience the work on DataMapper 2.0 has been started.&lt;/p&gt;
&lt;h2&gt;DataMapper 2.0&lt;/h2&gt;
&lt;p&gt;First of all the next major version of DataMapper will implement the Data Mapper pattern as described in the PoEAA:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself.&lt;/p&gt;
&lt;footer&gt;&lt;strong&gt;Martin Fowler&lt;/strong&gt; &lt;cite&gt;&lt;a href=’http://martinfowler.com/eaaCatalog/dataMapper.html’&gt;martinfowler.com/eaaCatalog/&amp;hellip;&lt;/a&gt;&lt;/cite&gt;&lt;/footer&gt;
&lt;/blockquote&gt;
&lt;p&gt;DataMapper 2 won’t be a big monolithic library, it will consist of multiple independent pieces that are glued together. Each piece of DM2 is a standalone&lt;br /&gt;
library so that you could use it separately from the DM itself.&lt;/p&gt;
&lt;p&gt;Let me describe all the related projects.&lt;/p&gt;
&lt;h3&gt;Veritas &amp;#8211; the new relational algebra engine&lt;/h3&gt;
&lt;p&gt;The core of DM2 is &lt;a href="https://github.com/dkubb/veritas"&gt;Veritas&lt;/a&gt; &amp;#8211; the new relational algebra engine developed by Dan Kubb. Why not ARel? The answer is simple &amp;#8211; ARel is designed to generate SQL whereas DataMapper needs something more abstract with adapters that can handle different kinds of query dialects. With that premise Veritas is a full-featured relational algebra implementation and there’s already an &lt;a href="https://github.com/dkubb/veritas-sql-generator"&gt;SQL generator&lt;/a&gt; which can build pretty complex queries. More generators will be written soon.&lt;/p&gt;
&lt;p&gt;Here’s a quick sneak-preview of how you can build relations with Veritas:&lt;/p&gt;
&lt;p&gt;[crayon-4fae46040abe1/]&lt;/p&gt;
&lt;p&gt;What’s great about Veritas is that with its level of abstraction you can use it for various things &amp;#8211; not just to generate queries. For example there’s an&lt;br /&gt;
idea of using Veritas to build a new “migrations” library for DM2 that will easily handle even very complex scenarios.&lt;/p&gt;
&lt;h3&gt;Virtus &amp;#8211; the new model definition and introspection layer&lt;/h3&gt;
&lt;p&gt;I’ve already introduced &lt;a href="http://solnic.eu/2011/06/06/virtus—attributes-for-your-plain-ruby-objects.html"&gt;Virtus&lt;/a&gt; &amp;#8211; it’s an extraction of DataMapper’s Property API. During the last few months we’ve made many significant improvements and more features will be added soon too. Virtus already supports defining attributes on your models and can handle many kinds of coercions. You can also implement your own coersion methods if you need them.&lt;br /&gt;
In the near future Virtus will be supporting more complex functionality like &lt;a href="http://martinfowler.com/eaaCatalog/embeddedValue.html"&gt;EmbeddedValue&lt;/a&gt; and &lt;a href="http://martinfowler.com/eaaCatalog/valueObject.html"&gt;ValueObject&lt;/a&gt;. It’s also possible that with Virtus you will be able to define relationships between POROs.&lt;/p&gt;
&lt;p&gt;The important thing about Virtus is that it’s designed to work with PORO and it has nothing to do with any persistence concerns. For example there were&lt;br /&gt;
people asking me about things like support for dirty attributes tracking &amp;#8211; it’s not going to be included in Virtus.&lt;/p&gt;
&lt;p&gt;I should mention that &lt;em&gt;DataMapper 2.0 will be designed to work with POROs&lt;/em&gt; that &lt;em&gt;are not&lt;/em&gt; extended by Virtus. Virtus will be optional but since it provides a very common functionality I suspect most people will want to use it.&lt;/p&gt;
&lt;h3&gt;Aequitas &amp;#8211; the new validation library&lt;/h3&gt;
&lt;p&gt;Developed by Emmanuel Gomez, &lt;a href="https://github.com/emmanuel/aequitas"&gt;Aequitas&lt;/a&gt; is designed to work with any Ruby object and it also has support for Virtus. The idea is similar to what we have in DataMapper 1.x where validations can be derived from property declarations. Aquitas is based on the current&lt;br /&gt;
&lt;a href="https://github.com/datamapper/dm-validations"&gt;dm-validations&lt;/a&gt; and the API is very similar, if not identical. Aequitas has support for custom error messages, I18n, validation contexts and built-in data types which come with their own set of validation rules.&lt;/p&gt;
&lt;p&gt;[crayon-4fae46040ac39/]&lt;/p&gt;
&lt;h3&gt;Session, Dirty Tracking and Unit of Work&lt;/h3&gt;
&lt;p&gt;In the Data Mapper world every change made to the models loaded into memory is tracked by a specialized object which works like a session. When you’re done&lt;br /&gt;
with making changes you can either commit them or rollback. The important thing is that all the complex logic behind tracking what was changed, what was deleted and what was added is handled by the session object. Your models are dumb in this regard, they don’t care about dirty tracking, it’s not their responsibility. It’s one of the major differences between AR and DM.&lt;/p&gt;
&lt;p&gt;The session object will be an implementation of the Unit of Work pattern described in PoEAA as:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Maintains a list of objects affected by a business transaction and coordinates&lt;br/&gt;the writing out of changes and the resolution of concurrency problems.&lt;/p&gt;
&lt;footer&gt;&lt;strong&gt;Martin Fowler&lt;/strong&gt; &lt;cite&gt;&lt;a href=’http://martinfowler.com/eaaCatalog/unitOfWork.html’&gt;martinfowler.com/eaaCatalog/&amp;hellip;&lt;/a&gt;&lt;/cite&gt;&lt;/footer&gt;
&lt;/blockquote&gt;
&lt;p&gt;More technically speaking a session will hold a &lt;a href="http://en.wikipedia.org/wiki/Directed_acyclic_graph"&gt;DAG&lt;/a&gt; of commands sorted by their dependencies so that when you commit the session it will know in what order those commands should be executed.&lt;/p&gt;
&lt;p&gt;When you think about it you will realize that this pattern is quite common. That’s why it would probably make sense to come up with a general UoW library&lt;br /&gt;
and then create an extended version for DataMapper needs.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s an example of how such a session &lt;em&gt;may&lt;/em&gt; look like:&lt;/p&gt;
&lt;p&gt;[crayon-4fae46040ac84/]&lt;/p&gt;
&lt;h3&gt;The Mapper&lt;/h3&gt;
&lt;p&gt;Probably &lt;a href="https://github.com/datamapper/dm-core"&gt;dm-core&lt;/a&gt;, the current core DataMapper library, will be completely rewritten and become the mapper layer with a thin query API that delegates most of the heavy work down to a veritas adapter. For your convenience there will be a veritas mapper class that you can inherit from but this doesn’t mean that you won’t be able to write custom mapper classes. The idea is really simple here, a mapper class defines&lt;br /&gt;
mappings between PORO and the database schema. In most of the cases this means a direct 1:1 mapping but the huge advantage is that once you need something&lt;br /&gt;
custom &amp;#8211; you will be able to define it.&lt;/p&gt;
&lt;p&gt;This is really the key aspect of using a data mapper library &amp;#8211; you define your domain objects so that they correspond to your real world domain as close as&lt;br /&gt;
possible. It makes applying practices like &lt;a href="http://confreaks.net/videos/641-gogaruco2011-fast-rails-tests"&gt;“Fast Rails Tests”&lt;/a&gt; suggested by Corey Haines come in a natural way because you’ll be implementing the business logic in POROs and have them unit tested in an isolation without the database access.&lt;/p&gt;
&lt;p&gt;You will be able to define a mapper class more or less like this:&lt;/p&gt;
&lt;p&gt;[crayon-4fae46040accb/]&lt;/p&gt;
&lt;h2&gt;Roadmap? ETA?&lt;/h2&gt;
&lt;p&gt;There&amp;#8217;s a work-in-progress roadmap for DM2 available &lt;a href="https://github.com/datamapper/dm-core/wiki/Roadmap"&gt;here&lt;/a&gt;. Regarding ETA it&amp;#8217;s really hard to say. We&amp;#8217;re taking our time to build all these libraries, there&amp;#8217;s a big focus on code quality and proper test &lt;em&gt;and&lt;/em&gt; docs coverage. Once the roadmap is finalized we will be able to come up with some ETA.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the full list of related projects on &lt;a href="https://github.com"&gt;Github&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dkubb/veritas"&gt;veritas&lt;/a&gt; &amp;#8211; core library&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dkubb/veritas-sql-generator"&gt;veritas-sql-generator&lt;/a&gt; &amp;#8211; SQL generator&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dkubb/veritas-do-adapter"&gt;veritas-do-adapter&lt;/a&gt; &amp;#8211; DataObjects adapter&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dkubb/veritas-optimizer"&gt;veritas-optimizer&lt;/a&gt; &amp;#8211; relation optimizer&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/solnic/virtus"&gt;virtus&lt;/a&gt; &amp;#8211; attributes/coercions&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/emmanuel/aequitas"&gt;aequitas&lt;/a&gt; &amp;#8211; validations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#8230;and more will come soon, so stay tuned!&lt;/p&gt;
&lt;p&gt;Make sure to follow &lt;a href="http://twitter.com/datamapper"&gt;@datamapper&lt;/a&gt; on twitter too :)&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re eager to learn more you can always join #datamapper IRC channel. I also understand that this post doesn&amp;#8217;t answer many possible questions &amp;#8211; feel free to ask them in the comments.&lt;/p&gt;
&lt;p&gt;&lt;a class="a2a_button_twitter_tweet addtoany_special_service" data-count="horizontal" data-url="http://solnic.eu/2012/01/10/ruby-datamapper-status.html" data-text="Ruby DataMapper Status"&gt;&lt;/a&gt;&lt;a class="a2a_button_google_plusone addtoany_special_service" data-href="http://solnic.eu/2012/01/10/ruby-datamapper-status.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_facebook_like addtoany_special_service" data-href="http://solnic.eu/2012/01/10/ruby-datamapper-status.html"&gt;&lt;/a&gt;&lt;a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F01%2F10%2Fruby-datamapper-status.html&amp;amp;linkname=Ruby%20DataMapper%20Status" title="Reddit" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/&gt;&lt;/a&gt;&lt;a class="a2a_button_dzone" href="http://www.addtoany.com/add_to/dzone?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F01%2F10%2Fruby-datamapper-status.html&amp;amp;linkname=Ruby%20DataMapper%20Status" title="DZone" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/dzone.png" width="16" height="16" alt="DZone"/&gt;&lt;/a&gt;&lt;a class="a2a_button_linkedin" href="http://www.addtoany.com/add_to/linkedin?linkurl=http%3A%2F%2Fsolnic.eu%2F2012%2F01%2F10%2Fruby-datamapper-status.html&amp;amp;linkname=Ruby%20DataMapper%20Status" title="LinkedIn" rel="nofollow" target="_blank"&gt;&lt;img src="http://solnic.eu/wp-content/plugins/add-to-any/icons/linkedin.png" width="16" height="16" alt="LinkedIn"/&gt;&lt;/a&gt;&lt;a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fsolnic.eu%2F2012%2F01%2F10%2Fruby-datamapper-status.html&amp;amp;title=Ruby%20DataMapper%20Status" id="wpa2a_16"&gt;Share/Bookmark&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/Jlg-obA72wU" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://solnic.eu/2012/01/10/ruby-datamapper-status.html#comments" thr:count="22" />
		<link rel="replies" type="application/atom+xml" href="http://solnic.eu/2012/01/10/ruby-datamapper-status.html/feed/atom" thr:count="22" />
		<thr:total>22</thr:total>
	<feedburner:origLink>http://solnic.eu/2012/01/10/ruby-datamapper-status.html</feedburner:origLink></entry>
	</feed><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: enhanced

Served from: solnic.eu @ 2012-05-12 13:14:12 -->

