<?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: Tag beautiful_code</title>
    <link>http://talklikeaduck.denhaven2.com/articles/tag/beautiful_code</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>In Ruby, it's not the dog, it's the tricks!</description>
    <item>
      <title>Aspects of Beauty: Proportion, Integrity, Clarity, and Monkey Patching?</title>
      <description>&lt;p&gt;&lt;img src="http://talklikeaduck.denhaven2.com/files/beauty_small.png" class="tease-image"/&gt;
Besides being a master werewolf, Marcel Molina Jr. gives great presentations!
&lt;p&gt;
In his keynote presentation on the second day of the Ruby Hoedown, Marcel talked about 
&lt;a href="http://rubyhoedown2007.confreaks.com/session09.html"&gt;&amp;#8220;What Makes Code Beautiful&amp;#8221;&lt;/a&gt;,
click on the link for the confreaks video of this session.
&lt;/p&gt;
&lt;p&gt;
The talk started with an exploration of the classical Philosophy of Beauty, from Plato to Descartes.
Marcel summarized this by proposing that beauty lies in the balance between three aspects which, 
at times, either strengthen or oppose each other:&lt;/p&gt;&lt;/p&gt;


&lt;dl&gt;
&lt;dt&gt;Proportion&lt;/dt&gt;&lt;dd&gt;The property that components have the appropriate(relative) size/weight.&lt;/dd&gt;
&lt;dt&gt;Integrity&lt;/dt&gt;&lt;dd&gt;I would summarize this as &amp;#8220;fitness of purpose.&amp;#8221;  Marcel&amp;#8217;s anti-example was a
hammer made out of glass. Although it might be beautifully constructed, and a joy to the eye, it
would be unlikely to serve its intended purpose, and thus would fall short on integrity&lt;/dd&gt;
&lt;dt&gt;Clarity&lt;/dt&gt;The property of being easily grasped as to meaning and function.&lt;/dd&gt;
&lt;/dl&gt;
&lt;h2&gt;Beauty and Ruby&lt;/h2&gt;
&lt;p&gt;About 16 minutes into the talk, Marcel started talking about this view of beauty in the context of Ruby code.  He gave an example of some really &amp;#8220;clever&amp;#8221; code to convert strings to an appropriate
instance of a Ruby class, for example &amp;#8220;true&amp;#8221; would me converted to true, &amp;#8220;false&amp;#8221; to false, and 
strings representing integer or time values to Integers or Times, respectively.&lt;/p&gt;
&lt;p&gt;The code in question, implemented a kind of functional language pattern match against the string.
Marcel suggested that he might have been into studying Haskell at the time he wrote this code.
He used a generator to produce an enumerable collection of patterns to try, and did some &amp;#8220;nice&amp;#8221; 
tricks to allow the result of a pattern match to sometimes be solely the value he wanted, and 
sometimes to be an array with the value as the second element, to handle the special case where the 
desired value was the literal false.  If it sounds complicated, it is, I&amp;#8217;ve placed the code at
the end of this article.  
Some of us in the audience, &amp;#8220;smelled&amp;#8221; this code right away.&lt;/p&gt;
&lt;p&gt;He then critiqued this solution. Although he had originally considered it &amp;#8220;beautiful&amp;#8221; since it was &amp;#8220;elegant&amp;#8221; and &amp;#8220;sophisticated&amp;#8221; he came to smell it too.&lt;/p&gt;
&lt;h2&gt;A Fresh Design&lt;/h2&gt;
&lt;p&gt;Here&amp;#8217;s how the code ultimately was written:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;CoercibleString&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;String&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;coerce&lt;/span&gt;
    &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;
    &lt;span class="keyword"&gt;when&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="constant"&gt;true&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;         &lt;span class="constant"&gt;false&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;^&lt;span class="escape"&gt;\d&lt;/span&gt;+$&lt;/span&gt;&lt;span class="punct"&gt;/:&lt;/span&gt;         &lt;span class="constant"&gt;Integer&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="ident"&gt;datetime_format&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="constant"&gt;Time&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="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt;
      &lt;span class="constant"&gt;self&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;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once this much simpler design is unveiled the original &amp;#8220;sophisticated&amp;#8221;, and &amp;#8220;elegant&amp;#8221; design
looks anything but.&lt;/p&gt;
&lt;h2&gt;Measuring against Proportion, Integrity, and Clarity&lt;/h2&gt;
&lt;dl&gt;
&lt;dt&gt;Proportion&lt;/dt&gt;&lt;dd&gt;The original is a total failure, it&amp;#8217;s much too long compared to the final
code.&lt;/dt&gt;
&lt;dt&gt;Integrity&lt;/dt&gt;&lt;dd&gt;Again the original loses on this aspect. The use of the generator, particularly
the early continuation based implementation, causes very slow performance, and leaks memory. Marcel
stated that the simpler version is an order of magnitude faster.&lt;/dt&gt;
&lt;dt&gt;Clarity&lt;/dt&gt;&lt;dd&gt;Do I really have to explore this?&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Marcel had pointed out when describing the original design that one of it&amp;#8217;s &amp;#8220;cool features&amp;#8221; was
extensibility. Adding a new coercion just required adding another call to try in the Generator.new
block.&lt;/p&gt;
&lt;p&gt;In contrast adding a new coercion to the better design just requires adding a when leg to the
case statement.&lt;/p&gt;
&lt;h2&gt;The Questionable Beauty of Making Subclasses of Core Classes&lt;/h2&gt;
&lt;p&gt;While I loved the talk and agree with 99 and 44/100%,  I&amp;#8217;m just a bit troubled by the introduction
of the CoercibleString class.  I think that it falls down on proportion at least.&lt;p&gt;
&lt;p&gt;It seems to me that there&amp;#8217;s some missing code here.  How do you actually coerce a string.
This seems to strongly imply a usage like this:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;PayloadProcessor&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;process&lt;/span&gt;
    &lt;span class="comment"&gt;# code which extracts a string to be coerced&lt;/span&gt;

    &lt;span class="comment"&gt;#coerce the string referenced by the variable value_str&lt;/span&gt;
    &lt;span class="ident"&gt;value&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;CoercibleString&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;value_str&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;coerce&lt;/span&gt;

    &lt;span class="comment"&gt;#further processing&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An alternative, and it seems to me to be a better one, although I&amp;#8217;m convinceable otherwise, would
be to just make that method part of the class requiring the conversion, either directly, or through a
module:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;class PayloadProcessor

  def process
    # code which extracts a string to be coerced

    #coerce the string referenced by the variable value_str
    value = coerce(value_str)

    #further processing
  end

  def coerce(str)
    case str
    when 'true':          true
    when 'false':         false
    when /^\d+$/:         Integer(str)
    when datetime_format: Time.parse(str)
    else
      str
    end
  end

end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now some might argue that the &amp;#8216;functional&amp;#8217; looking coerce method which takes the string
as an argument rather than the receiver seems somehow less &amp;#8216;object oriented&amp;#8217;, but I find this
unconvincing.&lt;/p&gt;
&lt;p&gt;If CoercibleString is a class we need code to create it from a string, something like:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;CoercibleString&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;String&lt;/span&gt;
    &lt;span class="comment"&gt;# Create a new coercible string&lt;/span&gt;
    &lt;span class="comment"&gt;# Note that since the actual value of&lt;/span&gt;
    &lt;span class="comment"&gt;# Ruby strings are not held by an instance variable&lt;/span&gt;
    &lt;span class="comment"&gt;# we need to alter the internal representation&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;source_str&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="constant"&gt;self&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;source_str&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I had a brief conversation with Marcel about whether or not subclassing string really seemed
appropriate, but it lasted all of about a minute. There&amp;#8217;s a bit of supposition here on my
part, so apologies to Marcel if I misunderstood the exchange. He indicated that he would probably 
advocate
defining a method called CoercibleString, in parallel with Kernel#Integer and its ilk.&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;Kernel&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;CoercibleString&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="constant"&gt;CoercibleString&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;str&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But this syntactic sugar, just seems to be tilting the balance towards a less proportional design.
&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Building new classes is often a good idea, but not always.  I&amp;#8217;m not totally convinced that
coerce(str) is more beautiful than CoercibleString.new(str).coerce, or CoercibleString(str).coerce,
but &lt;strong&gt;my&lt;/strong&gt; sense of esthetics tilts me that way.&lt;/p&gt;
&lt;p&gt;Comments?&lt;/p&gt;
&lt;h2&gt;A &amp;#8220;Smelly&amp;#8221; Way to Coerce Strings&lt;/h2&gt;
&lt;p&gt;Here&amp;#8217;s Marcel&amp;#8217;s original code:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;CoercibleString&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;String&lt;/span&gt;
  &lt;span class="ident"&gt;attr_accessor&lt;/span&gt; &lt;span class="ident"&gt;generator&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;coerce&lt;/span&gt;
    &lt;span class="ident"&gt;attempt&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;
    &lt;span class="keyword"&gt;break&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;&lt;span class="ident"&gt;attempt&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;coercions&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;next&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;nil?&lt;/span&gt; &lt;span class="keyword"&gt;while&lt;/span&gt; &lt;span class="ident"&gt;coercions&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;next?&lt;/span&gt;
    &lt;span class="ident"&gt;attempt&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nil?&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;attempt&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;coercions&lt;/span&gt;
      &lt;span class="constant"&gt;Generator&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;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;generator&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;
        &lt;span class="ident"&gt;try&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="constant"&gt;self&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="punct"&gt;}&lt;/span&gt;
        &lt;span class="ident"&gt;try&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt; &lt;span class="punct"&gt;]&lt;/span&gt;  &lt;span class="punct"&gt;}&lt;/span&gt;
        &lt;span class="ident"&gt;try&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="constant"&gt;Integer&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;              &lt;span class="punct"&gt;}&lt;/span&gt;
        &lt;span class="ident"&gt;try&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="constant"&gt;Date&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="constant"&gt;self&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="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;try&lt;/span&gt;
        &lt;span class="ident"&gt;attempt&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;desired&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="keyword"&gt;yield&lt;/span&gt;
        &lt;span class="ident"&gt;generator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;yield&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;desired&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;nil?&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="ident"&gt;attempt&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;desired&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;attempt&lt;/span&gt;
    &lt;span class="keyword"&gt;rescue&lt;/span&gt; &lt;span class="constant"&gt;ArgumentError&lt;/span&gt;
        &lt;span class="ident"&gt;generator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;yield&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Mon, 20 Aug 2007 14:25:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:736e1dfe-1fec-46d1-994d-15838271c4eb</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2007/08/20/aspects-of-beauty-proportion-integrity-clarity-and-monkey-patching</link>
      <category>ruby</category>
      <category>best_practices</category>
      <category>ruby</category>
      <category>rubyhoedown</category>
      <category>beautiful_code</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/456</trackback:ping>
    </item>
  </channel>
</rss>
