<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Talk Like A Duck: Category best_practices</title>
    <link>http://talklikeaduck.denhaven2.com/articles/category/best_practices</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>In Ruby, it's not the dog, it's the tricks!</description>
    <item>
      <title>Best Practice Patterns, Accessors and Encapsulation</title>
      <description>&lt;p&gt;&lt;img src="http://talklikeaduck.denhaven2.com/files/2008-02-15_kents_autograph_to_me_on_stbpp.png" alt="Kent's Autograph to me on STBPP" height="255" width="250" class="tease-image"&gt;
One of the classics in the Smalltalk literature, which  has also had a big influence on the Ruby community is Kent Beck&amp;#8217;s &lt;a href="http://www.amazon.com/gp/product/013476904X?ie=UTF8&amp;#38;tag=denhaven2com-20&amp;#38;linkCode=as2&amp;#38;camp=1789&amp;#38;creative=9325&amp;#38;creativeASIN=013476904X"&gt;&amp;#8220;Smalltalk Best Practice Patterns&amp;#8221;&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=denhaven2com-20&amp;#38;l=as2&amp;#38;o=1&amp;#38;a=013476904X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;, which captures the best practices for designing and coding Smalltalk programs.  Back when it was published, I used to see Kent a few times a year, and happened to be in the Bay area when he made an author appearance at the Computer Literacy Bookstore in San Jose, where I got my copy, and the autograph shown here.
&lt;p&gt;The Ruby language has many similarities with Smalltalk, so much of Kent&amp;#8217;s advice applies to Ruby.  I frequently hear prominent Rubyists mention the book.&lt;/p&gt;
&lt;p&gt;On the other hand, Ruby is not exactly Smalltalk, so Kent&amp;#8217;s book isn&amp;#8217;t an exact fit to Ruby. I&amp;#8217;ve been wanting to start writing about adapting some of these patterns to Ruby for a while, so this article will hopefully be the first in a series.&lt;/p&gt;
&lt;h2&gt;The Motivation For This Article&lt;/h2&gt;
&lt;p&gt;Recently on the ruby-talk forum a thread discussing &lt;a href="http://www.ruby-forum.com/topic/141107"&gt;accessor methods vs. direct instance variable access&lt;/a&gt; came up.  This was a hot debate topic in the Smalltalk community back in the 90s, and Kent addressed it in two competing patterns in the book, one of which Ryan Davis (a.k.a ZenSpider) brought up in the conversation.&lt;/p&gt;&lt;/p&gt;


&lt;h2&gt;Patterns Are Decisions, Not Prescriptions.&lt;/h2&gt;
&lt;p&gt;In their best form, patterns represent a network of decisions made during the creation of something, in this case software.  A good pattern should describe the &lt;strong&gt;forces&lt;/strong&gt; which affect the decision whether or not to adopt the particular &lt;strong&gt;solution&lt;/strong&gt; it offers.&lt;/p&gt;
&lt;p&gt;There can often be a tension between competing patterns, different patterns optimize different desirable characteristics, such as readability vs. flexibility.&lt;/p&gt;
&lt;p&gt;The forces, or their relative strength, can be affected by technical factors such as the language, and features of the editor or &lt;span class="caps"&gt;IDE&lt;/span&gt; being used. To varying degrees many or all of Kent&amp;#8217;s Smalltalk patterns have forces affected by the capabilities of the Smalltalk &lt;span class="caps"&gt;IDE&lt;/span&gt;. One of Kent&amp;#8217;s main goals is readable code, so writing code to maximize the utility of the code exploration features of the Smalltalk browsers, inspectors, and debugger figures into the book.&lt;/p&gt;
&lt;h2&gt;A Tale of Two Patterns&lt;/h2&gt;
&lt;p&gt;Now to the specifics of the article at hand.  The book has two patterns described in sequence,starting on page 89, &amp;#8220;Direct Variable Access&amp;#8221;, and &amp;#8220;Indirect Variable Access&amp;#8221;. Both address the same problem &amp;#8220;How do you get and set an instance variable&amp;#8217;s value?&amp;#8221; and give two opposing solutions, along with a good discussion of the tensions.&lt;/p&gt;
&lt;p&gt;The first pattern, as the name implies, advocates referring to an instance variable directly by name, so in Ruby, within a method, you&amp;#8217;d just write @x, instead of using accessor methods, the second pattern.&lt;/p&gt;
&lt;p&gt;As Kent points out in the discussion of the first pattern, direct vs. indirect access was a hotly debated topic in the Smalltalk community, although indirect access got to be popular since it was advocated by several Smalltalk training companies.&lt;/p&gt;
&lt;h2&gt;Tension Number One: Readability&lt;/h2&gt;
&lt;p&gt;In his argument for direct variable access, Kent explains that whenever he ran into an accessor method invocation, which in Smalltalk looks like this:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_Smalltalk "&gt;a = self x&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;He found himself pausing to remind himself that x was &amp;#8220;just&amp;#8221; accessing an instance variable, but that he would read the direct form:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_Smalltalk "&gt;a = x&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;without breaking his stride.&lt;/p&gt;
&lt;p&gt;I might point out that Ruby is subtly different here. First, direct instance variable access is clearly marked with the &amp;#8221;@&amp;#8221; sigil.  On the other hand, a read accessor invocation in Ruby can be written without the explicit self receiver:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So it&amp;#8217;s not as clear that this is a method invocation as opposed to a local variable access, although we know that it &lt;strong&gt;isn&amp;#8217;t&lt;/strong&gt; a direct instance variable access. Write accessor invocation usually requires an explicit receiver:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;x&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;to disambiguate between a write accessor call and simply assigning to a local variable, at least the first time x appears in a particular lexical scope.&lt;/p&gt;
&lt;h2&gt;Tension Number Two: Subclassablity&lt;/h2&gt;
&lt;p&gt;Although direct instance variable is more readable, it does have a drawback in that it makes certain subclassing patterns harder to implement.&lt;/p&gt;
&lt;p&gt;If a class uses indirect variable access consistently, then a subclass can leverage this by overriding the accessor.  For example, lets say we want a subclass which audits changes to an instance variable.  By overriding the setter accessor it can do things like logging changes very simply.  Otherwise any methods which access the instance variable in the superclass need to be overridden.&lt;/p&gt;
&lt;p&gt;Kent&amp;#8217;s example is defining a PolarPoint subclass of Point which has radius and theta instance variables, and overrides Point&amp;#8217;s accessors for x and y.  One interesting aspect of the Ruby/Smalltalk comparison when you look at this example a little more deeply relates to my recent article about instance variables.  In Smalltalk since the Point class has x and y instance variables, it&amp;#8217;s subclass PolarPoint would have x, y, radius and theta instance variables, although the x and y variables would be vestigial and unused.  In Ruby a PolarPoint instance wouldn&amp;#8217;t acquire the unneeded x and y instance variables.&lt;/p&gt;
&lt;h2&gt;The Encapsulation Tension&lt;/h2&gt;
&lt;p&gt;One of the reasons why there was/is such a debate between proponents of direct vs. indirect instance variable access is the effect providing setter and getter accessors has on the apparent encapsulation of the object&amp;#8217;s state.&lt;/p&gt;
&lt;p&gt;First, in either Ruby or Smalltalk, the mere absence of accessor methods doesn&amp;#8217;t prevent encapsulation intrusions.  Ruby has the instance_variable_get and instance_variable_set methods, and Smalltalk has instVarAt: and instVarAt:put:, but these methods are &amp;#8216;marked&amp;#8217; as slightly evil and reserved for dastardly deeds.&lt;/p&gt;
&lt;p&gt;An accessor method on the other hand seems much more like any other normal method.  In Smalltalk, convention is used to mark methods as private, although this is very weak consisting simply of putting private methods in a particular category in the browser, with no runtime check.  Ruby does provide runtime checking of both private and protected methods, although even this protection can be circumvented, using &lt;strong&gt;send&lt;/strong&gt;.&lt;/p&gt;
&lt;H2&gt;Summing Up&lt;/H2&gt;
&lt;p&gt;So in the end, the existence of and the tension between these two patterns demonstrates some key points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Patterns present choices, and the best patterns provide enough information to make an informed decision on a case-by-case basis.&lt;/li&gt;
&lt;li&gt;The languages and the tools we use have an effect on the patterns and the decisions they engender.&lt;/li&gt;&lt;/ul&gt;</description>
      <pubDate>Fri, 15 Feb 2008 08:29:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ef046ae9-bf0a-4b78-b095-53123a3bcdd8</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2008/02/15/best-practice-patterns-accessors-and-encapsulation</link>
      <category>ruby</category>
      <category>smalltalk</category>
      <category>best_practices</category>
      <category>kentbeck</category>
      <category>bestpracticepatterns</category>
      <category>patterns</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/490</trackback:ping>
    </item>
    <item>
      <title>Validating RSS Feeds with RSpec</title>
      <description>&lt;p&gt;One of my current Rails projects involves generating an RSS feed.  While I was working on this the other night, it seemed to be working, so I deployed it to the staging server. Everything looked fine. If I fetched it with Firefox, the browser offered to let me subscribe to the feed with Google Reader, and if I used Safari I'd see a nice view of the feed just like I expected.&lt;/p&gt;
&lt;p&gt;So I sent a note via our campfire to check it out, and a colleague replied that &lt;strong&gt;his&lt;/strong&gt; Safari was saying that it was in an invalid format.&lt;/p&gt;
&lt;p&gt;So I went to the &lt;a href="http://validator.w3.org/feed/"&gt;W3 RSS Feed Validation Service&lt;/a&gt; and worked through the validation issues, after which his browser was as happy as mine.&lt;/p&gt;
&lt;p&gt;Of course, having been through that, I wanted to make sure that RSS validation was covered in the specs for the project.&lt;/p&gt;
&lt;p&gt;I went looking for an existing RSpec matcher, and found &lt;a href="http://www.anodyne.ca/2007/09/28/rspec-custom-matchers-and-be_valid_xhtml/"&gt;a matcher to validate XHTML&lt;/a&gt; but nothing for RSS.&lt;/p&gt;
&lt;p&gt;I then found the &lt;a href="http://feedvalidator.rubyforge.org/"&gt;feedvalidator gem&lt;/a&gt; which provides a Ruby interface to the SOAP interface to the W3 feed validator.  You would think that W3 would be providing a REST interface!  The gem already provides assertions for use with Test::Unit, so I just built an RSpec matcher.&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;BeValidFeed&lt;/span&gt;
  &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;feed_validator&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;tmpdir&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;md5&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;matches?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;validity_checks_disabled?&lt;/span&gt;
    &lt;span class="ident"&gt;v&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;W3C&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;FeedValidator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="ident"&gt;fragment&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt;
    &lt;span class="ident"&gt;filename&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt; &lt;span class="constant"&gt;Dir&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;tmpdir&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;feed.&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="constant"&gt;MD5&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;md5&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;fragment&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
    &lt;span class="keyword"&gt;begin&lt;/span&gt;
      &lt;span class="ident"&gt;response&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;open&lt;/span&gt; &lt;span class="ident"&gt;filename&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="constant"&gt;Marshal&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;load&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;parse&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  	&lt;span class="keyword"&gt;rescue&lt;/span&gt;   
      &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;validate_data&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;fragment&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="attribute"&gt;@failure&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; could not access w3 validator to validate the feed.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;open&lt;/span&gt; &lt;span class="ident"&gt;filename&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;w+&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="constant"&gt;Marshal&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dump&lt;/span&gt; &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;f&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
  	&lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;valid?&lt;/span&gt;   
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;description&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;be valid xhtml&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;failure_message&lt;/span&gt;
   &lt;span class="attribute"&gt;@failure&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; expected xhtml to be valid, but validation produced these errors:&lt;span class="escape"&gt;\n&lt;/span&gt; &lt;span class="expr"&gt;#{@message}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;negative_failure_message&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; expected to not be valid, but was (missing validation?)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="ident"&gt;private&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;validity_checks_disabled?&lt;/span&gt;
      &lt;span class="constant"&gt;ENV&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;NONET&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;be_valid_feed&lt;/span&gt;
  &lt;span class="constant"&gt;BeValidFeed&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I saved this as spec/be_valid_feed.rb&lt;/p&gt;

&lt;p&gt;And in a view or controller spec, I can include this file, and test a response with:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;response.should be_valid_feed&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you use this in a controller spec, you will need to tell RSpec to integrate_views, or you won't have much of a feed to check.  If you use nested example groups, integrate_views needs to be inside the inner group.&lt;/p&gt;

</description>
      <pubDate>Fri, 08 Feb 2008 10:38:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0b27f7ba-403b-48c5-9833-2fd2b5d73fa8</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2008/02/08/validating-rss-feeds-with-rspec</link>
      <category>ruby</category>
      <category>best_practices</category>
      <category>rails</category>
      <category>Rspec</category>
      <category>rss</category>
      <category>validation</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/486</trackback:ping>
    </item>
    <item>
      <title>Chicken Typing Isn't Duck Typing</title>
      <description>&lt;div style='width:173; float:left; text-align:right; font-size:xx-small; border-width:1px; border-color:#444444; border-style:solid;margin-bottom:30px; margin-right:30px;' class='tease-image'&gt;
&lt;img width='173' height='240' alt='Stress' src='http://farm1.static.flickr.com/36/95509221_cc5e4aa8f5_m.jpg'&gt;
&lt;br/&gt;
&lt;a href='http://flickr.com/photos/frield/95509221/'&gt;Stress&lt;/a&gt;
&lt;br/&gt;&amp;copy;
&lt;a href='http://flickr.com/people/frield'&gt;David Friel&lt;/a&gt;
&lt;br/&gt;&lt;a href='http://creativecommons.org/licenses/by/2.0/'&gt;&lt;img src='http://i.creativecommons.org/l/by/2.0/80x15.png' title='used under a Creative Commons Attribution License' width='80' height='15' border='0'/&gt;&lt;/a&gt;
&lt;/div&gt;
Trans just posted a &lt;a href="http://thread.gmane.org/gmane.comp.lang.ruby.general/232460"&gt;question on ruby-talk&lt;/a&gt;.
&lt;p&gt;It seems that he uncovered a conflict between the facet's library and the Ruby standard open_uri library.  Open-uri defines a module called Meta which it uses to extend certain StringIo instances. The Meta module adds several methods including one called meta, which returns a hash of meta information.  In two places in open_uri, the message "respond_to? :meta" is used to test whether a particular StringIO instance has been extended.&lt;/p&gt;
&lt;p&gt;The problem is that Facets also defines a method in either Object or Kernel called meta which provides a clever way to access the singleton class of an object.  So the respond_to? in open_uri was getting false positives.&lt;/p&gt;
&lt;p&gt;Trans asked "So where lies the fault in this conflict? Are extensions the bad guy,
or is respond_to? really not a good oop concept? Or..?"&lt;/p&gt;
&lt;p&gt;David Black replied that he thinks "this is just the age-old issue about adding methods to
existing classes and hitting conflicts. #respond_to? is relatively
dumb; it can't tell you what the method actually does. I think of it
as an important tool for "soft" duck typing, in contrast with "hard"
duck typing where you just send the object the message.
"&lt;/p&gt;
&lt;p&gt;Reading this made me realize that a much better name than "soft" duck typing, for using kind_of?/is_a?, respond_to?, or other such "sniff first" techniques, is &lt;strong&gt;Chicken Typing&lt;/strong&gt; &lt;/p&gt;



&lt;h2&gt;Chicken Typing Isn't The Dynamic Equivalent of Static Typing&lt;/h2&gt;
&lt;p&gt;From what I've observed chicken typing is a "safety blanket" technique used by programmers experienced in statically typed languages, who seem uncomfortable with making the paradigm shift needed to really make dynamically typed languages work.&lt;/p&gt;
&lt;p&gt;But because Ruby is dynamically typed, such techniques work imperfectly at best.  Here are &lt;strong&gt;some&lt;/strong&gt; of the problems:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Checking with respond_to? can give false positives like this because just because an object has a method with the name you are looking for, doesn't mean that the method has the semantics you expect&lt;/li&gt;
	&lt;li&gt;Similarly respond_to? can give false negatives when methods are implemented dynamically via method_missing.  Chicken typers try to enforce conventions which require overriding respond_to? to get around this, but in general this is difficult, expensive, or impossible to do perfectly.&lt;/li&gt;
	&lt;li&gt;Checking with kind_of?/is_a? is unnecessarily constraining. In Ruby you don't need the the equivalent to Java Interfaces or Abstract Classes, and once you've really made the paradigm shift from chicken typing to duck typing, you &lt;a href="http://blog.objectmentor.com/articles/2007/08/08/craftsman-51-brown-bag-viii-ruby-visitor"&gt;realize that you don't want them&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What's OpenURI Doing?&lt;/h2&gt;
&lt;p&gt;Because of Trans' question, I decided to look at how OpenURI was using respond_to? in this case. Here's the code in question:&lt;/p&gt;
First the beginnings of the OpenURI::Meta module
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;OpenURI&lt;/span&gt;
 &lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;Meta&lt;/span&gt;
   &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;Meta.init&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;src&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="comment"&gt;# :nodoc:&lt;/span&gt;
     &lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;extend&lt;/span&gt; &lt;span class="constant"&gt;Meta&lt;/span&gt;
     &lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;instance_eval&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
       &lt;span class="attribute"&gt;@base_uri&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;
       &lt;span class="attribute"&gt;@meta&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{}&lt;/span&gt;
     &lt;span class="punct"&gt;}&lt;/span&gt;
     &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;src&lt;/span&gt;
       &lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;status&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;src&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;status&lt;/span&gt;
       &lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;base_uri&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;src&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;base_uri&lt;/span&gt;
       &lt;span class="ident"&gt;src&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;meta&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
         &lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;meta_add_field&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
       &lt;span class="punct"&gt;}&lt;/span&gt;
     &lt;span class="keyword"&gt;end&lt;/span&gt;
   &lt;span class="keyword"&gt;end&lt;/span&gt;

   &lt;span class="ident"&gt;attr_accessor&lt;/span&gt; &lt;span class="symbol"&gt;:status&lt;/span&gt;
   &lt;span class="ident"&gt;attr_accessor&lt;/span&gt; &lt;span class="symbol"&gt;:base_uri&lt;/span&gt;

   &lt;span class="comment"&gt;# returns a Hash which represents header fields.&lt;/span&gt;
   &lt;span class="comment"&gt;# The Hash keys are downcased for canonicalization.&lt;/span&gt;
   &lt;span class="ident"&gt;attr_reader&lt;/span&gt; &lt;span class="symbol"&gt;:meta&lt;/span&gt;

   &lt;span class="comment"&gt;# MORE STUFF....&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt; &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Meta.init causes the object passed as the first parameter to extend Meta, if a second parameter is passed, it's presumably also a Meta, and it's meta attributes are copied to obj.&lt;/p&gt;
&lt;p&gt;Now here's the use of chicken typing:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;OpenURI&lt;/span&gt;
   &lt;span class="comment"&gt;#...&lt;/span&gt;
  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Buffer&lt;/span&gt; &lt;span class="comment"&gt;# :nodoc:&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;
      &lt;span class="attribute"&gt;@io&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;StringIO&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
      &lt;span class="attribute"&gt;@size&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;attr_reader&lt;/span&gt; &lt;span class="symbol"&gt;:size&lt;/span&gt;

    &lt;span class="constant"&gt;StringMax&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;10240&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;str&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="attribute"&gt;@io&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;str&lt;/span&gt;
      &lt;span class="attribute"&gt;@size&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;str&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;StringIO&lt;/span&gt; &lt;span class="punct"&gt;===&lt;/span&gt; &lt;span class="attribute"&gt;@io&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="constant"&gt;StringMax&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="attribute"&gt;@size&lt;/span&gt;
        &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;tempfile&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
        &lt;span class="ident"&gt;io&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Tempfile&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;open-uri&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
        &lt;span class="ident"&gt;io&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;binmode&lt;/span&gt;
        &lt;span class="constant"&gt;Meta&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;init&lt;/span&gt; &lt;span class="ident"&gt;io&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="attribute"&gt;@io&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="attribute"&gt;@io&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;respond_to?&lt;/span&gt; &lt;span class="symbol"&gt;:meta&lt;/span&gt;
        &lt;span class="ident"&gt;io&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="attribute"&gt;@io&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;string&lt;/span&gt;
        &lt;span class="attribute"&gt;@io&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;io&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;io&lt;/span&gt;
      &lt;span class="constant"&gt;Meta&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;init&lt;/span&gt; &lt;span class="attribute"&gt;@io&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="attribute"&gt;@io&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;respond_to?&lt;/span&gt; &lt;span class="symbol"&gt;:meta&lt;/span&gt;
      &lt;span class="attribute"&gt;@io&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt; &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A few observations:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;The variable which is being chicken typed, in both cases, is an instance variable which is set by the initialize method and never rebound.  So there's no concern about checking an object which was handed in, e.g. through a parameter.  We might be concerned that someone outside the class might somehow access it and change it to extend Meta without the Buffer knowing about it, but...&lt;/li&gt;
	&lt;li&gt;The instance variable will &lt;strong&gt;always&lt;/strong&gt; extend Meta after the accessor is called, so the above concern is moot.&lt;/li&gt;
	&lt;li&gt;In the io accessor method, respond_to? is used to prevent re-extending Meta.  This could be avoided by either extending the object referred to by @io in the initialize method, or, if there's a legitimate reason to defer the extension, either adding a state instance variable to indicate that the extension has been done, or just change "unless @io.respond_to? :meta" to "unless @io.kind_of?(Meta)". This is one case where kind_of? is really useful since we're really just checking if code under our control has extended an object under our control, with a particular Module.&lt;/li&gt;
	&lt;li&gt;Finally, a minor point, but I find this code unnecessarily hard to read because of the choice of name 'io for the temporary in the &amp;lt.&amp;lt. method.  Look at the line "io.binmode".  Which io are we talking about?  Is it the io we just assigned, or the result of the io accessor method. Now it happens to be the former, but knowing that requires knowing that the assignment above is what causes the Ruby parser to treat it as a temporary rather than a method send.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Better a Duck Than  a Chicken&lt;/h2&gt;
&lt;p&gt;So in my opinion, it's better to be a bold Duck than a timid Chicken.  Chicken typing is weak, and it really doesn't provide much more than the "warm fuzzies".  Duck type, and build your specs/tests as you code to provide long-term robustness in dynamically typed languages.&lt;/p&gt;</description>
      <pubDate>Mon, 22 Oct 2007 10:43:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:234b2578-fe29-4215-994e-73d9592cfd63</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2007/10/22/chicken-typing-isnt-duck-typing</link>
      <category>ruby</category>
      <category>best_practices</category>
      <category>ducks</category>
      <category>chickens</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/475</trackback:ping>
    </item>
    <item>
      <title>You Can't Judge a Book...  Some Mental Traps in Learning Ruby</title>
      <description>&lt;div style='width:160; float:left; text-align:right; font-size:xx-small; border-width:1px; border-color:#444444; margin-bottom:30px; margin-right:30px;border-style:solid;'class="tease-image"&gt;
&lt;img width='160' height='240' alt='Bo Diddley, Hoyer' src='http://farm1.static.flickr.com/180/379366968_c8876333ee_m.jpg'
&gt;
&lt;br/&gt;
&lt;a href='http://flickr.com/photos/hubmedia/379366968/'&gt;Bo Diddley, Hoyer&lt;/a&gt;
&lt;br/&gt;&amp;copy;
&lt;a href='http://flickr.com/people/hubmedia'&gt;Andy Field&lt;/a&gt;
&lt;br/&gt;&lt;a href='http://creativecommons.org/licenses/by-nc-sa/2.0/'&gt;&lt;img src='http://i.creativecommons.org/l/by-nc-sa/2.0/80x15.png' title='used under a Creative Commons Attribution-NonCommercial-ShareAlike License' width='80' height='15' border='0'/&gt;&lt;/a&gt;
&lt;/div&gt;
 Quick,  in the Ruby expression:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;10&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 
&lt;p&gt;What's the class of a?&lt;/p&gt;
&lt;p&gt;Many beginning, and intermediate, rubyists whould instinctively say Array!  The real answer is that given just this code, you don't know.&lt;/p&gt;
&lt;p&gt;Recently, on the rails-talk mailing list there was a discussion of this &lt;a href="http://weblog.jamisbuck.org/2007/4/4/activerecord-base-find-shortcut"&gt;idea from Jamis Buck.&lt;/a&gt; Jamis uses alias_method in ActiveRecord::Base so that he can use shortcuts like:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="constant"&gt;Person&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;as a shortcut for:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="constant"&gt;Person&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is particularly nice when playing with ActiveRecord in the rails console, but many seem to think that this should be made part of Rails core, and I don't see a real objection.&lt;/p&gt;
&lt;p&gt;Now one objection raised by the folks who answer Array to the opening question is that, since ActiveRecord rows can be deleted, Person[2] might fail even though Person[1], and Person[3] work.  The reasoning is that the [] makes it "look like an array" and arrays don't act like that.&lt;/p&gt; 
&lt;p&gt;To me this is a case of judging a book by looking at it's cover. Something which I strongly suggest needs to be resisted in order to achieve ruby mastery.&lt;/p&gt;
&lt;p&gt;Let's have a look at a couple of "can't see past the cover" traps in Ruby.&lt;/p&gt;



&lt;h2&gt;Trap Number 1: Confusing Calling Interface with Class&lt;/h2&gt;
&lt;p&gt;Seeing a[2] and thinking Array is an example of this. Just because 99% of the time when you see something "indexed" by an integer, that thing doesn't have to be an Array. It might be an Array, but it &lt;stress&gt;could&lt;/stress&gt; be a Hash, or an ActiveRecord class, or anything which implemented some form of [] method.  This is looking at the method invocation as a 'cover.'&lt;/p&gt;
&lt;p&gt;Ruby method signatures are quite a bit more flexible or at least different from those of other languages, something which can trip up someone trying to see Ruby from the perspective of their 'native' language.  Consider the varieties of parameters which can be passed to Array#[], or String#[], rather than just a indexing methods these can slice and dice the receiver in various ways&lt;/p&gt;
&lt;p&gt;Although different classes might all implement a [] method, and while there are likely similarities or common subsets of functionality, each has it's own quirks.  This can drive folks expecting type signatures nuts, but it's actually one of the things which gives Ruby it's power, and efficiency of expression.&lt;/p&gt;
&lt;p&gt;Some folks go to great efforts trying to pin-down Ruby and make it 'behave' like other languages, but that's a fools errand which works against Rubys strengths.  I'd recommend that these folks redirect their efforts towards improving their testing skills.&lt;/p&gt;
&lt;h2&gt;Trap Number 2: Ignoring the Contents&lt;/h2&gt;
&lt;p&gt;For better or worse, many Ruby classes provide functions which may not work for all instances.  For example, the Range (1..10) is enumerable while (1.0..10.0) is not.  This is because some of the methods in range expect the beginning and ending values of the range to implement methods such as #succ in order to determine the next value.  Further they implicitly expect that applying #succ successively will get to the end value.&lt;/p&gt;
&lt;p&gt;So does this mean that making the range (1.0..10.0) is ilicit or bad?  Not if you don't need to enumerate it and only want to do things like check whether or not a value is included in the range.&lt;/p&gt;
&lt;p&gt;Some folks on ruby-talk have expressed the opinion that the documentation for Range implies that (1.0-10.0) is not a valid range, because the scope of the requirement for elements to implement #succ is ambiguous.  Pragmatically I find the ability to construct enumeration challenged ranges useful.&lt;/p&gt;
&lt;p&gt;Further if you take the philosophy which leads to restricting ranges to elements which make the ranges enumerable consider these things:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="punct"&gt;%w(&lt;/span&gt;&lt;span class="string"&gt;Now is the time&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;sort&lt;/span&gt;      &lt;span class="comment"&gt;# Works fine&lt;/span&gt;
&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:fee&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:fie&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:foe&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:fum&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;sort&lt;/span&gt; &lt;span class="comment"&gt;# Fails &lt;/span&gt;
&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;fred&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="number"&gt;42&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;sort&lt;/span&gt;             &lt;span class="comment"&gt;# Fails&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now do we really want to outlaw arrays of symbols, or heterogeneous arrays from Ruby usage because they don't sort?&lt;/p&gt;
&lt;p&gt;What do you think?&lt;/p&gt;</description>
      <pubDate>Wed, 17 Oct 2007 13:01:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:b835c6d9-8f12-4bbc-a344-96c2e6053c62</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2007/10/17/you-cant-judge-a-book-some-mental-traps-in-learning-ruby</link>
      <category>ruby_for_nubys</category>
      <category>ruby</category>
      <category>best_practices</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/472</trackback:ping>
    </item>
    <item>
      <title>Refactoring With Continuous Testing - a Guided Tour</title>
      <description>&lt;div style='width:180; float:left; text-align:right; font-size:xx-small; border-width:1px; border-color:#444444; border-style:solid; padding:3px; margin-bottom:30px; margin-right:30px;'&gt;&lt;img src="http://talklikeaduck.denhaven2.com/files/2007-10-11_davidcensoredonrefrigerator.jpg" alt="DavidCensoredOnRefrigerator" height="240" width="180" title="Photo by Flickr user melomane, cc-by-nc-sa"&gt;&lt;br/&gt;
&lt;a href='http://flickr.com/photos/melomane/333546498/'&gt;Refrigerator Censorship&lt;/a&gt;
&lt;br/&gt;&amp;copy;
&lt;a href='http://flickr.com/people/melomane'&gt;&lt;/a&gt;
&lt;br/&gt;&lt;a href='http://creativecommons.org/licenses/by-nc-nd/2.0/'&gt;&lt;img src='http://i.creativecommons.org/l/by-nc-nd/2.0/80x15.png' title='used under a Creative Commons Attribution-NonCommercial-NoDerivs License' width='80' height='15' border='0'/&gt;&lt;/a&gt;
&lt;/div&gt;

Today on &lt;a href="http://www.rubyfleebie.com/rubyize-this-3rd-edition/"&gt;Ruby Fleebie&lt;/a&gt;, Frank poses some ruby code to be "rubyized." I took this as an opportunity to do a little exposition of re-factoring under the watchful eye of 
&lt;a href="http://www.zenspider.com/ZSS/Products/ZenTest/"&gt;autotest.&lt;/a&gt;
&lt;p&gt;So I've taken Frank's code and run it through the re-factoring machine several times.  A word to the 'squeamish' because of the use case, there are a few words in the code which some folks, and spam filters might find mildly offensive, but we're all adults here right?&lt;/p&gt;
&lt;p&gt;Now I've got to admit that I really came up with the final solution pretty quickly after seeing the blog post, but then I went back and eased up to it for pedagogical purposes.  So if you're in the mood, sit down and lets re-factor some ruby!&lt;/p&gt;




&lt;h2&gt;The Original Code&lt;/h2&gt;
&lt;p&gt;Here's Frank's original code:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;def remove_insults(input)
  ctr = 0
  input.each do |word|
    word = word.downcase
    if word == &amp;quot;stupid&amp;quot; || word == &amp;quot;moron&amp;quot; || 
       word == &amp;quot;dumbass&amp;quot; || word == &amp;quot;retard&amp;quot;
      i=0
      word.length.times do
        input[ctr][i,1] = &amp;quot;*&amp;quot;
        i+=1
      end
    end
    ctr += 1
  end
  puts input.join(&amp;quot; &amp;quot;).to_s 
end
remove_insults &amp;quot;you truly are a moron sir!&amp;quot;.split(&amp;quot; &amp;quot;)  &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
I've split one line (the long if statement) to try to keep the horizontal scrolling down when viewed here.
&lt;h2&gt;Getting Ready for Autotest&lt;/h2&gt;
&lt;p&gt;My first step was to setup a local subversion repository, so that I could go back over my work and tell you about it.  Then I set up a project directory structure and imported it.&lt;/p&gt;
&lt;/p&gt;Autotest want's a particular directory structure, so I set up a project directory with a lib subdirectory to hold the code, and a test directory to hold the testcase.  The code also needs to be structured as a class, so I changed the code a bit and put it in lib/civilizer.rb&lt;/p&gt; 
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Civilizer&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.remove_insults&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;stupid&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;moron&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;dumbass&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;retard&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;
        &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
          &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;][&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
          &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;+=&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
  &lt;span class="keyword"&gt;end&lt;/span&gt;    
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;remove_insults&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that I also set this class up so that it has two methods, remove_insults prints the bowdlerized input, while civilize returns it as a string.  This change makes the code testable&lt;/p&gt; 
&lt;p&gt;Now we need a test case, that goes in test/test_civilizer.rb:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;require &amp;quot;test/unit&amp;quot;

require &amp;quot;civilizer&amp;quot;

class TestCivilizer &amp;lt; Test::Unit::TestCase
  def test_case_name
    assert false    
  end
end&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;More autotest conventions here, we're testing the class Civilizer which lives in lib/civilizer.rb so that autotest can find it, the test case class needs to be TestCivilizer (i.e. the class under test suffixed by Test).&lt;/p&gt;
&lt;p&gt;This initial test case is designed to fail, at this stage I'm just verifying that autotest is happy with my setup, and runs the test when either the code under test or the test case changes.&lt;/p&gt;
&lt;h2&gt;A Real Test Case&lt;/h2&gt;
&lt;p&gt;The next step is to test the actual code. So I changed the test_case_name method (that clever name was generated by the textmate tc snippet by the way, and I didn't change it) to:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_basic_operation&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a ***** sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;))&lt;/span&gt;  
  &lt;span class="keyword"&gt;end&lt;/span&gt; &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When I save this, autotest runs the test and it passes.  Okay, now that we've got a baseline to refactor against, lets start changing code.&lt;/p&gt;
&lt;h2&gt;Our First Change&lt;/h2&gt;
&lt;p&gt;Let's make use of Ruby's Array#include? method and get rid of that if statement with the long chain of ||s:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Civilizer&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.remove_insults&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;
        &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
          &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;][&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
          &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;+=&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
  &lt;span class="keyword"&gt;end&lt;/span&gt;    
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;remove_insults&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once again, I save this, and autotest automatically confirms that my change didn't break anything.&lt;/p&gt;
&lt;h2&gt;Let's Throw out a Loop or Two&lt;/h2&gt;
&lt;p&gt;That loop to generate the replacement string, seems unwieldy and error prone, let's get rid of it. Here's the new code. I'm focusing on just the method here, the rest of the file hasn't changed:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once again we've successfully cleaned up the code a bit, and the test success shows we haven't broken anything.&lt;/p&gt;
&lt;p&gt;While we're looking at loops, how about the one which steps through the words. We're initializing a counter before the loop and incrementing it at the bottom of the loop.  Smells too much like C if you ask me!&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_with_index&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now this looks more rubyish, but looking at it in retrospect, a better move here would have been to use input.map here with a block which returned either the original nice, or blotted out naughty word, but I didn't think of that at the time.  Of course with my tests I could go back and do that, but I'll leave that as an exercise for the interested reader.&lt;/p&gt;
&lt;p&gt;Anyway, that if statement in the middle is taking up more than it's share of vertical space, let's fix that by using a statement modifier:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_with_index&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code is getting shorter and tidier as we go, although not as short and tidy as that idea of using map, oh well, but keep with me, it's going to end up real short.&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_with_index&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I don't see any need for a separate assignment statement to downcase the input, so I moved that to the argument of include?, still shorter, but hang on.&lt;/p&gt;
&lt;h2&gt;Time For Some More Tests, and a Shift in Strategy&lt;/h2&gt;
&lt;p&gt;We've gotten to this point without changing any testcase code.  I've been using the testcase to ensure that I haven't changed the code in a way that would make it fail to meet the original 'specification.&lt;/p&gt;
&lt;p&gt;Let's revisit the testcase now. It's a pretty simple test case, how about some variations.  Here's a new test method I added to  test/test_civilizer.rb:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_multiple_words&lt;/span&gt;
  &lt;span class="ident"&gt;assert_equal&lt;/span&gt;  &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a ******, you *****!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
         &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
                &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a retard, you moron!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;))&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've reformatted this a bit to try to keep it narrower for the blog presentation.&lt;/p&gt;
&lt;p&gt;Finally, when I save this, autotest informs me that the test has failed, a little debugging reveals that the problem is those pesky punctuation characters. That String#split method is limiting us to splitting words on spaces.&lt;/p&gt;
&lt;p&gt;Now one way to fix that would be to use a regexp instead of a string as the argument to String#split, but why not just use a regexp to implement the Civilizer, here's the new sleek version of the civilize method:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\b&lt;/span&gt;(stupid|moron|dumbass|retard)&lt;span class="escape"&gt;\b&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;    &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 
&lt;p&gt;We've gotten the body of the method down to a one liner, &lt;strong&gt;and&lt;/strong&gt; we now properly handle punctuation!&lt;/p&gt;
&lt;h2&gt;The Value of [TB]DD&lt;/h2&gt;
&lt;p&gt;Let's add another test:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_ignore_case&lt;/span&gt;
  &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*******!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dumbass!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Oops!&lt;/strong&gt; this test fails.  Our original tests didn't exercise the use of lowercase in the original code.	 &lt;/p&gt;
&lt;p&gt;This just shows that even test infected developers are human.  Actually if we had developed the original code in a test driven style, we wouldn't have invoked lowercase until we'd written a test case to motivate it.&lt;/p&gt;
&lt;p&gt;Another useful tool to talk about putting in the arsenal is a coverage tool like rcov which profiles your running tests to show how much of the code under test is being exercised, although in this case, it wouldn't have shown the problem&lt;/p&gt;
&lt;p&gt;Anyway, let's fix the problem, we just make the regexp case insensitive:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\b&lt;/span&gt;(stupid|moron|dumbass|retard)&lt;span class="escape"&gt;\b&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All it took was one little 'i' to fix this bug.  Now autotest is once again showing us the green light.&lt;/p&gt;
&lt;h2&gt;Is the Specification Right?&lt;/h2&gt;
&lt;p&gt;I've been ignoring it all along, but having the caller split the input before giving it to the Civilizer has been bothering me even way before I changed the implementation to using gsub with a regexp, and since then, that code to 'unsplit' it has been sticking out like a sore thumb.  So, after switching from my consultant hat to my client hat and having a quick conference, "we've" agreed to change the interface so that the parameter is a simple string.&lt;/p&gt;
&lt;p&gt;Having agreed to this specification change, let's change the specification.  What do we change? The testcase code of course,  this is the point of test-driven design (or behavior driven design for you &lt;a href="http://www.google.com/url?sa=t&amp;ct=res&amp;cd=1&amp;url=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FSapir-Whorf_hypothesis"&gt;Sapir&#8211;Whorf&lt;/a&gt; &lt;a href="http://rspec.rubyforge.org/"&gt;adherents&lt;/a&gt;), whether you call them tests or something else, they are really specifications.&lt;/p&gt;
&lt;p&gt;Without further ado, here's the new spec:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;test/unit&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;civilizer&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;TestCivilizer&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Unit&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;TestCase&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_one_word&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt;             &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a ***** sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;,&lt;/span&gt; 
          &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;  
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_multiple_words&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt;              &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a ******, you *****!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
           &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a retard, you moron!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_ignore_case&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt;           &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*******!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
        &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dumbass!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've used slightly unusual formatting here too, which makes it easy to visually compare the expectation with the input.&lt;/p&gt;
&lt;p&gt;In good TDD style, we save this test &lt;strong&gt;before&lt;/strong&gt; we change the code to meet the new specification.  As we expected, autotest shows us a red light.  This is an indication that our changed tests are good.  Now let's change the code:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Civilizer&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.remove_insults&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\b&lt;/span&gt;(stupid|moron|dumbass|retard)&lt;span class="escape"&gt;\b&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;    
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;remove_insults&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Meeting the new spec just required getting rid of the join in civilize, and the split in the final statement which gets executed when we run this code for 'real' as opposed to testing it.  Once again, the feedback from autotest goes green.&lt;/p&gt;
&lt;h2&gt;Test Code Deserves to Be Beautiful Too&lt;/h2&gt;
&lt;p&gt;At this point I stepped back and tidied up the test code.  I wanted to make it DRYer, so I introduced a private method to move the repeated code out of each test case:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;test/unit&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;civilizer&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;TestCivilizer&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Unit&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;TestCase&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_one_word&lt;/span&gt;
    &lt;span class="ident"&gt;assert_civilizes&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
                     &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a ***** sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
            
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_multiple_words&lt;/span&gt;
    &lt;span class="ident"&gt;assert_civilizes&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a retard, you moron!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt;
                     &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a ******, you *****!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_ignore_case&lt;/span&gt;
    &lt;span class="ident"&gt;assert_civilizes&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dumbass!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt;
                     &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*******!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt; 
  
  &lt;span class="ident"&gt;private&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;assert_civilizes&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;expected&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="ident"&gt;expected&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I don't know about you, but I like the way this code looks.  I made a conscious decision on the order of the arguments. Normally assert* methods first argument is what's expected, but here it's the second.  The decision on the argument ordering was tied up in what to name the method.  I read it as assert_civilizes this [to] that.  I probably spent a full minute or two pondering this, probably the most 'agonizing' decision in this exercise.  If I kept on with this particular 'project' that might change, no code is sacred!&lt;/p&gt; 
&lt;h2&gt;Another Test, Another Spec Change?&lt;/h2&gt;
&lt;p&gt;The last test I wrote was this:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;    
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_treat_parts_of_words&lt;/span&gt; 
  &lt;span class="ident"&gt;assert_civilizes&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;You, sir are a retarded moron.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt;
                   &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;You, sir are a ******ed *****.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've left this as a proposed spec change.  It fails because one of the bad words is not bracketed by word boundaries. This would be easy to make work, just get rid of the two '\b' anchors in the regexp, but I'm not sure that it's a good idea, and neither is the 'client'.  Should 'stupidity' be considered a bad word? or oxymoron?&lt;/p&gt;
&lt;p&gt;I've raised it with the 'client' and I'm still waiting to hear back.&lt;/p&gt;
&lt;h2&gt;What Have We Learned?&lt;/h2&gt;
&lt;p&gt;The whole exercise, involving some 20 subversion commits, probably took me 30-45 minutes, far less time than writing this article.&lt;/p&gt;
&lt;p&gt;I hope that those of you who have stuck this out to the end found it interesting and perhaps useful.  I think it illustrates some key points about test-driven design, rapid iterative development, and dynamic languages:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Having and maintaining testcode as you go provides value by helping ensure that you aren't wandering away from the goal.&lt;/li&gt;
	&lt;li&gt;Good test code, particularly when run automatically, serves as a more powerful substitute for the type checking done by compilers of statically typed languages, it causes both interface and logic errors to cause fast failures which can usually be quickly corrected.&lt;/li&gt;
	&lt;li&gt;Just because code exists doesn't mean it's sacred.  I'm just as happy, probably happier when I throw old code away and replace it with better code, as long as I'm making progress.  Once again testing is a big boon to this goal.&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Thu, 11 Oct 2007 06:47:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:19c3ac75-cafb-45e8-8901-6a34ceb89e23</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2007/10/11/refactoring-with-continuous-testing-a-guided-tour</link>
      <category>ruby</category>
      <category>best_practices</category>
      <category>tdd</category>
      <category>bdd</category>
      <category>refactoring</category>
      <category>autotest</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/470</trackback:ping>
    </item>
    <item>
      <title>Refactoring With Continuous Testing - a Guided Tour</title>
      <description>&lt;div style='width:180; float:left; text-align:right; font-size:xx-small; border-width:1px; border-color:#444444; border-style:solid; padding:3px; margin-bottom:30px; margin-right:30px;'&gt;&lt;img src="http://talklikeaduck.denhaven2.com/files/2007-10-11_davidcensoredonrefrigerator.jpg" alt="DavidCensoredOnRefrigerator" height="240" width="180" title="Photo by Flickr user melomane, cc-by-nc-sa"&gt;&lt;br/&gt;
&lt;a href='http://flickr.com/photos/melomane/333546498/'&gt;Refrigerator Censorship&lt;/a&gt;
&lt;br/&gt;&amp;copy;
&lt;a href='http://flickr.com/people/melomane'&gt;&lt;/a&gt;
&lt;br/&gt;&lt;a href='http://creativecommons.org/licenses/by-nc-nd/2.0/'&gt;&lt;img src='http://i.creativecommons.org/l/by-nc-nd/2.0/80x15.png' title='used under a Creative Commons Attribution-NonCommercial-NoDerivs License' width='80' height='15' border='0'/&gt;&lt;/a&gt;
&lt;/div&gt;

Today on &lt;a href="http://www.rubyfleebie.com/rubyize-this-3rd-edition/"&gt;Ruby Fleebie&lt;/a&gt;, Frank poses some ruby code to be "rubyized." I took this as an opportunity to do a little exposition of re-factoring under the watchful eye of 
&lt;a href="http://www.zenspider.com/ZSS/Products/ZenTest/"&gt;autotest.&lt;/a&gt;
&lt;p&gt;So I've taken Frank's code and run it through the re-factoring machine several times.  A word to the 'squeamish' because of the use case, there are a few words in the code which some folks, and spam filters might find mildly offensive, but we're all adults here right?&lt;/p&gt;
&lt;p&gt;Now I've got to admit that I really came up with the final solution pretty quickly after seeing the blog post, but then I went back and eased up to it for pedagogical purposes.  So if you're in the mood, sit down and lets re-factor some ruby!&lt;/p&gt;




&lt;h2&gt;The Original Code&lt;/h2&gt;
&lt;p&gt;Here's Frank's original code:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;def remove_insults(input)
  ctr = 0
  input.each do |word|
    word = word.downcase
    if word == &amp;quot;stupid&amp;quot; || word == &amp;quot;moron&amp;quot; || 
       word == &amp;quot;dumbass&amp;quot; || word == &amp;quot;retard&amp;quot;
      i=0
      word.length.times do
        input[ctr][i,1] = &amp;quot;*&amp;quot;
        i+=1
      end
    end
    ctr += 1
  end
  puts input.join(&amp;quot; &amp;quot;).to_s 
end
remove_insults &amp;quot;you truly are a moron sir!&amp;quot;.split(&amp;quot; &amp;quot;)  &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
I've split one line (the long if statement) to try to keep the horizontal scrolling down when viewed here.
&lt;h2&gt;Getting Ready for Autotest&lt;/h2&gt;
&lt;p&gt;My first step was to setup a local subversion repository, so that I could go back over my work and tell you about it.  Then I set up a project directory structure and imported it.&lt;/p&gt;
&lt;/p&gt;Autotest want's a particular directory structure, so I set up a project directory with a lib subdirectory to hold the code, and a test directory to hold the testcase.  The code also needs to be structured as a class, so I changed the code a bit and put it in lib/civilizer.rb&lt;/p&gt; 
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Civilizer&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.remove_insults&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;stupid&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;moron&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;dumbass&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;retard&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;
        &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
          &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;][&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
          &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;+=&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
  &lt;span class="keyword"&gt;end&lt;/span&gt;    
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;remove_insults&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that I also set this class up so that it has two methods, remove_insults prints the bowdlerized input, while civilize returns it as a string.  This change makes the code testable&lt;/p&gt; 
&lt;p&gt;Now we need a test case, that goes in test/test_civilizer.rb:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;require &amp;quot;test/unit&amp;quot;

require &amp;quot;civilizer&amp;quot;

class TestCivilizer &amp;lt; Test::Unit::TestCase
  def test_case_name
    assert false    
  end
end&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;More autotest conventions here, we're testing the class Civilizer which lives in lib/civilizer.rb so that autotest can find it, the test case class needs to be TestCivilizer (i.e. the class under test suffixed by Test).&lt;/p&gt;
&lt;p&gt;This initial test case is designed to fail, at this stage I'm just verifying that autotest is happy with my setup, and runs the test when either the code under test or the test case changes.&lt;/p&gt;
&lt;h2&gt;A Real Test Case&lt;/h2&gt;
&lt;p&gt;The next step is to test the actual code. So I changed the test_case_name method (that clever name was generated by the textmate tc snippet by the way, and I didn't change it) to:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_basic_operation&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a ***** sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;))&lt;/span&gt;  
  &lt;span class="keyword"&gt;end&lt;/span&gt; &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When I save this, autotest runs the test and it passes.  Okay, now that we've got a baseline to refactor against, lets start changing code.&lt;/p&gt;
&lt;h2&gt;Our First Change&lt;/h2&gt;
&lt;p&gt;Let's make use of Ruby's Array#include? method and get rid of that if statement with the long chain of ||s:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Civilizer&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.remove_insults&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;
        &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
          &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;][&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
          &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;+=&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
  &lt;span class="keyword"&gt;end&lt;/span&gt;    
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;remove_insults&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once again, I save this, and autotest automatically confirms that my change didn't break anything.&lt;/p&gt;
&lt;h2&gt;Let's Throw out a Loop or Two&lt;/h2&gt;
&lt;p&gt;That loop to generate the replacement string, seems unwieldy and error prone, let's get rid of it. Here's the new code. I'm focusing on just the method here, the rest of the file hasn't changed:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once again we've successfully cleaned up the code a bit, and the test success shows we haven't broken anything.&lt;/p&gt;
&lt;p&gt;While we're looking at loops, how about the one which steps through the words. We're initializing a counter before the loop and incrementing it at the bottom of the loop.  Smells too much like C if you ask me!&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_with_index&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now this looks more rubyish, but looking at it in retrospect, a better move here would have been to use input.map here with a block which returned either the original nice, or blotted out naughty word, but I didn't think of that at the time.  Of course with my tests I could go back and do that, but I'll leave that as an exercise for the interested reader.&lt;/p&gt;
&lt;p&gt;Anyway, that if statement in the middle is taking up more than it's share of vertical space, let's fix that by using a statement modifier:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_with_index&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code is getting shorter and tidier as we go, although not as short and tidy as that idea of using map, oh well, but keep with me, it's going to end up real short.&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_with_index&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I don't see any need for a separate assignment statement to downcase the input, so I moved that to the argument of include?, still shorter, but hang on.&lt;/p&gt;
&lt;h2&gt;Time For Some More Tests, and a Shift in Strategy&lt;/h2&gt;
&lt;p&gt;We've gotten to this point without changing any testcase code.  I've been using the testcase to ensure that I haven't changed the code in a way that would make it fail to meet the original 'specification.&lt;/p&gt;
&lt;p&gt;Let's revisit the testcase now. It's a pretty simple test case, how about some variations.  Here's a new test method I added to  test/test_civilizer.rb:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_multiple_words&lt;/span&gt;
  &lt;span class="ident"&gt;assert_equal&lt;/span&gt;  &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a ******, you *****!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
         &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
                &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a retard, you moron!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;))&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've reformatted this a bit to try to keep it narrower for the blog presentation.&lt;/p&gt;
&lt;p&gt;Finally, when I save this, autotest informs me that the test has failed, a little debugging reveals that the problem is those pesky punctuation characters. That String#split method is limiting us to splitting words on spaces.&lt;/p&gt;
&lt;p&gt;Now one way to fix that would be to use a regexp instead of a string as the argument to String#split, but why not just use a regexp to implement the Civilizer, here's the new sleek version of the civilize method:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\b&lt;/span&gt;(stupid|moron|dumbass|retard)&lt;span class="escape"&gt;\b&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;    &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 
&lt;p&gt;We've gotten the body of the method down to a one liner, &lt;strong&gt;and&lt;/strong&gt; we now properly handle punctuation!&lt;/p&gt;
&lt;h2&gt;The Value of [TB]DD&lt;/h2&gt;
&lt;p&gt;Let's add another test:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_ignore_case&lt;/span&gt;
  &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*******!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dumbass!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Oops!&lt;/strong&gt; this test fails.  Our original tests didn't exercise the use of lowercase in the original code.	 &lt;/p&gt;
&lt;p&gt;This just shows that even test infected developers are human.  Actually if we had developed the original code in a test driven style, we wouldn't have invoked lowercase until we'd written a test case to motivate it.&lt;/p&gt;
&lt;p&gt;Another useful tool to talk about putting in the arsenal is a coverage tool like rcov which profiles your running tests to show how much of the code under test is being exercised, although in this case, it wouldn't have shown the problem&lt;/p&gt;
&lt;p&gt;Anyway, let's fix the problem, we just make the regexp case insensitive:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\b&lt;/span&gt;(stupid|moron|dumbass|retard)&lt;span class="escape"&gt;\b&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All it took was one little 'i' to fix this bug.  Now autotest is once again showing us the green light.&lt;/p&gt;
&lt;h2&gt;Is the Specification Right?&lt;/h2&gt;
&lt;p&gt;I've been ignoring it all along, but having the caller split the input before giving it to the Civilizer has been bothering me even way before I changed the implementation to using gsub with a regexp, and since then, that code to 'unsplit' it has been sticking out like a sore thumb.  So, after switching from my consultant hat to my client hat and having a quick conference, "we've" agreed to change the interface so that the parameter is a simple string.&lt;/p&gt;
&lt;p&gt;Having agreed to this specification change, let's change the specification.  What do we change? The testcase code of course,  this is the point of test-driven design (or behavior driven design for you &lt;a href="http://www.google.com/url?sa=t&amp;ct=res&amp;cd=1&amp;url=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FSapir-Whorf_hypothesis"&gt;Sapir&#8211;Whorf&lt;/a&gt; &lt;a href="http://rspec.rubyforge.org/"&gt;adherents&lt;/a&gt;), whether you call them tests or something else, they are really specifications.&lt;/p&gt;
&lt;p&gt;Without further ado, here's the new spec:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;test/unit&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;civilizer&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;TestCivilizer&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Unit&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;TestCase&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_one_word&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt;             &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a ***** sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;,&lt;/span&gt; 
          &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;  
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_multiple_words&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt;              &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a ******, you *****!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
           &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a retard, you moron!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_ignore_case&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt;           &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*******!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
        &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dumbass!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've used slightly unusual formatting here too, which makes it easy to visually compare the expectation with the input.&lt;/p&gt;
&lt;p&gt;In good TDD style, we save this test &lt;strong&gt;before&lt;/strong&gt; we change the code to meet the new specification.  As we expected, autotest shows us a red light.  This is an indication that our changed tests are good.  Now let's change the code:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Civilizer&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.remove_insults&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\b&lt;/span&gt;(stupid|moron|dumbass|retard)&lt;span class="escape"&gt;\b&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;    
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Civilizer&lt;/span&