<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Virtuous Code</title>
	
	<link>http://avdi.org/devblog</link>
	<description>"...the three great virtues of a programmer: laziness, impatience, and hubris." -- Larry Wall</description>
	<lastBuildDate>Mon, 06 Feb 2012 18:10:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/VirtuousCode" /><feedburner:info uri="virtuouscode" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>VirtuousCode</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Editing Directory Trees in Emacs</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/bXtZhmdI6M0/</link>
		<comments>http://avdi.org/devblog/2012/02/06/editing-directory-trees-in-emacs/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 14:30:14 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Screencasts]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[find]]></category>
		<category><![CDATA[ls]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=2023</guid>
		<description><![CDATA[In which I demonstrate how to use Emacs to edit a directory tree just like you'd edit an ordinary file. <a href="http://avdi.org/devblog/2012/02/06/editing-directory-trees-in-emacs/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><iframe width="640" height="480" src="http://www.youtube.com/embed/3csYjWbwMrE" frameborder="0" allowfullscreen></iframe></p>
<p style="text-align: left;">Sorry about the recording being cut off at the bottom. Tools demonstrated:</p>
<ul>
<li><a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html#Dired">Dired</a></li>
<li><a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Dired-and-Find.html">find-dired</a></li>
<li><a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Wdired.html">Writable Dired</a></li>
<li><a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Query-Replace.html#Query-Replace">query-replace</a></li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=bXtZhmdI6M0:xRZrP0HI6bY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=bXtZhmdI6M0:xRZrP0HI6bY:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=bXtZhmdI6M0:xRZrP0HI6bY:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=bXtZhmdI6M0:xRZrP0HI6bY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=bXtZhmdI6M0:xRZrP0HI6bY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=bXtZhmdI6M0:xRZrP0HI6bY:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=bXtZhmdI6M0:xRZrP0HI6bY:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=bcOpcFrp8Mo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/bXtZhmdI6M0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2012/02/06/editing-directory-trees-in-emacs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2012/02/06/editing-directory-trees-in-emacs/</feedburner:origLink></item>
		<item>
		<title>On Module Integrity</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/vdEV6SY2Aec/</link>
		<comments>http://avdi.org/devblog/2012/02/03/on-module-integrity/#comments</comments>
		<pubDate>Fri, 03 Feb 2012 05:00:00 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[modules]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=2018</guid>
		<description><![CDATA[A reply to Josh Cheek's post "Modules called, they want their integrity back". <a href="http://avdi.org/devblog/2012/02/03/on-module-integrity/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Goodness, such strong but mixed feelings provoked by this article: <a href="http://blog.8thlight.com/josh-cheek/2012/02/03/modules-called-they-want-their-integrity-back.html">Modules called, they want their integrity back.</a> On the one hand: yes! But on the other: no! </p>
<p> Having used Ruby for upwards of ten years, I have no trouble thinking of <code>#include</code> (and its callback partner-in-crime <code>#included</code>) as just another method. To some degree I think it&#8217;s bringing biases in from less dynamic languages to expect Ruby built-in methods like <code>#include</code> to behave like immutable keywords. </p>
<p> To that end, I think I have a looser idea of the &#8220;correct&#8221; semantics of <code>#include</code> than Josh Cheek does. <code>#include</code> / <code>#included</code> includes new functionality into a class (or module). How they do that is <strong>typically</strong> to add the referenced module to the inheritance chain and copy in constants. But I have no fundamental problem with more exotic methods of bringing in new functionality. </p>
<p> On the other hand, I <strong>do</strong> have a slight problem with adding zillions of public class methods in order to establish a some kind of declarative mini-language at class level; methods which then overstay their welcome and clutter up the class API. A chief offender is my usual punching-bag, ActiveRecord: </p>
<pre class="src src-ruby">require<span class="org-whitespace-space"> </span><span class="org-string">'active_record'</span>
<span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">Foo</span>;<span class="org-whitespace-space"> </span><span class="org-keyword">end</span>
<span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">Bar</span><span class="org-whitespace-space"> </span>&lt;<span class="org-whitespace-space"> </span><span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>;<span class="org-whitespace-space"> </span><span class="org-keyword">end</span>
<span class="org-type">Foo</span>.public_methods.size<span class="org-whitespace-space"> </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">=&gt;</span><span class="org-whitespace-space"> </span><span class="org-comment">153</span>
<span class="org-type">Bar</span>.public_methods.size<span class="org-whitespace-space"> </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">=&gt;</span><span class="org-whitespace-space"> </span><span class="org-comment">481</span>
</pre>
<p> Holy mackeral! A whopping 328 methods added to the public class API! And that&#8217;s calculated <strong>after</strong> taking into account all the methods which ActiveSupport adds to every class in the system; before requiring <code>active_record</code> the public class method count is 97. </p>
<p> Most of those methods are declarative &#8220;macros&#8221; which will only ever be used in the class definition: methods like <code>has_many</code>, <code>belongs_to</code>, and <code>validates</code>. But they linger around long after the class is fully defined, like that guy who&#8217;s still snoring on your couch at noon the day after a party. </p>
<p> I&#8217;ve started to experiment with alternatives to littering classes with &#8220;construction macros&#8221; which stick around after they have outlived their usefulness. Here&#8217;s one approach I&#8217;ve been playing with: </p>
<pre class="src src-ruby">require<span class="org-whitespace-space"> </span><span class="org-string">'make_believe_active_record'</span>

<span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">Post</span>
<span class="org-whitespace-space">  </span><span class="org-type">ActiveRecord</span>.build(<span class="org-variable-name">self</span>)<span class="org-whitespace-space"> </span><span class="org-keyword">do</span>
<span class="org-whitespace-space">    </span>has_many<span class="org-whitespace-space"> </span><span class="org-constant">:tags</span>
<span class="org-whitespace-space">    </span>belongs_to<span class="org-whitespace-space"> </span><span class="org-constant">:category</span>
<span class="org-whitespace-space">    </span>validates<span class="org-whitespace-space"> </span><span class="org-constant">:title</span>,<span class="org-whitespace-space"> </span><span class="org-constant">:unique</span><span class="org-whitespace-space"> </span>=&gt;<span class="org-whitespace-space"> </span><span class="org-variable-name">true</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>

<span class="org-whitespace-space">  </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">has_many,</span><span class="org-whitespace-space"> </span><span class="org-comment">belongs_to</span><span class="org-whitespace-space"> </span><span class="org-comment">etc.</span><span class="org-whitespace-space"> </span><span class="org-comment">are</span><span class="org-whitespace-space"> </span><span class="org-comment">not</span><span class="org-whitespace-space"> </span><span class="org-comment">accessible</span><span class="org-whitespace-space"> </span><span class="org-comment">here</span>
<span class="org-keyword">end</span>
</pre>
<p> At the risk of being a little bit more verbose, this pattern controls the context in which the additional &#8220;macro&#8221; methods are active. As an added bonus, it gives the implementor a convenient point, at the end of the block execution, to do any post-processing of the data structures that were set up by the builder macros. </p>
<p> Some of Josh&#8217;s alternatives reminded me of these experiments. I definitely think we share some concerns, although I think we&#8217;re coming at it from slightly different angles. For me, it&#8217;s more about avoiding namespace pollution: staying out of the global namespace, avoiding adding methods to base classes (<strong>cough</strong> <code>acts_as_*</code> <strong>cough</strong>), and not cluttering up classes with methods which serve no purpose once the class setup is finished. </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=vdEV6SY2Aec:FD6j7MHpQ6U:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=vdEV6SY2Aec:FD6j7MHpQ6U:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=vdEV6SY2Aec:FD6j7MHpQ6U:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=vdEV6SY2Aec:FD6j7MHpQ6U:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=vdEV6SY2Aec:FD6j7MHpQ6U:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=vdEV6SY2Aec:FD6j7MHpQ6U:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=vdEV6SY2Aec:FD6j7MHpQ6U:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=bcOpcFrp8Mo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/vdEV6SY2Aec" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2012/02/03/on-module-integrity/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2012/02/03/on-module-integrity/</feedburner:origLink></item>
		<item>
		<title>Ruby Thread Locals are also Fiber-Local</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/f9dZDJvVc-c/</link>
		<comments>http://avdi.org/devblog/2012/02/02/ruby-thread-locals-are-also-fiber-local/#comments</comments>
		<pubDate>Thu, 02 Feb 2012 05:00:00 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[fibers]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[threads]]></category>
		<category><![CDATA[variables]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=2016</guid>
		<description><![CDATA[I was briefly concerned that thread-local variables would not also be Fiber-local, since fibers have their own stack. This would be a problem for any code which uses thread-local variables to delimit a stack context, e.g. to implement dynamically-scoped variables &#8230; <a href="http://avdi.org/devblog/2012/02/02/ruby-thread-locals-are-also-fiber-local/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I was briefly concerned that thread-local variables would not also be Fiber-local, since fibers have their own stack. This would be a problem for any code which uses thread-local variables to delimit a stack context, e.g. to implement <a href="http://c2.com/cgi/wiki?DynamicScoping">dynamically-scoped variables</a> or to <a href="http://www.codebenders.com/code/preventing-recursion-in-ruby/">prevent recursion</a>. My fears, however, were easily allayed. </p>
<pre class="src src-ruby">f<span class="org-whitespace-space"> </span>=<span class="org-whitespace-space"> </span><span class="org-type">Fiber</span>.new<span class="org-whitespace-space"> </span><span class="org-keyword">do</span>
<span class="org-whitespace-space">  </span>puts<span class="org-whitespace-space"> </span><span class="org-string">"Fiber</span><span class="org-whitespace-space"> </span><span class="org-string">started"</span>
<span class="org-whitespace-space">  </span><span class="org-type">Thread</span>.current[<span class="org-constant">:in_fiber_context</span>]<span class="org-whitespace-space"> </span>=<span class="org-whitespace-space"> </span><span class="org-variable-name">true</span>
<span class="org-whitespace-space">  </span><span class="org-type">Fiber</span>.yield
<span class="org-whitespace-space">  </span>puts<span class="org-whitespace-space"> </span><span class="org-string">"Fiber-local</span><span class="org-whitespace-space"> </span><span class="org-string">value:</span><span class="org-whitespace-space"> </span><span class="org-variable-name">#{Thread.current[:in_fiber_context].inspect}</span><span class="org-string">"</span>
<span class="org-whitespace-space">  </span>puts<span class="org-whitespace-space"> </span><span class="org-string">"Fiber</span><span class="org-whitespace-space"> </span><span class="org-string">finished"</span>
<span class="org-keyword">end</span>

puts<span class="org-whitespace-space"> </span><span class="org-string">"Starting</span><span class="org-whitespace-space"> </span><span class="org-string">value:</span><span class="org-whitespace-space"> </span><span class="org-variable-name">#{Thread.current[:in_fiber_context].inspect}</span><span class="org-string">"</span>
f.resume
puts<span class="org-whitespace-space"> </span><span class="org-string">"Value</span><span class="org-whitespace-space"> </span><span class="org-string">outside</span><span class="org-whitespace-space"> </span><span class="org-string">of</span><span class="org-whitespace-space"> </span><span class="org-string">fiber:</span><span class="org-whitespace-space"> </span><span class="org-variable-name">#{Thread.current[:in_fiber_context].inspect}</span><span class="org-string">"</span>
f.resume
puts<span class="org-whitespace-space"> </span><span class="org-string">"Ending</span><span class="org-whitespace-space"> </span><span class="org-string">value:</span><span class="org-whitespace-space"> </span><span class="org-variable-name">#{Thread.current[:in_fiber_context].inspect}</span><span class="org-string">"</span>
<span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">&gt;&gt;</span><span class="org-whitespace-space"> </span><span class="org-comment">Starting</span><span class="org-whitespace-space"> </span><span class="org-comment">value:</span><span class="org-whitespace-space"> </span><span class="org-comment">nil</span>
<span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">&gt;&gt;</span><span class="org-whitespace-space"> </span><span class="org-comment">Fiber</span><span class="org-whitespace-space"> </span><span class="org-comment">started</span>
<span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">&gt;&gt;</span><span class="org-whitespace-space"> </span><span class="org-comment">Value</span><span class="org-whitespace-space"> </span><span class="org-comment">outside</span><span class="org-whitespace-space"> </span><span class="org-comment">of</span><span class="org-whitespace-space"> </span><span class="org-comment">fiber:</span><span class="org-whitespace-space"> </span><span class="org-comment">nil</span>
<span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">&gt;&gt;</span><span class="org-whitespace-space"> </span><span class="org-comment">Fiber-local</span><span class="org-whitespace-space"> </span><span class="org-comment">value:</span><span class="org-whitespace-space"> </span><span class="org-comment">true</span>
<span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">&gt;&gt;</span><span class="org-whitespace-space"> </span><span class="org-comment">Fiber</span><span class="org-whitespace-space"> </span><span class="org-comment">finished</span>
<span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">&gt;&gt;</span><span class="org-whitespace-space"> </span><span class="org-comment">Ending</span><span class="org-whitespace-space"> </span><span class="org-comment">value:</span><span class="org-whitespace-space"> </span><span class="org-comment">nil</span>
</pre>
<p> Once again, Ruby gets the little things right. </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=f9dZDJvVc-c:cYpln60MkJk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=f9dZDJvVc-c:cYpln60MkJk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=f9dZDJvVc-c:cYpln60MkJk:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=f9dZDJvVc-c:cYpln60MkJk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=f9dZDJvVc-c:cYpln60MkJk:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=f9dZDJvVc-c:cYpln60MkJk:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=f9dZDJvVc-c:cYpln60MkJk:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=bcOpcFrp8Mo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/f9dZDJvVc-c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2012/02/02/ruby-thread-locals-are-also-fiber-local/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2012/02/02/ruby-thread-locals-are-also-fiber-local/</feedburner:origLink></item>
		<item>
		<title>Preventing Recursion in Ruby</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/Fk4WqYFyzvU/</link>
		<comments>http://avdi.org/devblog/2012/02/01/preventing-recursion-in-ruby-2/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 14:00:20 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[macros]]></category>
		<category><![CDATA[metaprogramming]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=2012</guid>
		<description><![CDATA[A new post on the CodeBenders blog about how to prevent a method from accidentally falling into an infinite recursion. <a href="http://avdi.org/devblog/2012/02/01/preventing-recursion-in-ruby-2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Sometimes you need to prevent code from executing recursively. I had to do this recently in order to prevent an infinite recursion in ActiveRecord callbacks. A before-save hook needed to save a parent model attribute, which because of an :autosave option would then try to save the child model, which would then try to save the parent… and so on until the stack overflowed.</p>
<p><a href="http://www.codebenders.com/code/preventing-recursion-in-ruby/">Read on at the CodeBenders blog&#8230;</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=Fk4WqYFyzvU:n_LI4psQfNw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=Fk4WqYFyzvU:n_LI4psQfNw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=Fk4WqYFyzvU:n_LI4psQfNw:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=Fk4WqYFyzvU:n_LI4psQfNw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=Fk4WqYFyzvU:n_LI4psQfNw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=Fk4WqYFyzvU:n_LI4psQfNw:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=Fk4WqYFyzvU:n_LI4psQfNw:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=bcOpcFrp8Mo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/Fk4WqYFyzvU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2012/02/01/preventing-recursion-in-ruby-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2012/02/01/preventing-recursion-in-ruby-2/</feedburner:origLink></item>
		<item>
		<title>Decoration is best, except when it isn’t</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/CqLueiW936g/</link>
		<comments>http://avdi.org/devblog/2012/01/31/decoration-is-best-except-when-it-isnt/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 14:00:00 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=2002</guid>
		<description><![CDATA[I think by now we all know to prefer composition over inheritance. But in a language with a lot of options, what&#8217;s the best kind of composition to use? Composing an adventure Consider an adventure game, with objects representing player &#8230; <a href="http://avdi.org/devblog/2012/01/31/decoration-is-best-except-when-it-isnt/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I think by now we all know to <a href="http://en.wikipedia.org/wiki/Composition_over_inheritance">prefer composition over inheritance</a>. But in a language with a lot of options, what&#8217;s the best kind of composition to use? </p>
<div id="outline-container-1" class="outline-3">
<h3 id="sec-1">Composing an adventure</h3>
<div class="outline-text-3" id="text-1">
<p> Consider an adventure game, with objects representing player characters. </p>
<pre class="src src-ruby"><span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">Character</span>
<span class="org-whitespace-space">  </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">...</span>
<span class="org-keyword">end</span>
</pre>
<p> A <code>Character</code> can be described: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">Character</span>
<span class="org-whitespace-space">  </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">...</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">describe</span>
<span class="org-whitespace-space">    </span>puts<span class="org-whitespace-space"> </span><span class="org-string">"You</span><span class="org-whitespace-space"> </span><span class="org-string">are</span><span class="org-whitespace-space"> </span><span class="org-string">a</span><span class="org-whitespace-space"> </span><span class="org-string">dashing,</span><span class="org-whitespace-space"> </span><span class="org-string">rugged</span><span class="org-whitespace-space"> </span><span class="org-string">adventurer."</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>
<span class="org-whitespace-space">  </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">...</span>
<span class="org-keyword">end</span>
</pre>
<p> A <code>Character</code> can look, listen, and smell his environment: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">Character</span>
<span class="org-whitespace-space">  </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">...</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">look</span>
<span class="org-whitespace-space">    </span>list(<span class="org-string">"You</span><span class="org-whitespace-space"> </span><span class="org-string">can</span><span class="org-whitespace-space"> </span><span class="org-string">see"</span>,<span class="org-whitespace-space"> </span>[<span class="org-string">"a</span><span class="org-whitespace-space"> </span><span class="org-string">lightning</span><span class="org-whitespace-space"> </span><span class="org-string">bug"</span>,<span class="org-whitespace-space"> </span><span class="org-string">"a</span><span class="org-whitespace-space"> </span><span class="org-string">guttering</span><span class="org-whitespace-space"> </span><span class="org-string">candle"</span>])
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>

<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">listen</span>
<span class="org-whitespace-space">    </span>list(<span class="org-string">"You</span><span class="org-whitespace-space"> </span><span class="org-string">hear"</span>,<span class="org-whitespace-space"> </span>[<span class="org-string">"a</span><span class="org-whitespace-space"> </span><span class="org-string">distant</span><span class="org-whitespace-space"> </span><span class="org-string">waterfall"</span>])
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>

<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">smell</span>
<span class="org-whitespace-space">    </span>list(<span class="org-string">"You</span><span class="org-whitespace-space"> </span><span class="org-string">smell"</span>,<span class="org-whitespace-space"> </span>[<span class="org-string">"egg</span><span class="org-whitespace-space"> </span><span class="org-string">salad"</span>])
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>

<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">list</span>(prefix,<span class="org-whitespace-space"> </span>objects)
<span class="org-whitespace-space">    </span>objects.each<span class="org-whitespace-space"> </span><span class="org-keyword">do</span><span class="org-whitespace-space"> </span>|o|
<span class="org-whitespace-space">      </span>puts<span class="org-whitespace-space"> </span><span class="org-string">"</span><span class="org-variable-name">#{prefix}</span><span class="org-whitespace-space"> </span><span class="org-variable-name">#{o}</span><span class="org-string">."</span>
<span class="org-whitespace-space">    </span><span class="org-keyword">end</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>
<span class="org-whitespace-space">  </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">...</span>
<span class="org-keyword">end</span>
</pre>
<pre class="src src-ruby">require<span class="org-whitespace-space"> </span><span class="org-string">'./decoration-vs-extension'</span>
cohen<span class="org-whitespace-space"> </span>=<span class="org-whitespace-space"> </span><span class="org-type">Character</span>.new
cohen.describe
cohen.look
cohen.listen
</pre>
<pre class="example">
You are a dashing, rugged adventurer.
You can see a lightning bug.
You can see a guttering candle.
You hear a distant waterfall.
</pre>
<p> The character can also consult all of his senses at once: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">Character</span>
<span class="org-whitespace-space">  </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">...</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">observe</span>
<span class="org-whitespace-space">    </span>look
<span class="org-whitespace-space">    </span>listen
<span class="org-whitespace-space">    </span>smell
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>
<span class="org-whitespace-space">  </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">...</span>
<span class="org-keyword">end</span>
</pre>
<pre class="src src-ruby">require<span class="org-whitespace-space"> </span><span class="org-string">'./decoration-vs-extension'</span>
cohen<span class="org-whitespace-space"> </span>=<span class="org-whitespace-space"> </span><span class="org-type">Character</span>.new
cohen.observe
</pre>
<pre class="example">
You can see a lightning bug.
You can see a guttering candle.
You hear a distant waterfall.
You smell egg salad.
</pre>
<p> Characters can have various effects conferred upon them by items, potions, etc. A simple example is a hat: </p>
<pre class="src src-ruby">require<span class="org-whitespace-space"> </span><span class="org-string">'delegate'</span>
<span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">BowlerHatDecorator</span><span class="org-whitespace-space"> </span>&lt;<span class="org-whitespace-space"> </span><span class="org-type">SimpleDelegator</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">describe</span>
<span class="org-whitespace-space">    </span><span class="org-keyword">super</span>
<span class="org-whitespace-space">    </span>puts<span class="org-whitespace-space"> </span><span class="org-string">"A</span><span class="org-whitespace-space"> </span><span class="org-string">jaunty</span><span class="org-whitespace-space"> </span><span class="org-string">bowler</span><span class="org-whitespace-space"> </span><span class="org-string">cap</span><span class="org-whitespace-space"> </span><span class="org-string">sits</span><span class="org-whitespace-space"> </span><span class="org-string">atop</span><span class="org-whitespace-space"> </span><span class="org-string">your</span><span class="org-whitespace-space"> </span><span class="org-string">head."</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>
<span class="org-keyword">end</span>
</pre>
<p> At each turn of the game, the <code>Character</code> object will be decorated with whatever effects are currently active, and then a user command will be performed: </p>
<pre class="src src-ruby">require<span class="org-whitespace-space"> </span><span class="org-string">'./decoration-vs-extension'</span>
cohen<span class="org-whitespace-space"> </span>=<span class="org-whitespace-space"> </span><span class="org-type">BowlerHatDecorator</span>.new(<span class="org-type">Character</span>.new)
cohen.describe
</pre>
<pre class="example">
You are a dashing, rugged adventurer.
A jaunty bowler cap sits atop your head.
</pre>
</p></div>
</p></div>
<div id="outline-container-2" class="outline-3">
<h3 id="sec-2">Seeing in the dark</h3>
<div class="outline-text-3" id="text-2">
<p> A more interesting effect is conferred by an infravision potion. It enables your character to see in the dark. </p>
<pre class="src src-ruby"><span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">InfravisionPotionDecorator</span><span class="org-whitespace-space"> </span>&lt;<span class="org-whitespace-space"> </span><span class="org-type">SimpleDelegator</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">describe</span>
<span class="org-whitespace-space">    </span><span class="org-keyword">super</span>
<span class="org-whitespace-space">    </span>puts<span class="org-whitespace-space"> </span><span class="org-string">"Your</span><span class="org-whitespace-space"> </span><span class="org-string">eyes</span><span class="org-whitespace-space"> </span><span class="org-string">glow</span><span class="org-whitespace-space"> </span><span class="org-string">dull</span><span class="org-whitespace-space"> </span><span class="org-string">red."</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>

<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">look</span>
<span class="org-whitespace-space">    </span><span class="org-keyword">super</span>
<span class="org-whitespace-space">    </span>look_infrared
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>

<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">look_infrared</span>
<span class="org-whitespace-space">    </span>list(<span class="org-string">"You</span><span class="org-whitespace-space"> </span><span class="org-string">can</span><span class="org-whitespace-space"> </span><span class="org-string">see"</span>,<span class="org-whitespace-space"> </span>[<span class="org-string">"the</span><span class="org-whitespace-space"> </span><span class="org-string">ravenous</span><span class="org-whitespace-space"> </span><span class="org-string">bugblatter</span><span class="org-whitespace-space"> </span><span class="org-string">beast</span><span class="org-whitespace-space"> </span><span class="org-string">of</span><span class="org-whitespace-space"> </span><span class="org-string">traal"</span>])
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>
<span class="org-keyword">end</span>
</pre>
<p> While the character is experiencing the effects of an <a href="http://nethack.wikia.com/wiki/Infravision">infravision</a> potion, his powers of observation increase: </p>
<pre class="src src-ruby">require<span class="org-whitespace-space"> </span><span class="org-string">'./decoration-vs-extension'</span>
cohen<span class="org-whitespace-space"> </span>=<span class="org-whitespace-space"> </span><span class="org-type">InfravisionPotionDecorator</span>.new(<span class="org-type">Character</span>.new)
cohen.describe
cohen.look
</pre>
<pre class="example">
You are a dashing, rugged adventurer.
Your eyes glow dull red.
You can see a lightning bug.
You can see a guttering candle.
You can see the ravenous bugblatter beast of traal.
</pre>
<p> There&#8217;s just one little problem that crops up when the <code>#observe</code> method is called. </p>
<pre class="src src-ruby">require<span class="org-whitespace-space"> </span><span class="org-string">'./decoration-vs-extension'</span>
cohen<span class="org-whitespace-space"> </span>=<span class="org-whitespace-space"> </span><span class="org-type">InfravisionPotionDecorator</span>.new(<span class="org-type">Character</span>.new)
cohen.observe
</pre>
<pre class="example">
You can see a lightning bug.
You can see a guttering candle.
You hear a distant waterfall.
You smell egg salad.
</pre>
<p> Hey, where&#8217;d that bugblatter beast go? </p>
<p> The <code>Character#observe</code> method calls <code>#look</code>&mdash;but since the wrapped object has no knowledge whatsoever of the <code>InfravisionPotionDecorator</code>, it calls the original definition of <code>#look</code>, not the one which also calls <code>#look_infrared</code>. </p>
<p> Now, granted, this flaw actually works out in our intrepid adventurer&#8217;s favor, since the ravenous bugblatter beast of Traal is so stupid it thinks that if you can&#8217;t see it, it can&#8217;t see you. But never mind that: it&#8217;s still a bug, and bugs must be blattered. </p>
</p></div>
</p></div>
<div id="outline-container-3" class="outline-3">
<h3 id="sec-3">A solution that&#8217;s all wet</h3>
<div class="outline-text-3" id="text-3">
<p> We could patch this flaw by overriding <code>#observe</code> as well in the decorator: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">InfravisionPotionDecorator</span><span class="org-whitespace-space"> </span>&lt;<span class="org-whitespace-space"> </span><span class="org-type">SimpleDelegator</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">observe</span>
<span class="org-whitespace-space">    </span>look
<span class="org-whitespace-space">    </span>listen
<span class="org-whitespace-space">    </span>smell
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>
<span class="org-keyword">end</span>
</pre>
<p> Yuck! This is the exact same implementation as in <code>Character</code>, just copied and pasted so that the correct implementaiton of <code>#look</code> will be called. Clearly this is non-DRY. But even worse, we&#8217;ve introduced a nasty variety of <a href="http://blog.rubybestpractices.com/posts/gregory/056-issue-24-connascence.html">connascence</a>. Every time we introduces a new <code>Character</code> method which calls <code>#look</code>, we&#8217;ll have to cull through every single effect decorator which overrides <code>#look</code>, adding copy-and-pasted versions of the new method so that it doesn&#8217;t accidentally ignore the effect-wrapped version. Double yuck! </p>
</p></div>
</p></div>
<div id="outline-container-4" class="outline-3">
<h3 id="sec-4">Modules to the rescue</h3>
<div class="outline-text-3" id="text-4">
<p> In Ruby, there is an easy solution: extend the character with a module instead of a decorator. </p>
<pre class="src src-ruby"><span class="org-keyword">module</span><span class="org-whitespace-space"> </span><span class="org-type">InfravisionPotionModule</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">describe</span>
<span class="org-whitespace-space">    </span><span class="org-keyword">super</span>
<span class="org-whitespace-space">    </span>puts<span class="org-whitespace-space"> </span><span class="org-string">"Your</span><span class="org-whitespace-space"> </span><span class="org-string">eyes</span><span class="org-whitespace-space"> </span><span class="org-string">glow</span><span class="org-whitespace-space"> </span><span class="org-string">dull</span><span class="org-whitespace-space"> </span><span class="org-string">red."</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>

<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">look</span>
<span class="org-whitespace-space">    </span><span class="org-keyword">super</span>
<span class="org-whitespace-space">    </span>look_infrared
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>

<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">look_infrared</span>
<span class="org-whitespace-space">    </span>list(<span class="org-string">"You</span><span class="org-whitespace-space"> </span><span class="org-string">can</span><span class="org-whitespace-space"> </span><span class="org-string">see"</span>,<span class="org-whitespace-space"> </span>[<span class="org-string">"the</span><span class="org-whitespace-space"> </span><span class="org-string">ravenous</span><span class="org-whitespace-space"> </span><span class="org-string">bugblatter</span><span class="org-whitespace-space"> </span><span class="org-string">beast</span><span class="org-whitespace-space"> </span><span class="org-string">of</span><span class="org-whitespace-space"> </span><span class="org-string">traal"</span>])
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>
<span class="org-keyword">end</span>
</pre>
<pre class="src src-ruby">require<span class="org-whitespace-space"> </span><span class="org-string">'./decoration-vs-extension'</span>
cohen<span class="org-whitespace-space"> </span>=<span class="org-whitespace-space"> </span><span class="org-type">Character</span>.new.extend(<span class="org-type">InfravisionPotionModule</span>)
cohen.observe
</pre>
<pre class="example">
You can see a lightning bug.
You can see a guttering candle.
You can see the ravenous bugblatter beast of traal.
You hear a distant waterfall.
You smell egg salad.
</pre>
<p> This time the overridden method is added directly to the object via its singleton class. So even the object&#8217;s own unmodified methods get the new infravision version of <code>#look</code>. </p>
<p> Sadly, by enabling him to see the monster we have sealed our protagonists&#8217;s fate. But at least we fixed the bug! </p>
</p></div>
</p></div>
<div id="outline-container-5" class="outline-3">
<h3 id="sec-5">Other solutions</h3>
<div class="outline-text-3" id="text-5">
<p> That&#8217;s not the only way to fix the problem. We might, for instance, decompose our <code>Character</code> into individual body parts, with separate attributes for <code>eyes</code>, <code>nose</code>, and <code>ears</code>. The <code>Character</code> could then delegate the individual senses to their respective organs: </p>
<pre class="src src-ruby">require<span class="org-whitespace-space"> </span><span class="org-string">'forwardable'</span>
<span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">Character</span>
<span class="org-whitespace-space">  </span>extend<span class="org-whitespace-space"> </span><span class="org-type">Forwardable</span>

<span class="org-whitespace-space">  </span>attr_accessor<span class="org-whitespace-space"> </span><span class="org-constant">:eyes</span>
<span class="org-whitespace-space">  </span>attr_accessor<span class="org-whitespace-space"> </span><span class="org-constant">:ears</span>
<span class="org-whitespace-space">  </span>attr_accessor<span class="org-whitespace-space"> </span><span class="org-constant">:nose</span>

<span class="org-whitespace-space">  </span>def_delegator<span class="org-whitespace-space"> </span><span class="org-constant">:eyes</span>,<span class="org-whitespace-space"> </span><span class="org-constant">:look</span>
<span class="org-whitespace-space">  </span>def_delegator<span class="org-whitespace-space"> </span><span class="org-constant">:ears</span>,<span class="org-whitespace-space"> </span><span class="org-constant">:lisen</span>
<span class="org-whitespace-space">  </span>def_delegator<span class="org-whitespace-space"> </span><span class="org-constant">:nose</span>,<span class="org-whitespace-space"> </span><span class="org-constant">:smell</span>
<span class="org-keyword">end</span>
</pre>
<p> A potion of infravision might then replace the character&#8217;s eyes with infrared-enhanced ones: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">InfravisionPotionDecorator</span><span class="org-whitespace-space"> </span>&lt;<span class="org-whitespace-space"> </span><span class="org-type">SimpleDelegator</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">class</span><span class="org-whitespace-space"> </span><span class="org-type">EyesDecorator</span><span class="org-whitespace-space"> </span>&lt;<span class="org-whitespace-space"> </span><span class="org-type">SimpleDelegator</span>
<span class="org-whitespace-space">    </span><span class="org-comment-delimiter">#</span><span class="org-whitespace-space"> </span><span class="org-comment">...</span>
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>

<span class="org-whitespace-space">  </span><span class="org-keyword">def</span><span class="org-whitespace-space"> </span><span class="org-function-name">initialize</span>(character)
<span class="org-whitespace-space">    </span><span class="org-keyword">super</span>(character)
<span class="org-whitespace-space">    </span>character.eyes<span class="org-whitespace-space"> </span>=<span class="org-whitespace-space"> </span><span class="org-type">EyesDecorator</span>.new(character.eyes)
<span class="org-whitespace-space">  </span><span class="org-keyword">end</span>
<span class="org-keyword">end</span>
</pre>
<p> &hellip;but this is an awful lot of code and ceremony. It might make sense someday, but right now it feels like massive overkill. The module extension approach, by contrast, is only a small change from our original version. </p>
</p></div>
</p></div>
<div id="outline-container-6" class="outline-3">
<h3 id="sec-6">Are decorators overrated?</h3>
<div class="outline-text-3" id="text-6">
<p> So what can we learn from this? When composing objects, Is it always better to use module extension than decoration? </p>
<p> In a word, no. For one thing, decoration is a simpler structure to understand. Given object <code>A</code> wrapped in object <code>B</code> wrapped in object <code>C</code>, it&#8217;s easy to reason about how method calls will be handled. They&#8217;ll always go one-way: a method in object <code>A</code> will never reference a method in <code>B</code> or <code>C</code>.By contrast, method calls in a module-extended object can bounce around the inheritance heirarchy in unexpected ways. </p>
<p> A second consideration is that once you&#8217;ve extended an object with a module, its behavior is changed for <strong>all</strong> clients, including itself. You can&#8217;t interact with the &#8220;unadorned&#8221; object anymore. You might extend an object for your own purposes, then pass it to a third-party method which doesn&#8217;t understand the modified behavior of the object and barfs as a result. </p>
<p> Finally, there&#8217;s a performance penalty. While it varies from implementation to implementation, dynamically extending objects can slow down your code as a result of the method cache beign invalidated. Of course, as with all performance-related guidelines, be sure to profile before making any code changes based on this point. </p>
</p></div>
</p></div>
<div id="outline-container-7" class="outline-3">
<h3 id="sec-7">Conclusion</h3>
<div class="outline-text-3" id="text-7">
<p> Decoration and module extension are both viable ways to compose objects in Ruby. Which to use is not a simple black-or-white choice; it depends on the purpose of the composition.  </p>
<p> For applications where you want to adorn an object with some extra functionality, or modify how it presents itself, a decorator is probably the best bet. Decorators are great for creating Presenters, where we just want to change an object&#8217;s &#8220;face&#8221; in a specific context.  </p>
<p> On the other hand, when building up a composite object at runtime object out of individual &#8220;aspects&#8221; or &#8220;facets&#8221;, module extension may make more sense. Judicious use of module extension can lead to a kind of &#8220;emergent behavior&#8221; which is hard to replicate with decoration or delegation. </p>
<p> At least, this has been my experience. Got some experiences or opinions on decoration vs. module extension? Feel free to leave a note in the comments! </p>
</div></div>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=CqLueiW936g:RBnTFJBWdQU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=CqLueiW936g:RBnTFJBWdQU:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=CqLueiW936g:RBnTFJBWdQU:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=CqLueiW936g:RBnTFJBWdQU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=CqLueiW936g:RBnTFJBWdQU:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=CqLueiW936g:RBnTFJBWdQU:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=CqLueiW936g:RBnTFJBWdQU:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=bcOpcFrp8Mo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/CqLueiW936g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2012/01/31/decoration-is-best-except-when-it-isnt/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2012/01/31/decoration-is-best-except-when-it-isnt/</feedburner:origLink></item>
		<item>
		<title>A Game Development Curriculum</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/PmpygPjKtrw/</link>
		<comments>http://avdi.org/devblog/2012/01/24/a-game-development-curriculum/#comments</comments>
		<pubDate>Tue, 24 Jan 2012 14:30:00 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Education]]></category>
		<category><![CDATA[books]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[education]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=1996</guid>
		<description><![CDATA[Along with every other hacker on the planet, I got into programming because I wanted to write games. It wasn&#8217;t long at all, though, before I learned that the greatest game of all is teaching the machine to do your &#8230; <a href="http://avdi.org/devblog/2012/01/24/a-game-development-curriculum/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Along with every other hacker on the planet, I got into programming because I wanted to write games. It wasn&#8217;t long at all, though, before I learned that the greatest game of all is teaching the machine to do your will and get things done. I lost interest in game development pretty quickly and moved on to systems and application programming.</p>
<p>My son J. is almost 16, and he wants to write games too. However, in his case I have reason to believe he&#8217;s a lot more serious about the &#8220;games&#8221; aspect than I ever was. So I&#8217;m trying to put together a curriculum with an emphasis on game programming. This is a little tricky, since it&#8217;s a sub-field I have little connection to.</p>
<p>Here&#8217;s what I have so far, with many thanks to the folks on Twitter who helped me narrow down the list: (Book links include my Amazon affiliate code.)</p>
<p><strong><a href="http://www.amazon.com/Learn-Program-Second-Facets-Ruby/dp/1934356360%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1934356360"><img class="alignleft" src="http://ecx.images-amazon.com/images/I/51mMkUpi8qL._SL75_.jpg" alt="" width="63" height="75" /></a><a href="http://www.amazon.com/Learn-Program-Second-Facets-Ruby/dp/1934356360%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1934356360">Learn to Program, by Chris Pine</a>.</strong> While I already have him working on <a href="http://hackety.com/">Hackety Hack</a>, I honestly hesitated to make Ruby his first language. Ruby is a programmer&#8217;s language; it has an enormous amount of syntax and many ways to do something. I worry that, as with C++, it will make learning the basics more difficult because it will be hard to separate the fundamentals from the incidentals.</p>
<p>After thinking about it for a while I came around, though. My reasons:</p>
<ol>
<li>Ruby is the language I&#8217;m most fluent in at the moment. I&#8217;ll have no trouble helping him with any roadblocks he might run into.</li>
<li>He&#8217;s going to run into OO programming eventually, and I want his first contact to be with a strongly Alan Kay-inspired language. Rather than having to come around to that understanding the long way round, as I did. So no C++, Java, or Python as a first OO language. That pretty much means Smalltalk or Ruby, and of the two Ruby is probably more generally useful these days.</li>
<li>Finally, there are some Ruby game development bindings like <a href="http://www.libgosu.org/">Gosu</a> that will let him have some fun even before diving into the more hardcore C/C++ stuff.</li>
</ol>
<p>I suppose Javascript would fit the bill as well, and has the advantage of being ever-so-accessible inside the nearest browser. That said, for all that there is a beautiful language hidden in it, Javscript has more than it&#8217;s share of warts. I think in some ways Javascript might have even more of a fundamentals-obscured-by-incidentals problem than Ruby. Tough call though; I could definitely see starting with Javascript, especially if the student were most interested in programming for the web.</p>
<p><strong><a href="http://www.amazon.com/Land-of-Lisp-ebook/dp/B004AE3P4K%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB004AE3P4K"><img class="alignright" src="http://ecx.images-amazon.com/images/I/515ZuOjktML._SL75_.jpg" alt="" width="57" height="75" /></a><a href="http://www.amazon.com/Land-of-Lisp-ebook/dp/B004AE3P4K%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB004AE3P4K">Land of Lisp</a>, by Conrad Barsky.</strong> A timely book: it&#8217;s our next <a href="http://rubyrogues.com/">Ruby Rogues</a> book club book. It&#8217;s about Lisp, which I want to give J. early exposure to, for ever so many reasons. And it&#8217;s about writing games. Win!</p>
<p><strong><a href="http://www.amazon.com/C-Primer-Plus-5th-ebook/dp/B0050G2RA0%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB0050G2RA0"><img class="alignleft" src="http://ecx.images-amazon.com/images/I/41eQuM8js5L._SL75_.jpg" alt="" width="61" height="75" /></a><a href="http://www.amazon.com/C-Primer-Plus-5th-ebook/dp/B0050G2RA0%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB0050G2RA0">C Primer Plus</a>, by Stephen Prata.</strong> For someone interested in web applications I might wait C until much later. But if it&#8217;s games you want to build, you simply can&#8217;t avoid C. Eventually you&#8217;re going to find yourself writing OpenGL or DirectX code. Even if you&#8217;re writing it in a higher level language, chances are the API documentation will be for the C/C++ API, so a basic understanding of C is essential.</p>
<p>And anyway, a little C goes a long way towards understanding just what the hell the computer is up to.</p>
<p><strong><a href="http://www.amazon.com/Blender-Foundations-Essential-Guide-Learning/dp/0240814304%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0240814304"><img class="alignright" src="http://ecx.images-amazon.com/images/I/51BoB-m-Q-L._SL75_.jpg" alt="" width="60" height="75" /></a><a href="http://www.amazon.com/Blender-Foundations-Essential-Guide-Learning/dp/0240814304%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0240814304">Blender Foundations</a>, by Roland Hess.</strong> J. is particularly interested in modeling. I don&#8217;t know jack squat about 3D modeling, but I know Blender is free, Open Source, and widely used. I suspect I won&#8217;t need to give him much guidance in this area beyond giving him the tools he needs to get started.</p>
<p><strong><a href="http://www.amazon.com/Accelerated-C-Practical-Programming-Example/dp/020170353X%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D020170353X"><img class="alignleft" src="http://ecx.images-amazon.com/images/I/51XZZ9RV4BL._SL75_.jpg" alt="" width="60" height="75" /></a>Some C++ book, TBD.</strong> I suspect this will be a necessity for understanding later OpenGL texts and working with various game SDKs. If he does well with the earlier languages I&#8217;ll probably give him <a href="http://www.amazon.com/Accelerated-C-Practical-Programming-Example/dp/020170353X%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D020170353X">Accelerated C++</a>; or maybe I&#8217;ll just go over the basics with him myself without resorting to a text.</p>
<p><strong><a href="http://www.amazon.com/OpenGL-SuperBible-Comprehensive-Tutorial-Reference/dp/0321712617%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0321712617"><img class="alignright" src="http://ecx.images-amazon.com/images/I/51juHDYZeSL._SL75_.jpg" alt="" width="60" height="75" /></a><a href="http://www.amazon.com/OpenGL-SuperBible-Comprehensive-Tutorial-Reference/dp/0321712617%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0321712617">OpenGL SuperBible</a></strong>: this one seems to come reasonably well recommended. And honestly I would <strong>love</strong> to learn some OpenGL along with him.</p>
<p>That&#8217;s what I&#8217;ve got so far. Any other suggestions?</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=PmpygPjKtrw:GC5iP_HKUzI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=PmpygPjKtrw:GC5iP_HKUzI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=PmpygPjKtrw:GC5iP_HKUzI:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=PmpygPjKtrw:GC5iP_HKUzI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=PmpygPjKtrw:GC5iP_HKUzI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=PmpygPjKtrw:GC5iP_HKUzI:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=PmpygPjKtrw:GC5iP_HKUzI:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=bcOpcFrp8Mo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/PmpygPjKtrw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2012/01/24/a-game-development-curriculum/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2012/01/24/a-game-development-curriculum/</feedburner:origLink></item>
		<item>
		<title>ActiveRecord Default Association Extensions</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/BRJjlaRL3i0/</link>
		<comments>http://avdi.org/devblog/2012/01/19/activerecord-default-association-extensions/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 19:07:00 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[activerecord]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=1991</guid>
		<description><![CDATA[How to add helper methods to all associations of a given type, as well as to the model class. <a href="http://avdi.org/devblog/2012/01/19/activerecord-default-association-extensions/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s say we want a helper method <code>#build_fuzzy</code> everywhere we have a collection of socks. </p>
<pre class="src src-ruby"><span class="org-type">Sock</span>.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; #&lt;Sock type: "fuzzy" id: nil drawer_id: nil&gt;</span>
sock_drawer.socks.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; #&lt;Sock type: "fuzzy" id: nil drawer_id: 123&gt;</span>
</pre>
<p> At first we might think to put it in an a collection extension module: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Sock</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  <span class="org-keyword">module</span> <span class="org-type">SockCollectionHelpers</span>
    <span class="org-keyword">def</span> <span class="org-function-name">build_fuzzy</span>
      build(type: <span class="org-string">"fuzzy"</span>)
    <span class="org-keyword">end</span>
  <span class="org-keyword">end</span>
  <span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
<span class="org-keyword">end</span>
</pre>
<p> Now we have to remember to add it to every <code>Sock</code> association: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Drawer</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  has_many <span class="org-constant">:socks</span>, extend: <span class="org-type">Sock</span>::<span class="org-type">SockCollectionHelpers</span>
  <span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
<span class="org-keyword">end</span>
</pre>
<p> And we also need to include it in <code>Sock</code>: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Sock</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  <span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
  extend <span class="org-type">SockCollectionHelpers</span>
<span class="org-keyword">end</span>
</pre>
<p> &hellip;but this doesn&#8217;t work: </p>
<pre class="src src-ruby">sock_drawer.socks.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; #&lt;Sock type: "fuzzy" id: nil drawer_id: 123&gt;</span>
<span class="org-type">Sock</span>.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; Raises no method exception for Sock.build()</span>
</pre>
<p> And anyway, we want this to be available globally without explicitly extending associations. </p>
<p> Next, we try adding a class method to the <code>Sock</code> class. Since ActiveRecord association proxies delegate missing methods to the assoication class, it seems like this should work. </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Sock</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  <span class="org-keyword">def</span> <span class="org-function-name">self.build_fuzzy</span>
    build(type: <span class="org-string">"fuzzy"</span>)
  <span class="org-keyword">end</span>
  <span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
<span class="org-keyword">end</span>
</pre>
<p> This is a complete failure. While the association does forward the <code>.build_fuzzy</code> call to <code>Sock</code>, once in the call it is operating in the context of the class object, which as we saw before has no <code>#build</code> method. </p>
<pre class="src src-ruby">sock_drawer.socks.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">Raises no method exception for Sock.build()</span>
<span class="org-type">Sock</span>.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; Raises no method exception for Sock.build()</span>
</pre>
<p> However, a slight change makes everything work as hoped: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Sock</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  <span class="org-keyword">def</span> <span class="org-function-name">self.build_fuzzy</span>
    scoped.build(type: <span class="org-string">"fuzzy"</span>)
  <span class="org-keyword">end</span>
<span class="org-keyword">end</span>
</pre>
<p> Now when we call <code>#build_fuzzy</code> on the class it builds a fuzzy sock unassociated with any drawer, and when we call it on an association it builds a fuzzy sock with the appropriate drawer ID set: </p>
<pre class="src src-ruby"><span class="org-type">Sock</span>.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; #&lt;Sock type: "fuzzy" id: nil drawer_id: nil&gt;</span>
sock_drawer.socks.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; #&lt;Sock type: "fuzzy" id: nil drawer_id: 123&gt;</span>
</pre>
<p> All this thanks to the <a href="http://apidock.com/rails/ActiveRecord/NamedScope/ClassMethods/scoped"><code>#scoped</code></a> method, which is aware of the current scope. </p>
<p> Thank you to <a href="https://github.com/dkubb">Dan Kubb</a> for figuring this out for me. </p>
<p> UPDATE: Fixed <code>def build_fuzzy</code> to be <code>def self.build_fuzzy</code> in the last two examples. </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=BRJjlaRL3i0:0yWtcYzDwyE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=BRJjlaRL3i0:0yWtcYzDwyE:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=BRJjlaRL3i0:0yWtcYzDwyE:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=BRJjlaRL3i0:0yWtcYzDwyE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=BRJjlaRL3i0:0yWtcYzDwyE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=BRJjlaRL3i0:0yWtcYzDwyE:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=BRJjlaRL3i0:0yWtcYzDwyE:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=bcOpcFrp8Mo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/BRJjlaRL3i0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2012/01/19/activerecord-default-association-extensions/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2012/01/19/activerecord-default-association-extensions/</feedburner:origLink></item>
		<item>
		<title>My authoring tools</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/Q_7SHl39dyw/</link>
		<comments>http://avdi.org/devblog/2012/01/12/my-authoring-tools/#comments</comments>
		<pubDate>Thu, 12 Jan 2012 14:00:00 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[books]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=1978</guid>
		<description><![CDATA[Several people have asked about my self-publishing process. I&#8217;d really like to write something comprehensive about this, along with code/scripts/config for my whole build stack, but I haven&#8217;t had time yet. Until that time, here are some notes on tools &#8230; <a href="http://avdi.org/devblog/2012/01/12/my-authoring-tools/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Several people have asked about my self-publishing process. I&#8217;d really like to write something comprehensive about this, along with code/scripts/config for my whole build stack, but I haven&#8217;t had time yet. Until that time, here are some notes on tools I use.</p>
<ul>
<li>I do all of my writing in Emacs <a href="http://orgmode.org/">Org-Mode</a>. (Including this blog post.) Org-Mode has many advantages for technical writing, but chief among them is probably the integration with various Emacs programming language modes. As a result, I am able to execute code samples &#8220;live&#8221; from within the manuscript and have the output automatically inserted. This saves me from having to maintain separate sample files and manually sync up the manuscript with the examples.</li>
<li>HTML export is handled directly by Org-Mode.</li>
<li>For PDF I use Org-Mode&#8217;s LaTeX-to-PDF support. I&#8217;ve made a number of customizations to the way the <a href="http://www.latex-project.org/">LaTeX</a> is generated, something that Org-Mode makes very easy.</li>
<li>PDF code typesetting is handled by <a href="http://pygments.org/">Pygments</a> via the <a href="http://code.google.com/p/minted/">Minted</a> LaTeX package.</li>
<li>For Mobi and Epub formats I pipe the generated HTML into the <a href="http://calibre-ebook.com/">Calibre</a> command-line tools.</li>
<li>I automate the various file conversions and packaging the outputs into a ZIP file with good-ole&#8217; <a href="http://www.gnu.org/software/make/">GNU Make</a>.</li>
<li>I use <a href="http://getdpd.com">DPD</a> for digital distribution, payment processing, discount codes, everything having to do with selling the books.</li>
<li>I use <a href="http://99designs.com">99Designs</a> for cover designs.</li>
</ul>
<p>I can recommend all of these tools to anyone looking to self-publish a technical book. I also recommend that anyone thinking of doing this read <a href="http://www.authoringebooks.com/">Jeremy McAnally&#8217;s book</a> on the subject; it has a lot of good advice on how to plan, structure, write, and sell an eBook.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=Q_7SHl39dyw:cNW7KKuyBSY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=Q_7SHl39dyw:cNW7KKuyBSY:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=Q_7SHl39dyw:cNW7KKuyBSY:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=Q_7SHl39dyw:cNW7KKuyBSY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=Q_7SHl39dyw:cNW7KKuyBSY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=Q_7SHl39dyw:cNW7KKuyBSY:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=Q_7SHl39dyw:cNW7KKuyBSY:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=bcOpcFrp8Mo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/Q_7SHl39dyw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2012/01/12/my-authoring-tools/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2012/01/12/my-authoring-tools/</feedburner:origLink></item>
		<item>
		<title>Should I rename my gem?</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/zsk9n06Jg8U/</link>
		<comments>http://avdi.org/devblog/2012/01/09/should-i-rename-my-gem/#comments</comments>
		<pubDate>Mon, 09 Jan 2012 14:00:49 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=1966</guid>
		<description><![CDATA[The Ruby community has some diversity challenges. I don&#8217;t think the Ruby community is any more biased than other tech communities; if anything, I think Rubyists are more apt to make a big deal over offensive content which would be considered business-as-usual &#8230; <a href="http://avdi.org/devblog/2012/01/09/should-i-rename-my-gem/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The Ruby community has <a href="http://confreaks.net/videos/692-rubyconf2011-must-it-always-be-about-sex">some diversity challenges</a>. I don&#8217;t think the Ruby community is any <em>more</em> biased than other tech communities; if anything, I think Rubyists are <a href="http://blog.nicksieger.com/articles/2009/04/30/stand-and-be-counted">more apt to make a big deal</a> over offensive content which would be considered business-as-usual in much of the traditionally white-male-dominated tech industry. Which, ironically, may make us seem like a hotbed of scandal.</p>
<p>As a community we also like our colorful gem names. A little while back someone wrote a blog post about some of the more <a href="http://unethicalblogger.com/2011/11/13/ten-poorly-chosen-gem-names.html">questionable naming choices</a>. Which got me thinking about one of my own gems.</p>
<p>The gem in question is <a href="https://github.com/avdi/hookr">HookR</a>. It&#8217;s a library I wrote a few years ago for adding event hooks to arbitrary classes and objects.</p>
<p>The name amused me at the time. Actually, let&#8217;s be honest, the name <em>still </em>amuses me. But I&#8217;m also concerned it could be offensive. Not in an overt, groping-bottoms-at-a-conference kind of way, but in that insidious way that monocultures tend to be subtly threatening to outsiders without even realizing it.</p>
<p>As I personally read it, it is not gender-offensive since &#8220;hooker&#8221; is a gender-neutral term. However, it is potentially offensive to sex workers. And anyway, <a href="http://avdi.org/devblog/2009/04/30/rehabilitating-the-professional-rock-sta/">as I&#8217;ve noted before</a>, ultimately I&#8217;m not the one who gets to decide which of my statements are offensive.</p>
<p>So my question for you: is HookR an offensive name? I realize it&#8217;s an unconventional, non-enterprisey name; that much I&#8217;m OK with. But is it offensive? Is it amusing, or is it off-putting?</p>
<p>And if you do find it problematic: <strong>can you suggest a better name?</strong></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=zsk9n06Jg8U:AZD0DpoSyRQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=zsk9n06Jg8U:AZD0DpoSyRQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=zsk9n06Jg8U:AZD0DpoSyRQ:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=zsk9n06Jg8U:AZD0DpoSyRQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=zsk9n06Jg8U:AZD0DpoSyRQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=zsk9n06Jg8U:AZD0DpoSyRQ:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=zsk9n06Jg8U:AZD0DpoSyRQ:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=bcOpcFrp8Mo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/zsk9n06Jg8U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2012/01/09/should-i-rename-my-gem/feed/</wfw:commentRss>
		<slash:comments>55</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2012/01/09/should-i-rename-my-gem/</feedburner:origLink></item>
		<item>
		<title>Stop reading this blog and learn something</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/4N3LwcyotJY/</link>
		<comments>http://avdi.org/devblog/2011/12/29/stop-reading-this-blog-and-learn-something/#comments</comments>
		<pubDate>Thu, 29 Dec 2011 14:00:00 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[learning]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=1952</guid>
		<description><![CDATA[Software development is a wonderful field to be a noob in. Perhaps more than any other discipline, there is a wealth of information available for free online–everything from fundamental computer science courses, to the night-by-night learning notes of a master &#8230; <a href="http://avdi.org/devblog/2011/12/29/stop-reading-this-blog-and-learn-something/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Software development is a wonderful field to be a noob in. Perhaps more than any other discipline, there is a wealth of information available for free online–everything from <a href="http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/">fundamental computer science courses</a>, to the <a href="http://japhr.blogspot.com/">night-by-night learning notes</a> of a master programmer. And, of course, there are <a href="https://github.com/">millions upon millions of lines</a> of Open Source code free for the reading.</p>
<p>Unfortunately, this embarassment of riches can be as much stumbling block as well as a stepping-stone. You can learn a lot from this information overload, but you can also waste a great deal of time and find yourself with very little to show for it. Personally, I&#8217;ve probably wasted thousands of hours in this way over the years. It&#8217;s only recently that I&#8217;ve come to identify the antipattern behind this waste. I hope that in writing this I can help you to avoid my mistakes.</p>
<p>The pattern usually looks something like this:</p>
<blockquote><p>Oh man, this web programming stuff is HOT! I need to get in on this!</p>
<p>Let&#8217;s see… if I want to program for the web, I&#8217;ll need to learn a programming language better suited for the web. And I don&#8217;t want to get stuck with on that sucks, so I need to pick the very best one.  Research <a href="http://hyperboleandahalf.blogspot.com/2010/06/this-is-why-ill-never-be-adult.html">ALL the languages</a>!</p>
<p>[insert 3 months of reading about Perl, Python, Ruby, and PHP and maybe writing one or two "hello world" examples]</p>
<p>OK, my &#8220;hello world&#8221; was totally better in Blub than in any of the other languages. But now I need to pick the <em>right</em> web stack for my awesome app ideas. Subscribe to ALL of the blogs!</p>
<p>[Insert three months of voraciously reading web programming blog articles.]</p>
<p>I&#8217;ve been reading some of these blogs, and while it seems like everyone is using &#8220;Ruts&#8221;, it has almost become passé now. Some of the more obscure competitor frameworks look a lot cooler. I&#8217;ve read all of their design rationales, and despite the fact that I&#8217;ve never written an app in Ruts, I totally agree with their critiques. Yeah, I don&#8217;t want to to be stuck in a 6-month- old outmoded framework like Ruts.</p>
<p>Also I need to remember to use the &#8220;Box Turtle Pattern&#8221; that everyone is talking about.</p>
<p>No wait, now they are realizing Box Turtle doesn&#8217;t scale, and the Elephant Plop pattern is the way to go. Man, why did we ever think Box Turtle was a good idea? Whew, glad I hadn&#8217;t started my app yet. Dodged a bullet!</p>
<p>Oops, no, looks like Classic Box Turtle coding is making a comeback with a vengeance. Man they are totally right, when you do it correctly it&#8217;s way more robust than Elephant Plop.</p>
<p>Gosh, what a vibrant community! These advances are hard to keep up with! When am I ever going to find time to write code?</p>
<p>Oh man, this smartphone programming stuff is really heating up…</p></blockquote>
<p>Maybe you mastered web programming long ago, but if you&#8217;re still learning at all there&#8217;s probably <em>some</em> technology that you&#8217;re at this point in. Maybe you&#8217;re like me and right now it&#8217;s client-side JavaScript frameworks. You know it&#8217;s there, you know you&#8217;re interested, you know where to find out more information about it. And you know that there are <a href="https://github.com/addyosmani/todomvc">a lot of alternatives</a>, and that despite the overwhelming amount of information available it isn&#8217;t at all clear where to start.</p>
<p>Without further ado, here is Avdi&#8217;s autodidact guide to learning a new programming technology:</p>
<ol>
<li>Do <strong>not</strong> subscribe to all of the blogs. As yet you have no way of contextualizing the information you will receive from this firehose, and it will just be a paralyzing stream of often-contradictory information.</li>
<li>Make a list of the alternative languages/libraries/frameworks/whatever.</li>
<li>Pick <strong>the most popular one</strong>. Here are the criteria for &#8220;most popular&#8221;:
<ul>
<li>You can easily discover <strong>high-traffic</strong> fora–mailing lists, IRC rooms, forums–dedicated to it. When you ask newbie questions on these fora, they are quickly answered.</li>
<li>There is at least one reputable book about the topic. Books aren&#8217;t a perfect indicator of technology viability, but the fact that someone has taken the time to organize knowledge in a systematic fashion is a decent heuristic pointing to a certain level of stability.</li>
<li>There is a healthy users group dedicated to the technology, meeting regularly in your nearest big city.</li>
<li>At least a few people in the community are too hip for it, and have vocally moved on.</li>
</ul>
</li>
<li>Yes, I said the <strong>most popular</strong>. Not the &#8220;best&#8221;. You don&#8217;t have enough information to figure out the &#8220;best&#8221; one yet. We&#8217;ll get to that. Right now, you need to pick the one where any problem you run into as you learn can be easily googled.</li>
<li>Join that local users group. Attend it diligently. You will need those people.</li>
<li>Buy, and read, a book about it. Yes, an actual book that you can read on your actual iPad. Or even, (<strong>gasp</strong>) on paper. Books have some nice properties which most online learning resources lack:
<ul>
<li>They are (relatively) complete. Free online tutorials have a nasty tendency to have gaping &#8220;to be written&#8221; sections, or to simply stop right in the middle.</li>
<li>They usually focus on fundamentals, rather than the latest nifty techniques. Right now you need fundamentals.</li>
<li>They have structure. Right now you need structure.</li>
<li>Authors of capital-B Books typically spend more time making sure that you&#8217;ll be able to reproduce the examples shown in the book using a given version of the tools. Not always (sadly), but usually. For that matter, they usually have fully-worked examples rather than snippets.</li>
<li>Fewer hyperlinks, and thus fewer opportunities to be distracted by rabbit holes which lead everywhere <em>except</em> to you writing actual working software.</li>
</ul>
</li>
<li>Now use what you&#8217;ve learned in a project. For the love of pete do <strong>not</strong> use it on a project you get paid for, unless you have an explicit understanding with your employer that you are using something you&#8217;ve never used before, and will probably get it totally wrong and have to rip it up and start again in six months. Otherwise, use it on a personal project. A <strong>small</strong> personal project.</li>
<li>When you run into trouble, consult the people in the aforementioned fora and local users groups. You are attending those groups regularly, right?</li>
<li>Congratulations! You now have the beginnings of context and perspective on this new realm of knowledge. The annoyances which caused those aforementioned hipsters to abandon technology X are no longer academic to you; they are real things which you have also dealt with.</li>
<li>With your newfound perspective in hand, review that list you made in step 2. Toss out the projects which have become defunct since you made the list. Pick out one which specifically addresses the problems and irritations you encountered in step 6. Use online tutorials, blogs, whatever; you know the territory now and don&#8217;t need to be so pedantic.</li>
</ol>
<p>This is the framework I&#8217;m going to try to stick to, going forward. If you decide to try it, please let me know how it works out for you.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=4N3LwcyotJY:JOOzuZHB1nE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=4N3LwcyotJY:JOOzuZHB1nE:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=4N3LwcyotJY:JOOzuZHB1nE:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=4N3LwcyotJY:JOOzuZHB1nE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=4N3LwcyotJY:JOOzuZHB1nE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=4N3LwcyotJY:JOOzuZHB1nE:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=4N3LwcyotJY:JOOzuZHB1nE:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=bcOpcFrp8Mo" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/4N3LwcyotJY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2011/12/29/stop-reading-this-blog-and-learn-something/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2011/12/29/stop-reading-this-blog-and-learn-something/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.570 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-02-06 14:30:12 --><!-- Compression = gzip -->

