<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[pragmatist]]></title>
  <link href="http://pragmati.st/atom.xml" rel="self"/>
  <link href="http://pragmati.st/"/>
  <updated>2012-03-24T22:10:04-04:00</updated>
  <id>http://pragmati.st/</id>
  <author>
    <name><![CDATA[Patrick Joyce]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[The Elements of Ruby Style: Predicate Methods]]></title>
    <link href="http://pragmati.st/2012/03/24/the-elements-of-ruby-style-predicate-methods/"/>
    <updated>2012-03-24T14:44:00-04:00</updated>
    <id>http://pragmati.st/2012/03/24/the-elements-of-ruby-style-predicate-methods</id>
    <content type="html"><![CDATA[<p>A method that returns true or false is called a &#8220;predicate method&#8221;.</p>

<p>In Ruby, there is a naming convention where predicate methods end with a question mark. For instance, if you have an <code>Invoice</code> class and are writing an instance method that returns whether the invoice has been paid or not, you would name the method <code>paid?</code></p>

<p>This idiom helps improve readability by making Ruby code read more like English:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">puts</span> <span class="s2">&quot;This invoice has been paid&quot;</span> <span class="k">if</span> <span class="n">invoice</span><span class="o">.</span><span class="n">paid?</span>
</span></code></pre></td></tr></table></div></figure>


<p>Predicate methods should always return <code>true</code> or <code>false</code>. Because of the way that Ruby evaluates truthiness (<code>false</code> and <code>nil</code> are false; everything else evaluates to true) some people will advocate simply returning a &#8220;truthy&#8221; value. An implementation of <code>Invoice#paid?</code> that was truthy could look like this:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">TruthyInvoice</span>
</span><span class='line'>  <span class="kp">attr_accessor</span> <span class="ss">:paid_at</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">paid?</span>
</span><span class='line'>    <span class="vi">@paid_at</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">invoice</span> <span class="o">=</span> <span class="no">TruthyInvoice</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'><span class="n">invoice</span><span class="o">.</span><span class="n">paid?</span> <span class="c1"># nil</span>
</span><span class='line'>
</span><span class='line'><span class="n">invoice</span><span class="o">.</span><span class="n">paid_at</span> <span class="o">=</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span>
</span><span class='line'><span class="n">invoice</span><span class="o">.</span><span class="n">paid?</span> <span class="c1"># 2012-03-24 20:45:59 -0400 </span>
</span></code></pre></td></tr></table></div></figure>


<p>The above implementation of <code>paid?</code> will work fine in conditionals.</p>

<p>However, the intent of the <code>paid?</code> method is to tell you if the invoice has been paid, yet it is returning an instance of <code>Time</code>. This is confusing. The method would better represent the author&#8217;s intent if it always returned a boolean. The most common way to ensure that a method returns true or false is to use the not operator (<code>!</code>) twice. This is read &#8220;not not&#8221; and would be used as follows:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">Invoice</span>
</span><span class='line'>  <span class="kp">attr_accessor</span> <span class="ss">:paid_at</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">paid?</span>
</span><span class='line'>    <span class="o">!!</span><span class="vi">@paid_at</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">invoice</span> <span class="o">=</span> <span class="no">Invoice</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'><span class="n">invoice</span><span class="o">.</span><span class="n">paid?</span> <span class="c1"># false </span>
</span><span class='line'>
</span><span class='line'><span class="n">invoice</span><span class="o">.</span><span class="n">paid_at</span> <span class="o">=</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span>
</span><span class='line'><span class="n">invoice</span><span class="o">.</span><span class="n">paid?</span> <span class="c1"># true</span>
</span></code></pre></td></tr></table></div></figure>


<p>Using &#8220;not not&#8221; only requires two more keystrokes and it more closely matches the intent of the method. One of the maxims of good programming is to &#8220;be liberal in what you accept and strict in what you emit&#8221;. Returning a boolean from predicate methods is being strict in what you emit.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The War on Comments Isn't Over]]></title>
    <link href="http://pragmati.st/2012/03/10/the-war-on-comments/"/>
    <updated>2012-03-10T17:16:00-05:00</updated>
    <id>http://pragmati.st/2012/03/10/the-war-on-comments</id>
    <content type="html"><![CDATA[<p>Back in January, my very talented colleague Dave Copeland and me spent a bit of time talking about the proper role of comments in Ruby. He wrote a nice piece <a href="http://www.naildrivin5.com/blog/2012/01/11/the-war-on-comments.html">defending the use of code level comments</a> back then. We disagree. You should go read his piece before getting to my argument. And after you read that you should go buy his <a href="http://pragprog.com/book/dccar/build-awesome-command-line-applications-in-ruby">new book</a>.</p>

<p>I&#8217;ll wait&#8230;</p>

<p>Welcome back.</p>

<p>Dave and I wholeheartedly agree on API Documentation. If you are writing a reusable library&mdash;even if only you and your coworkers will ever use it&mdash;I find it irresponsible to neglect API level documentation.</p>

<p>We semi-agree on what he calls <em>&ldquo;Why&rdquo; comments</em>: comments that explain something about the reasons <em>why</em> a piece of code is the way it is. Sometimes there truly is some odd, external constraint that needs to be explained&hellip; and it needs to be explained right there in the code. However, I think that explanatory comments are overused and most times indicate a failure of communications that could better be solved by clear tests, improved naming, and good commit messages. I hope to write about this more later.</p>

<p>What I&#8217;m writing about today&mdash;and where we disagree&mdash;is on the used of <em>descriptive comments</em>: comments that explain <em>what a piece of code is doing</em>.</p>

<blockquote><p>Problem: Your code needs to be commented to be understood. Solution: Add comments - Now you have 2 problems :)</p><footer><strong>Paul Barry</strong><cite><a href='https://twitter.com/#!/pjb3/status/156783860846301184'>Twitter</a></cite></footer></blockquote>


<p>Dave&#8217;s argument for explanatory comments is that even the best of us occasionally write code that is convoluted and difficult to understand. I know that, despite my best efforts, I&#8217;m responsible for much of the less than clear code that prompted the discussion on comments in the first place.</p>

<p>Here is the example Dave used of convoluted code you could come across in a production app that would benefit from comments:</p>

<figure class='code'><figcaption><span>Original  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">isqrt</span><span class="p">(</span><span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="n">square</span> <span class="o">=</span> <span class="n">square</span><span class="o">.</span><span class="n">to_i</span>
</span><span class='line'>  <span class="k">return</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">square</span> <span class="o">==</span> <span class="mi">0</span>
</span><span class='line'>  <span class="k">raise</span> <span class="no">RangeError</span> <span class="k">if</span> <span class="n">square</span> <span class="o">&lt;</span> <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">n</span> <span class="o">=</span> <span class="n">iter</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="n">n1</span> <span class="o">=</span> <span class="n">iter</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="n">n1</span><span class="p">,</span> <span class="n">n</span> <span class="o">=</span> <span class="n">iter</span><span class="p">(</span><span class="n">n1</span><span class="p">,</span> <span class="n">square</span><span class="p">),</span> <span class="n">n1</span> <span class="k">until</span> <span class="n">n1</span> <span class="o">&gt;=</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span>
</span><span class='line'>  <span class="n">n1</span> <span class="o">=</span> <span class="n">n1</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">until</span> <span class="n">n1</span><span class="o">*</span><span class="n">n1</span> <span class="o">&lt;=</span> <span class="n">square</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">n1</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'><span class="k">def</span> <span class="nf">iter</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="p">(</span><span class="n">square</span> <span class="o">/</span> <span class="n">n</span><span class="p">))</span> <span class="o">/</span> <span class="mi">2</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>No argument from me. That code is impenetrable. As I write this I still don&#8217;t completely understand what it does. Dave suggests adding comments so that the next poor bastard who comes along has an easier time of figuring it out. Here&#8217;s his commented version:</p>

<figure class='code'><figcaption><span>Dave&#8217;s Version with Comments  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">isqrt</span><span class="p">(</span><span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="c1"># just in case we don&#39;t get an int</span>
</span><span class='line'>  <span class="n">square</span> <span class="o">=</span> <span class="n">square</span><span class="o">.</span><span class="n">to_i</span>
</span><span class='line'>  <span class="k">return</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">square</span> <span class="o">==</span> <span class="mi">0</span>
</span><span class='line'>  <span class="k">raise</span> <span class="no">RangeError</span> <span class="k">if</span> <span class="n">square</span> <span class="o">&lt;</span> <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># make our initial guesses, which are initially</span>
</span><span class='line'>  <span class="c1"># too high (intentionally; see next)</span>
</span><span class='line'>  <span class="n">n</span> <span class="o">=</span> <span class="n">iter</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="n">n1</span> <span class="o">=</span> <span class="n">iter</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># Refine our guesses until we get close enough</span>
</span><span class='line'>  <span class="n">n1</span><span class="p">,</span> <span class="n">n</span> <span class="o">=</span> <span class="n">iter</span><span class="p">(</span><span class="n">n1</span><span class="p">,</span> <span class="n">square</span><span class="p">),</span> <span class="n">n1</span> <span class="k">until</span> <span class="n">n1</span> <span class="o">&gt;=</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span>
</span><span class='line'>  <span class="c1"># We&#39;re close enough when we&#39;re JUST under square</span>
</span><span class='line'>  <span class="n">n1</span> <span class="o">=</span> <span class="n">n1</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">until</span> <span class="n">n1</span><span class="o">*</span><span class="n">n1</span> <span class="o">&lt;=</span> <span class="n">square</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">n1</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'><span class="k">def</span> <span class="nf">iter</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="p">(</span><span class="n">square</span> <span class="o">/</span> <span class="n">n</span><span class="p">))</span> <span class="o">/</span> <span class="mi">2</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p><span class='pullquote-right' data-pullquote='The hard part of improving a difficult piece of code is understanding it, not making the changes to improve it'>
And that <em>is an improvement</em>. However, even with the comments I still don&#8217;t fully understand what this method is doing. That&#8217;s the problem. Dave went to the trouble of figuring out this really tricky piece of code. He even tried to help me&mdash; the aforementioned poor bastard reading this code at a later date&mdash;and I <em>still don&#8217;t get it</em>.</p>

<p>The problem is that despite the helpful comments (and they are helpful) the method is still pretty much incomprehensible.</p>

<p>The hard part of improving a difficult piece of code is understanding it, not making the changes to improve it. After you&#8217;ve managed to understand the code you can improve it in two ways: add comments that describe what it is doing or refactor the code to make it easier to understand. Dave did all the hard work of figuring out the <code>isqrt</code> method. But it is still a difficult method to follow.
</span></p>

<p>Let&#8217;s see if we can make the code speak for itself.</p>

<p>My first change was the name of the method from <code>isqrt</code> to <code>integer_square_root_of</code>. There is no reason to drop vowels like we&#8217;re writing C in the 70&#8217;s. Storage is cheap. Editors autocomplete. Don&#8217;t be afraid of descriptive variable and method names. I&#8217;m not sure if the &ldquo;i&rdquo; in <code>isqrt</code> was supposed to mean <em>integer</em> because the method returns an integer approximation of the square root, or <em>iterative</em> because the method uses an iterative algorithm to determine the square root. I went with &ldquo;integer&rdquo; so that the method signature now describes exactly what it does: give you the integer square root of a square.</p>

<figure class='code'><figcaption><span>My Version  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">integer_square_root_of</span><span class="p">(</span><span class="n">square</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>My next change was to drop the comment <code>just in case we don't get an int</code>. This comment doesn&#8217;t really hurt, but it also doesn&#8217;t add anything that isn&#8217;t already immediately obvious.  Furthermore, there should be a test that shows that the method behaves as expected when receiving a non integer parameter.</p>

<figure class='code'><figcaption><span>Test  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">test</span> <span class="s2">&quot;integer_square_root_of should convert non int squares to int&quot;</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">assert_equal</span> <span class="mi">3</span><span class="p">,</span> <span class="n">integer_square_root_of</span><span class="p">(</span><span class="mi">9</span><span class="o">.</span><span class="mi">9</span><span class="p">)</span>
</span><span class='line'>  <span class="n">assert_equal</span> <span class="mi">3</span><span class="p">,</span> <span class="n">integer_square_root_of</span><span class="p">(</span><span class="s1">&#39;9&#39;</span><span class="p">)</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Not hurting isn&#8217;t a good enough reason to add a comment to your code. There must be a compelling reason to add a comment. Since this comment doesn&#8217;t meet that standard we&#8217;re going to go ahead and remove it.</p>

<p>Next up are the special cases: when the square is 0 we short circuit and return 0. When the square is negative we raise a RangeError because there is no such real number square root of a negative number and our method would go into an infinite loop if we didn&#8217;t raise an exception. In the original version they were written like this:</p>

<figure class='code'><figcaption><span>Original  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="n">square</span> <span class="o">=</span> <span class="n">square</span><span class="o">.</span><span class="n">to_i</span>
</span><span class='line'>  <span class="k">return</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">square</span> <span class="o">==</span> <span class="mi">0</span>
</span><span class='line'>  <span class="k">raise</span> <span class="no">RangeError</span> <span class="k">if</span> <span class="n">square</span> <span class="o">&lt;</span> <span class="mi">0</span>
</span></code></pre></td></tr></table></div></figure>


<p><span class='pullquote-right' data-pullquote='Think of your application&apos;s source code as a book. Classes are chapters. Methods are sections. Each line of code is a sentence.'>
The first thing I did was add a blank line to separate them from line 2 (line 1 above as I haven&#8217;t figured out how to specify line numbers in Octopress) where we ensure that square is an integer. Blank lines inside of a method definition are greatly underutilized as a tool for grouping related code and improving readability. Think of your application&apos;s source code as a book. Classes are chapters. Methods are sections. Each line of code is a sentence. And using blank lines lets us group our &ldquo;sentences&rdquo; (lines of code) into paragraphs.</p>

<p>Next I changed the checks for the special cases from two independent lines with postfix <code>if</code> statements to a combined <code>if / elsif</code> structure. Functionally, this is equivalent to the original version. However, by choosing to group them together in one logical block it further serves to emphasize that these two lines are related and draws further attention to the conditionals.</p>

<p>I also add a message to the <code>RangeError</code> that is raised if the square is a negative number. This is an example of what I call <em>executable comments</em>. The body of the message explains <em>why</em> we&#8217;re raising the exception&mdash;much as a comment would&mdash;but because it is part of the executable code it is far less likely to fall out of sync as the code changes.
</span></p>

<p>This yields the following snippet:</p>

<figure class='code'><figcaption><span>My Version  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="n">square</span> <span class="o">=</span> <span class="n">square</span><span class="o">.</span><span class="n">to_i</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="n">square</span> <span class="o">==</span> <span class="mi">0</span>
</span><span class='line'>    <span class="k">return</span> <span class="mi">0</span>
</span><span class='line'>  <span class="k">elsif</span> <span class="n">square</span> <span class="o">&lt;</span> <span class="mi">0</span>
</span><span class='line'>    <span class="k">raise</span> <span class="no">RangeError</span><span class="p">,</span> <span class="s2">&quot;square must be non-negative. No negative number has a real square root&quot;</span>
</span><span class='line'>  <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Continuing on, variable names like <code>n1</code> and <code>n2</code> don&#8217;t tell us anything, so I changed them to <code>upper_guess</code> and <code>lower_guess</code>. These names are far from perfect, but they at least suggest that as we continue to iterate these two variables will converge on the square root.</p>

<figure class='code'><figcaption><span>My Version  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="n">upper_guess</span> <span class="o">=</span> <span class="n">next_guess</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="n">lower_guess</span> <span class="o">=</span> <span class="n">next_guess</span><span class="p">(</span><span class="n">upper_guess</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>I also renamed the method <code>iter</code> to <code>next_guess</code> as that is what it does, give us our next guess.</p>

<figure class='code'><figcaption><span>My Version  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">next_guess</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="p">(</span><span class="n">square</span> <span class="o">/</span> <span class="n">n</span><span class="p">))</span> <span class="o">/</span> <span class="mi">2</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now for the main work of the method. First, we repeatedly refine our guesses. Then, when we&#8217;re close enough, we decrement the guess until we get to our answer.</p>

<figure class='code'><figcaption><span>Dave&#8217;s Version with Comments  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="c1"># Refine our guesses until we get close enough</span>
</span><span class='line'>  <span class="n">n1</span><span class="p">,</span> <span class="n">n</span> <span class="o">=</span> <span class="n">iter</span><span class="p">(</span><span class="n">n1</span><span class="p">,</span> <span class="n">square</span><span class="p">),</span> <span class="n">n1</span> <span class="k">until</span> <span class="n">n1</span> <span class="o">&gt;=</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span>
</span><span class='line'>  <span class="c1"># We&#39;re close enough when we&#39;re JUST under square</span>
</span><span class='line'>  <span class="n">n1</span> <span class="o">=</span> <span class="n">n1</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">until</span> <span class="n">n1</span><span class="o">*</span><span class="n">n1</span> <span class="o">&lt;=</span> <span class="n">square</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">n1</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>First, I again introduce whitespace to separate logically distinct steps.</p>

<p>The next thing I do is unpack the loop statements from one-liners to blocks. The ability to use postfix loop operators is a good tool for brevity in Ruby. However, a double variable assignment <em>and</em> a loop operator is simply too much for one line. By splitting the loop condition from the variable assignment I allow the reader to focus on each part independently.</p>

<p>Finally, I switch from to <code>while</code> from <code>until</code> for the looping logic. <code>while</code> says &#8220;check if this is true then execute the statement and loop&#8221; <code>until</code> says &#8220;check if this statement is false, and then execute the statement and loop.&#8221; This may be a matter of preference, but I find positive logic easier to understand then negative logic.</p>

<figure class='code'><figcaption><span>My Version  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="k">while</span> <span class="n">lower_guess</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">upper_guess</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">lower_guess</span><span class="p">,</span> <span class="n">upper_guess</span> <span class="o">=</span> <span class="n">next_guess</span><span class="p">(</span><span class="n">lower_guess</span><span class="p">,</span> <span class="n">square</span><span class="p">),</span> <span class="n">lower_guess</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">while</span> <span class="n">lower_guess</span> <span class="o">*</span> <span class="n">lower_guess</span> <span class="o">&gt;</span> <span class="n">square</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">lower_guess</span> <span class="o">=</span> <span class="n">lower_guess</span> <span class="o">-</span> <span class="mi">1</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="n">lower_guess</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now, my version is complete:</p>

<figure class='code'><figcaption><span>My Version  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">integer_square_root_of</span><span class="p">(</span><span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="n">square</span> <span class="o">=</span> <span class="n">square</span><span class="o">.</span><span class="n">to_i</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="n">square</span> <span class="o">==</span> <span class="mi">0</span>
</span><span class='line'>    <span class="k">return</span> <span class="mi">0</span>
</span><span class='line'>  <span class="k">elsif</span> <span class="n">square</span> <span class="o">&lt;</span> <span class="mi">0</span>
</span><span class='line'>    <span class="k">raise</span> <span class="no">RangeError</span><span class="p">,</span> <span class="s2">&quot;square must be non-negative. No negative number has a real square root&quot;</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">upper_guess</span> <span class="o">=</span> <span class="n">next_guess</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="n">lower_guess</span> <span class="o">=</span> <span class="n">next_guess</span><span class="p">(</span><span class="n">upper_guess</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">while</span> <span class="n">lower_guess</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">upper_guess</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">lower_guess</span><span class="p">,</span> <span class="n">upper_guess</span> <span class="o">=</span> <span class="n">next_guess</span><span class="p">(</span><span class="n">lower_guess</span><span class="p">,</span> <span class="n">square</span><span class="p">),</span> <span class="n">lower_guess</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">while</span> <span class="n">lower_guess</span> <span class="o">*</span> <span class="n">lower_guess</span> <span class="o">&gt;</span> <span class="n">square</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">lower_guess</span> <span class="o">=</span> <span class="n">lower_guess</span> <span class="o">-</span> <span class="mi">1</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="n">lower_guess</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">next_guess</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">square</span><span class="p">)</span>
</span><span class='line'>  <span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="p">(</span><span class="n">square</span> <span class="o">/</span> <span class="n">n</span><span class="p">))</span> <span class="o">/</span> <span class="mi">2</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This post took quite some time to write because explaining code takes a long time. Thankfully, writing code doesn&#8217;t. I think it only took me about 15 minutes to read, understand, and rewrite the <code>isqrt</code> method. My bet is that it would have taken about the same amount of time to read, understand, and comment it.</p>

<p>Is this clearer than Dave&#8217;s commented version? I obviously think it is, but it still a bit unclear. Perhaps a comment or two would help. My argument isn&#8217;t that <em>all</em> comments are unnecessary. It is that <em>the vast majority</em> of comments are unnecessary and that time spent writing comments can be better spent writing clearer code.</p>

<p>What do you think?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Boxee, Hulu, and the Future of Video Advertising]]></title>
    <link href="http://pragmati.st/2009/02/20/boxee-hulu-and-the-future-of-video-advertising/"/>
    <updated>2009-02-20T00:00:00-05:00</updated>
    <id>http://pragmati.st/2009/02/20/boxee-hulu-and-the-future-of-video-advertising</id>
    <content type="html"><![CDATA[<p><img src="http://pragmati.st/assets/2009/2/20/boxee_home.png" alt="" /></p>
<p><a href="http://boxee.tv">Boxee</a> is a fork of the excellent <a href="http://xbmc.org/"><span class="caps">XBMC</span> media player</a> that runs on Macs, AppleTVs and Linux. It provides a great remote control based interface for accessing your stored video, music, and photo libraries on your TV, as well as providing site specific browsers for viewing media from the internet sources like YouTube, Comedy Central, the <span class="caps">BBC</span>, <span class="caps">CNN</span>, Last.fm, Flickr, Picassa, and, at least for a few more days, Hulu. For a more in depth introduction check out this New York Times <a href="http://www.nytimes.com/2009/01/17/technology/internet/17video.html?_r=2">article</a>.</p>
<p>Hulu recently announced that they were being asked by their content providers to cut off access to Boxee. So as of about 20 minutes ago, you can&#8217;t access Hulu via boxee. A lot of people, myself included, are really annoyed at this. I think that <a href="http://radar.oreilly.com/2009/02/hulus-superbowl-ad-and-the-box.html">Marc Hedlund</a> pretty much nailed it.</p>
<p><img src="http://pragmati.st/assets/2009/2/20/hulu_down.png" alt="" /></p>
<p>Basically, the studios are worried about anything that makes it easy for the general public to view video content on their TVs over the Internet. Never mind that this is what people want, or that there I can and will still watch Hulu on my TV (see <a href="http://www.avc.com/a_vc/2009/02/the-valentines-day-breakup.html">Fred Wilson&#8217;s take</a>). The studios are worried about the cannibalization of their television audience. Hulu has ads, but television ads are <em>much</em> more lucrative. The studios are going to protect that market, at all costs, for as long as they can.</p>
<p>I think that the studios are being short sighted and incredibly stupid, but I&#8217;m going to choose to focus on another question: Why are TV ads more profitable than video ads in a Hulu stream on a <em>per impression</em> basis?</p>
<h2>Television Advertising</h2>
<p>Television is fundamentally a mass media. Everyone watching a TV show gets the same ads (well, mostly, but not exactly as local affiliates and cable providers do insert certain local ads) But there are fundamental limitation on how well they know their audience. Simply put, there is no way to know <em>who</em> is watching the ad, so the best they can do is target the demographic average. Never are the limitations of this approach more clear than when you watch a show for which you are clearly not the normal viewer. Let&#8217;s call it the &#8220;Top Chef Problem&#8221;.</p>
<p>I watch Top Chef. There. I said it. I find the reality show portions pretty annoying, but I love food, love cooking, and damn if that show isn&#8217;t entertaining. However, watching the ads makes it really clear that I&#8217;m not their target audience&#8212; women with children are. So the vast majority of ads are a complete waste on me. I&#8217;m not buying beauty products or minivans. There is no way that I&#8217;m going to watch the Real Housewives of Orange County, so they might as well stop advertising it to me.</p>
<p>But, since with TV ads there is no way to know that I&#8217;m a 27 year old straight man who happens to love cooking and drinking, they keep showing me ads I have no interest in, and Dove Body Wash keeps paying for ads that have no chance of turning me into a consumer.</p>
<h2>Internet Video Advertising</h2>
<p>What about Internet Video Ads. Unfortunately, the state of the art seems in Internet Video Ads seems to be roughly equivalent to that of TV advertising. Actually, it could be even a little worse.</p>
<p>Last night, I watched a few streaming episodes of South Park last (from Comedy Central via Boxee). I saw the same ad for Jack In The Box over and over. I live in Maryland. The closest Jack In The Box is in North Carolina. Jack In The Box paid for an ad that has absolutely no chance of converting me to a customer.</p>
<p>This should never happen. Advertising on an Internet Video Stream isn&#8217;t a mass media. Its a targeted media. They&#8217;re streaming the show to <em>me</em>. And they know a ton about me. Lets look at the bare minimum that they know:</p>
<ul>
	<li>My location. Geolocation isn&#8217;t that tough. Looking up my IP gives my location within 2 miles. No more Jack In The Box ads.</li>
	<li>My <span class="caps">ISP</span>. At my present location, Comcast. Why then does Hulu regularly show me ads for Comcast High Speed Internet when I watch Hulu <em>over</em> Comcast internet.</li>
	<li>They know I use a Mac. Probably not a ton of use in showing me ads for the Zune. Sorry, Microsoft.</li>
	<li>What I watch. Based on my cookie they know what other shows I watch on Hulu.</li>
</ul>
<h2>The Future</h2>
<p>This isn&#8217;t even taking into account the truly scary amount of data that Double Click / Google / Facebook have accumulated about me on my travels across the web.</p>
<p>Lets go back to the &#8220;Top Chef Problem&#8221;. Imagine what they could do with all that information. No more ads for minivans. No more ads for makeup. No more ads for easy to prepare meals for kids.</p>
<p>Instead, they show me ads for local restaurants, wine and beer.</p>
<p>Now, lets put all the stuff DoubleClick knows about me to work. They know I&#8217;m a Software Engineer, so they show me job listings. They know I&#8217;m hip hop fan, so they advertise an upcoming Mos Def concert. They know I play soccer, so they show me a Nike soccer ad. They know I read <a href="http://aveceric.com">aveceric.com</a> religiously, so show me an ad for <a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FLine-Eric-Ripert%2Fdp%2F1579653693%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1212681030%26sr%3D1-3&amp;tag=aveeri-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325">On The Line</a></p>
<p>Ads this targeted have to be worth much more, per view, to advertisers. So it would reason that advertisers would pay more per view for them. So even though internet video will need to include fewer ads than traditional television (to effectively compete with bittorrent / other sites that don&#8217;t have any ads) the studios could still make just as much money, or more, per view than by selling more expensive ads.</p>
<p>Wouldn&#8217;t it be more productive for media companies to spend their time and money investing in advertising technology then engaging in a Sisyphian struggle to protect the staus quo?</p>
<p>The future of video entertainment is on demand. The media companies aren&#8217;t going to be able to continue to extract rents (meant in the <a href="http://en.wikipedia.org/wiki/Economic_rent">economic sense</a>) from controlling distribution. In a digital world, once you release something people are going to be able to get it on the device they want. The only question is how the media companies figure out a way to make money off of that.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Teachers and Quarterbacks]]></title>
    <link href="http://pragmati.st/2008/12/18/teachers-and-quarterbacks/"/>
    <updated>2008-12-18T00:00:00-05:00</updated>
    <id>http://pragmati.st/2008/12/18/teachers-and-quarterbacks</id>
    <content type="html"><![CDATA[<p><img src="http://pragmati.st/assets/2008/12/18/quarterbacks_and_teachers.jpg" alt="" /></p>
<p>- Quarterbacks by <a href="http://www.flickr.com/photos/ableman/">Ableman</a> / Teacher by <a href="http://www.flickr.com/photos/editor/">Editor B</a></p>
<p><a href="http://www.newyorker.com/reporting/2008/12/15/081215fa_fact_gladwell?currentPage=all">Most Likely to Succeed</a>, the most recent Malcom Gladwell piece in The New Yorker, is a really interesting look at the similarities between trying to draft an <span class="caps">NFL</span> quarterback and trying to hire a good public school teacher. The main similarity being that we are incredibly bad at predicting success in either field.</p>
<p>For all the effort on scouting, combines, and testing of college quarterbacks it turns out that there is no demonstrated correlation between wonderlic test scores or draft position with an <span class="caps">NFL</span> quarterback&#8217;s career performance. Similarly, teachers who earn a Masters Degree or an advanced teaching certificate don&#8217;t perform any better than those with a vanilla bachelor&#8217;s degree. So <span class="caps">NFL</span> teams end up selecting <a href="http://en.wikipedia.org/wiki/Ryan_Leaf">Ryan Leaf</a> with the number one pick and giving him an 11 million dollar signing bonus while passing on <a href="http://en.wikipedia.org/wiki/Tom_Brady">Tom Brady</a> until the 199th pick. Similarly, and more important for society, we end up with teachers who have Masters Degrees, but couldn&#8217;t teach you how to make a peanut butter and jelly sandwich.</p>
<p>I&#8217;ve always found the way we select teachers strange. You don&#8217;t need a master&#8217;s degree in math to teach high school geometry. The skills needed to earn an advanced degree and the skills needed to be a good teacher are completely different. Sure, sometimes those skills develop in the same person, but I&#8217;m willing to wager that is the exceptional case.</p>
<p>Let me make a quick conterfactual argument: If education and intelligence correlated with teaching performance, then college TA&#8217;s (generally Masters or PhD candidates who are incredibly intelligent and know the material inside out) would be great teachers. I think anyone who ever had a Calculus, Physics or Comp Sci class in college will immediately agree that this most certainly is <strong>not</strong> the case.</p>
<p>In fact, I think you can make a good argument that the skills and attributes you need to earn a Master&#8217;s Degree in math (to take one example) are a significant <em>negative</em> predictor of success in teaching.</p>
<p>Let&#8217;s face it, there is no subject taught in high school that requires a graduate level understanding of the material. The most difficult subject taught in high school is probably Calc AB and that is something that we expect college freshmen to master. The skills needed to be a great teacher are almost entirely social: you need to be able to engage your students, explain the material in multiple ways, control a classroom, and have a remarkable amount of patience with your students. These are not the skills that graduate level academics select for.</p>
<p>I know brilliant people who became teachers and failed miserably. I&#8217;m also fairly certain that some of the best teachers I had were actually pretty low on the IQ scale. If we as a nation are serious about improving education we need to look at ways to find and train better teachers.</p>
<p>There is a lot more I could say about this: about how we face the same problem in hiring programmers, or about what the implications of admitting we are terrible at predicting success are. But it is late, and I am tired, so maybe another day.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Alexa Web Crawler - TamperedWithCookie Error]]></title>
    <link href="http://pragmati.st/2008/12/02/alexa-web-crawler-tamperedwithcookie-error/"/>
    <updated>2008-12-02T00:00:00-05:00</updated>
    <id>http://pragmati.st/2008/12/02/alexa-web-crawler-tamperedwithcookie-error</id>
    <content type="html"><![CDATA[<p>I&#8217;ve recently started receiving a ton of <code>CGI::Session::CookieStore::TamperedWithCookie</code> errors on an application I manage. All of the errors are coming from the <a href="http://www.alexa.com/site/help/webmasters">Alexa Web Crawler</a>.</p>
<p>The application is using the <a href="http://ryandaigle.com/articles/2007/2/21/what-s-new-in-edge-rails-cookie-based-sessions">Cookie Session Store</a> (<a href="http://railscasts.com/episodes/84">Railscast</a>) introduced in Rails 2. Upon inspection it appears that the problem is related to the newline characters rails inserts every 60 characters. Rails encodes these newlines as %0A. The alexa web crawler seems to convert these to \n. This is the only difference between the two cookies that I can see.</p>
<p>Rails Cookie:</p>
<pre>
<code>
_application_session=BAh7CToMY3NyZl9pZCIlZDA1ODAzY2MwZGZjNzJkN2I4NGFjZTE5OTcxNzZh%0ANjI6FnNlYXJjaF9jYXRlZ29yaWVzWxRvOg1DYXRlZ29yeQc6FkBhdHRyaWJ1%0AdGVzX2NhY2hlewA6EEBhdHRyaWJ1dGVzewciCW5hbWUiFUF1dG8gLyBUcmFu%0Ac3BvcnQiB2lkIgYxbzsHBzsIewA7CXsHIgluYW1lIhNCZWF1dHkgLyBJbWFn%0AZSIHaWQiBjVvOwcHOwh7ADsJewciCW5hbWUiEkJvYXQgLyBNYXJpbmUiB2lk%0AIggxMTVvOwcHOwh7ADsJewciCW5hbWUiFUJ1c2luZXNzIC8gQWRtaW4iB2lk%0AIgY5bzsHBzsIewA7CXsHIgluYW1lIhRDb21wdXRlciAvIFRlY2giB2lkIgcx%0AMW87Bwc7CHsAOwl7ByIJbmFtZSIVQ3JlYXRpdmUgLyBNZWRpYSIHaWQiBzEy%0AbzsHBzs;
</code>
</pre>
<p>Alexa Crawler Request Cookie:</p>
<pre>
<code>
_application_session=BAh7CToMY3NyZl9pZCIlOGJlNGQ2ZGYzYWZjODRhZGI4YmNlMWUxZTkwNmNl\nYjA6FnNlYXJjaF9jYXRlZ29yaWVzWxRvOg1DYXRlZ29yeQc6FkBhdHRyaWJ1\ndGVzX2NhY2hlewA6EEBhdHRyaWJ1dGVzewciCW5hbWUiFUF1dG8gLyBUcmFu\nc3BvcnQiB2lkIgYxbzsHBzsIewA7CXsHIgluYW1lIhNCZWF1dHkgLyBJbWFn\nZSIHaWQiBjVvOwcHOwh7ADsJewciCW5hbWUiEkJvYXQgLyBNYXJpbmUiB2lk\nIggxMTVvOwcHOwh7ADsJewciCW5hbWUiFUJ1c2luZXNzIC8gQWRtaW4iB2lk\nIgY5bzsHBzsIewA7CXsHIgluYW1lIhRDb21wdXRlciAvIFRlY2giB2lkIgcx\nMW87Bwc7CHsAOwl7ByIJbmFtZSIVQ3JlYXRpdmUgLyBNZWRpYSIHaWQiBzEy\nbzsHBzs
</code>
</pre>
<p>I&#8217;m <a href="http://willj.net/blog/2008/03/19/bad-cookie/">not the only person</a> having this problem. Any ideas?</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Interesting Things to Read]]></title>
    <link href="http://pragmati.st/2008/11/21/interesting-things-to-read/"/>
    <updated>2008-11-21T00:00:00-05:00</updated>
    <id>http://pragmati.st/2008/11/21/interesting-things-to-read</id>
    <content type="html"><![CDATA[<p>I&#8217;ve recently read some excellent long form magazine articles.</p>
<h2>Michael Lewis</h2>
<h3><a href="http://www.portfolio.com/news-markets/national-news/portfolio/2008/11/11/The-End-of-Wall-Streets-Boom">The End</a></h3>
<p>Michael Lewis is the author of Liar&#8217;s Poker, Moneyball, and The Blind Side (all excellent books). Before becoming an author he worked at Salomon Brothers in the 1980&#8217;s when they were the first investment bank to go public and one of his immediate co-workers invented the mortgage backed security. It is an excellent examination of just how badly fucked the system was.</p>
<p>Also to the &#8220;How did professionals so badly misjudge risk and fuck us all?&#8221; category are two excellent episodes of This American Life from earlier this year: <a href="http://www.thislife.org/Radio_Episode.aspx?episode=355">The Giant Pool of Money</a> and <a href="http://www.thislife.org/Radio_Episode.aspx?episode=365">Another Frightening Show About</a> the Economy.</p>
<h2>David Foster Wallace</h2>
<p>I&#8217;ve also recently read two excellent David Foster Wallace essays. I actually came to both organically as they were linked to from other things I was reading. Still, I feel a bit guilty to only now be reading more Wallace. (I&#8217;d only read the <a href="http://www.nytimes.com/2006/08/20/sports/playmagazine/20federer.html?pagewanted=all">Federer piece</a> and <a href="http://www.gourmet.com/magazine/2000s/2004/08/consider_the_lobster">Consider the Lobster</a> while he was alive)</p>
<h3><a href="http://www.theatlantic.com/doc/200504/wallace">Host</a></h3>
<p>About talk radio host John Ziegler (Who recently got involved in some controversy with FiveThirtyEight.com and a generally ridiculous <a href="http://www.fivethirtyeight.com/2008/11/interview-with-john-ziegler-on-zogby.htmli">interview</a> about an upcoming &#8220;<a href="http://howobamagotelected.com/">documentary</a>&#8221; he is releasing) By the way, the quotes around &#8220;documentary&#8221; are because he has a clear agenda in making the film, not because of its ideological content. That, in my opinion, renders it editorial or argument, but not a documentary. I would also use quotes if referring to Michael Moore&#8217;s &#8220;documentaries&#8221;</p>
<h3><a href="http://www.esquire.com/features/sports/the-string-theory-0796">The String Theory</a></h3>
<p>About Michael Joyce, at the time the 89th ranked professional tennis player in the world. However, to say that it is about a tennis player does not even remotely do the piece justice. It is about specialization, sacrifice, grotesqueness, desire, and talent. I think it was even better than the Federer piece which was amazing.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Error - rake ultrasphinx:configure]]></title>
    <link href="http://pragmati.st/2008/11/07/error-rake-ultrasphinx-configure/"/>
    <updated>2008-11-07T00:00:00-05:00</updated>
    <id>http://pragmati.st/2008/11/07/error-rake-ultrasphinx-configure</id>
    <content type="html"><![CDATA[<p>A new Web Designer I work with was running into an error when attempting to configure ultrasphinx for his local Rails development environment.</p>
<pre>
<code>
rake ultrasphinx:configure

rake aborted!
Anonymous modules have no name to be referenced by
/var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:402:in `to_constant_name'
/var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:214:in `qualified_name_for'
/var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:477:in `const_missing'
/home/deploy/apps/stylespotted/releases/20080131024018/vendor/plugins/ultrasphinx/lib/ultrasphinx/configure.rb:33:in `load_constants'
</code>
</pre>
<p>I was baffled for this for a few days. We finally figured it out this afternoon.</p>
<p>He is a UI developer, and new to Rails, so hadn&#8217;t created his DB. The fix was simple:</p>
<pre>
<code>
rake db:create
rake db:migrate
rake ultrasphinx:configure
</code>
</pre>
<p>And he had a working development.conf for Ultrasphinx</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Election 2008]]></title>
    <link href="http://pragmati.st/2008/11/05/election-2008/"/>
    <updated>2008-11-05T00:00:00-05:00</updated>
    <id>http://pragmati.st/2008/11/05/election-2008</id>
    <content type="html"><![CDATA[<p><img src="http://pragmati.st/assets/2008/11/5/white_house_celebration.jpg" alt="" /></p>
<p>- flickr user <a href="http://flickr.com/photos/sanjaysuchak/3004768941/in/set-72157608678986035/">sanjaysuchak</a></p>
<p>Anyone who knows me knows that I am very happy with the outcome, but regardless of your politics you have to admit that we witnessed something special.</p>
<h2>A quick story</h2>
<p>My mom worked as an election judge in Montgomery County. She was at the polls from 6 AM to after 10 PM and said she&#8217;d never seen anything like it. 2 hour lines, people genuinely excited, 65% turnout. She shared a story that I think illustrates why yesterday was special.</p>
<p>When the polls opened at 7AM there was already a line. While waiting, a 74 year old black man fainted. An ambulance was called, and while they were wheeling him out on a stretcher <del>he asked if he could vote before he left</del> (Edit 11/13/2008: Apparently I misheard my mother&#8217;s telling of the story. <em>She</em> asked the <span class="caps">EMT</span> about letting the man vote. Still a good story in my opinion). The <span class="caps">EMT</span> said it wasn&#8217;t worth risking his life over. My mom promised him that if he made it back he&#8217;d go straight to the front of the line.</p>
<p>A few hours later he came back in a wheelchair and cast his vote.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Me Meme]]></title>
    <link href="http://pragmati.st/2008/10/15/the-me-meme/"/>
    <updated>2008-10-15T00:00:00-04:00</updated>
    <id>http://pragmati.st/2008/10/15/the-me-meme</id>
    <content type="html"><![CDATA[<p>Taking a break from work to participate in a silly blog meme.</p>
<p><img src="http://pragmati.st/assets/2008/10/15/the_me_meme.jpg" alt="" /></p>
<ol>
	<li>Take a picture of yourself right now.</li>
	<li>Don&apos;t change your clothes, don&apos;t fix your hair&mdash;just take a picture. (should be super-easy with Photobooth)</li>
	<li>Post that picture with NO editing.</li>
	<li>Post these instructions with your picture.</li>
</ol>
<p>via <a href="http://www.flickr.com/photos/raganwald/2909791653/">raganwald</a></p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Freezing to Rails 2.0.4]]></title>
    <link href="http://pragmati.st/2008/09/22/freezing-to-rails-2-0-4/"/>
    <updated>2008-09-22T00:00:00-04:00</updated>
    <id>http://pragmati.st/2008/09/22/freezing-to-rails-2-0-4</id>
    <content type="html"><![CDATA[<p>One of our applications is still running Rails 2.0. I&#8217;m planning to upgrade to 2.1 soon, but in the meantime I wanted to upgrade to <a href="http://weblog.rubyonrails.org/2008/9/3/rails-2-0-4-maintenance-release">2.0.4</a> to get the patch for the <a href="http://weblog.rubyonrails.org/2008/8/23/dos-vulnerabilities-in-rexml"><span class="caps">REXML</span> DoS vulnerability</a>. We freeze our version of Rails (and so should you) but I couldn&#8217;t freeze in the normal way:</p>
rake rails:freeze:edge
<p>This resulted in a message that the release was not found so it checked out the head instead.</p>
<p>I managed to freeze by running the following two commands:</p>
sudo gem install rails &#8212;version 2.0.4
rake environment <span class="caps">VERSION</span>=2.0.4 rails:freeze:gems]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Explanatory Text is a UI Design Smell]]></title>
    <link href="http://pragmati.st/2008/07/26/explanatory-text-is-a-ui-smell/"/>
    <updated>2008-07-26T00:00:00-04:00</updated>
    <id>http://pragmati.st/2008/07/26/explanatory-text-is-a-ui-smell</id>
    <content type="html"><![CDATA[<p>I&#8217;ve had to switch the phone on my Verizon account a few times in the last couple of weeks. Verizon has an online tool that makes it pretty easy. You login to your account, click on &#8220;My Phone&#8221;, click &#8220;Activate a Phone&#8221; and then enter your <span class="caps">ESN</span> or <span class="caps">MEID</span>. The <span class="caps">ESN</span> or <span class="caps">MEID</span> is the unique identifier of the handset and is typically found in very small text underneath the battery.</p>
<p>All in all it is a very good experience and makes a fairly arcane task pretty easy. However, there is one bit of explanatory text (highlighted in red) that offers an opportunity for an improved user experience.</p>
<p><img src="http://pragmati.st/assets/2008/7/26/verizon_esn_tips.png" alt="" /></p>
<p>Since <span class="caps">ESN</span> or <span class="caps">MEID</span> is either in decimal or hexidecimal there never will be the letter O it will always be the number 0. However, my mother shouldn&#8217;t have to think about hexadecimal base numbers if she is changing her phone. A better solution would be to just treat the letter O as the number 0. Then the user doesn&#8217;t have to worry about it, and you can get rid of the explanatory text.</p>
<p>This reminds me of <a href="http://martinfowler.com/bliki/CodeSmell.html">code smells</a>. A code smell is a <em>symptom</em> that there may be deeper issues with the code. For instance, long methods are a code smell. They don&#8217;t mean that there is necessarily a problem with the code, but they do suggest that there is a good chance there is.</p>
<p>I think that long blocks of explanatory text are a User Experience smell. Sometimes there isn&#8217;t a better option, and you really need that text, but in most cases a little extra thought about the UI can eliminate the need for the explanatory text.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Smartphones]]></title>
    <link href="http://pragmati.st/2008/07/01/smartphones/"/>
    <updated>2008-07-01T00:00:00-04:00</updated>
    <id>http://pragmati.st/2008/07/01/smartphones</id>
    <content type="html"><![CDATA[<p>I think that the release last year of the iPhone represented the biggest jump in computing since the introduction of the personal computer in the 1980&#8217;s. The iPhone is not a &#8220;smartphone&#8221; in the sense of its predecessors. It is a handheld computer that happens to do voice well.</p>
<p>The designers clearly were willing to sacrifice to optimize for how mobile devices are actually used. The biggest complaint about the iPhone is the lack of a physical keyboard. The touch screen keyboard <em>is</em> cumbersome. It is sufficient for typing short messages, but is woefully inadequate for long passages of text. However, the decision to abandon a physical keyboard allows for a much larger screen. Without the large screen surfing the web, reading emails, and watching video would not work as well. A larger screen makes it much easier to <em>recieve</em> information. And that is the crux of the mobile experience. A mobile device is primarily used to pull information; to look up directions, check movie times, read an email. If you need to write more than 2 or 3 lines for an email it can probably wait until you get back to a full computer. The willingness to sacrifice the uncommon to make the common delightful is what makes the iPhone great.</p>
<p>This is not to say that I think the iPhone is the end all and be all of mobile interfaces. As much as I love it, it is not perfect. There have to be other interesting approaches to mobile computing. Unfortunately, all the existing phone producers have done is to produce cheap imitations. Just google for &#8220;iphone killer&#8221; to see a sad array of products without an original idea.</p>
<p><img src="http://pragmati.st/assets/2008/6/28/iphone_and_knockoffs.jpg" alt="" /></p>
<p>What the mobile space most needs is legitimate competition (If you think that Windows Mobile or <span class="caps">RIM</span> count, then I just don&#8217;t know what to tell you) <a href="http://code.google.com/android/">Android</a> could be very interesting, but I&#8217;m not sure if Google is going to be able to pull it off. Apple managed to produce the iPhone by completely controlling the hardware and software, and by pistol whipping one of the weaker carriers into allowing it. Google is trying to build a platform with multiple hardware manufacturers and networks. I don&#8217;t see how they&#8217;re going to be able to get them all on one page. I&#8217;m also not sure how one is supposed to effectively develop applications for the various phones with wildly different hardware.</p>
<p>That said, the first round of winners in the <a href="http://code.google.com/android/adc.html">Android Developer Challenge</a> include some very interesting applications. I&#8217;m particularly excited about <a href="http://scan.jsharkey.org/">Android Scan</a> an application that lets you scan the barcode of a book, movie, or CD using the camera on your phone and instantly get reviews, samples and comparison shop online. I think that this is going to be really useful. Imagine being able to scan the barcode of a bottle of wine and instantly get reviews as well as finding out that it&#8217;s half price down the street. This is the future of shopping.</p>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/bwhdXJuiO48&hl=en"></param><embed src="http://www.youtube.com/v/bwhdXJuiO48&hl=en" type="application/x-shockwave-flash" width="425" height="344"></embed></object></p>
<p>A lot of the other winners are underwhelming. There are a lot of location based social networks that will never get to a critical mass and a lot of emergency notification apps. Still there is a ton of potential, and an open mobile platform is really exciting. I love the idea of being able to replace the email client on my phone if I don&#8217;t like it. We&#8217;re in the infancy of designing for mobile devices, and the lower the barrier to entry the better. We need more people trying new things.</p>
<p>In the end I think that the iPhone is going to remain the pinnacle of mobile experience for some time. The seamless experience Apple has created is going to be hard to beat. If Android comes out before the iPhone becomes available on all carriers I think it will find a decent market. I would strongly consider an Android phone before switching away from Verizon&#8217;s network.</p>
<p>At least I am hopeful about the future of mobile devices, and that is something I&#8217;ve never been able to say be before.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Cool Shopping Cart Interface]]></title>
    <link href="http://pragmati.st/2008/05/02/cool-shopping-cart-interface/"/>
    <updated>2008-05-02T00:00:00-04:00</updated>
    <id>http://pragmati.st/2008/05/02/cool-shopping-cart-interface</id>
    <content type="html"><![CDATA[<p><a href="http://baggubag.com/">Baggu</a> sells reusable shopping bags. Their <a href="http://baggubag.com/SHOP.html">shop</a> has a simple interface that makes it really easy to visualize what you&#8217;re purchasing.</p>
<p><img src="http://pragmati.st/assets/2008/5/2/baggu_shopping_interface.png" alt="" /></p>
<p>Reusable shopping bags are a good way to cut down on our consumption. I bought the beautiful gray one from <a href="http://bagthehabit.com/products.html">BagTheHabit</a> for my girlfriend for Christmas.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Web Content Mavens Meeting: Tuning Up Your Web Analytics]]></title>
    <link href="http://pragmati.st/2008/04/24/web-content-mavens-meeting-tuning-up-your-web-analytics/"/>
    <updated>2008-04-24T00:00:00-04:00</updated>
    <id>http://pragmati.st/2008/04/24/web-content-mavens-meeting-tuning-up-your-web-analytics</id>
    <content type="html"><![CDATA[<p>I attended the <a href="http://webcms.meetup.com/39/calendar/7471411/">Web Content Mavens Meeting</a> tonight. <a href="http://www.pkwc.com/exec/bio.php">Phil Kemelor</a> gave a presentation on &#8220;Tuning Up Your Web Analytics&#8221;</p>
<p>I didn&#8217;t think that the presentation itself provided much value. Everything that Phil said boiled down to the following: <strong>Make sure everything you do with web analytics helps the business.</strong></p>
<p>In other words, <em>think</em> about what questions you want your web analytics to help you answer and always try to tie that back to something of business value. This is a very important point, but one that I feel is self-evident and certainly one that can be made in less than an hour.</p>
<p>I was disappointed that he didn&#8217;t offer specific suggestions for how to improve your usage of analytics. Instead he stayed in the land of platitudes with suggestions like &#8220;Reach out and touch a stake holder&#8221; That said, web analytics helps to answer questions that are business specific, so coming up with general advice is clearly a difficult task.</p>
<p>To be fair, I think that I am a bit more technical that the target audience of the talk, so maybe others did benefit.</p>
<p>In any case, the meeting had a good crowd and was well organized and the sponsors paid for free beer which was cool. Thanks to the organizers.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[SandwichBoard Launch]]></title>
    <link href="http://pragmati.st/2008/03/19/sandwichboard-launch/"/>
    <updated>2008-03-19T00:00:00-04:00</updated>
    <id>http://pragmati.st/2008/03/19/sandwichboard-launch</id>
    <content type="html"><![CDATA[<p><img src="http://pragmati.st/assets/2008/3/14/SandwichBoardD15aR05aP01ZL.jpg" alt="SandwichBoard Logo"/></p>
<p>In September I left Lockheed Martin to start a company with my very talented colleague <a href="http://ianlotinsky.wordpress.com">Ian Lotinsky</a>. Today is a very proud day for us, as after several months of private beta we have just publicly launched <a href="http://www.sandwichboard.com">SandwichBoard</a>.</p>
<h2>What is SandwichBoard?</h2>
<p>SandwichBoard is the best way to create and maintain a restaurant&#8217;s website. We&#8217;ve worked really hard to make managing a restaurant&#8217;s website with SandwichBoard as easy as writing an email, updating a Facebook profile, or writing a blog entry. We let restaurant owners and managers update their menus, events, locations, and news from a web browser without having to learn anything about <span class="caps">HTML</span> or web design.</p>
<p>The best way to describe SandwichBoard is to show it in action, so please go check out our <a href="http://www.sandwichboard.com">introductory video</a>.</p>
<h2>Why Restaurants?</h2>
<p>I started working in restaurants when I was still in high school and paid my way through college as a busboy, waiter, bartender, and manager. I <em><strong>love</strong></em> restaurants. And I saw how painful it is for most restaurants to manage their web sites.</p>
<p>Every restaurant needs a web site, but getting a good one is currently an expensive and time consuming proposition. First, you have to hire a graphic designer, then you have to find, set-up, and pay for web hosting. Most of the time this involves signing a multi-year contract. One restaurant I know just spent upwards of $20,000 on a site redesign.</p>
<p>And after all that you can&#8217;t easily update your site. Every time you change your menu or want to make a change to a page you have to call up the designer and pay them more to make the change. This leads to restaurant web sites being out of date. And the only thing worse than not having a web site is having customers show up to find out that you now close an hour earlier than your 2 year old web site says.</p>
<p>SandwichBoard solves this problem. When a restaurant signs up for SandwichBoard they can start building their site immediately. In minutes they can create a basic site, and in about an hour they can create about a complete site. We give them a choice of several pre-built themes. They can use the theme as is, customize the theme themselves, or higher a designer to build them a custom theme. Once the theme is set up they can easily manage their entire site without the need to involve (and pay) the designer.</p>
<p>We&#8217;re so confident that restaurants are going to love SandwichBoard that we let them try it free for a month. We also don&#8217;t lock them into a long term contract, so they can cancel at any time.</p>
<h2>Please Help Us&#8230;</h2>
<p>Making it to launch is a big accomplishment, and is cause for celebration (And believe me, I will be celebrating tonight)</p>
<p>But now comes the truly important part: getting customers. So please help us spread the word. If you know people in the restaurant business please let us know. If you&#8217;re going out to eat please check and see if they have a web site. If they don&#8217;t, let us know. If they do and it&#8217;s bad, let us know.</p>
<p>If you know graphic designers who are interested in some work let us know. We would love to refer restaurants to them. We manage all the hosting and software, so designers can focus on design. We&#8217;re not looking to make money off the designers, they keep whatever fee they negotiate with the restaurants, we just want to get good designers building beautiful web sites on SandwichBoard.</p>
<h2>Thank You</h2>
<p>Thanks to everyone who has put up with me for the last several months while we built this application. I flaked on plans, was generally a bad friend, and for that I&#8217;m sorry. For those of you I&#8217;ve been bad about keeping up with please know that you are in my thoughts and I hope to catch up with you soon.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Why the Obama "Brand" Is Working]]></title>
    <link href="http://pragmati.st/2008/03/04/why-the-obama-brand-is-working/"/>
    <updated>2008-03-04T00:00:00-05:00</updated>
    <id>http://pragmati.st/2008/03/04/why-the-obama-brand-is-working</id>
    <content type="html"><![CDATA[<p><a href="http://www.blog.newsweek.com/blogs/stumper/archive/2008/02/27/how-obama-s-branding-is-working-on-you.aspx">Interesting interview</a> with graphic designer Michael Bierut about the overall excellence and startling consistency of Obama&#8217;s visual branding.</p>
<blockquote>The thing that sort of flabbergasts me as a professional graphic designer is that, somewhere along the way, they decided that all their graphics would basically be done in the same typeface, which is this typeface called Gotham. If you look at one of his rallies, every single non-handmade sign is in that font. Every single one of them. And they&#8217;re all perfectly spaced and perfectly arranged. Trust me. I&#8217;ve done graphics for events &#8212;and I know what it takes to have rally after rally without someone saying, &#8220;Oh, we ran out of signs, let&#8217;s do a batch in Arial.&#8221; It just doesn&#8217;t seem to happen. There&#8217;s an absolute level of control that I have trouble achieving with my corporate clients.<br />
<br />
Then if you go to the Web site, it&#8217;s all reflected there too&#8212;all the same elements showing up in this clean, smooth, elegant way. It all ties together really, really beautifully as a system. </blockquote>
<p>(via NotCot)</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Expectations]]></title>
    <link href="http://pragmati.st/2008/02/07/expectations/"/>
    <updated>2008-02-07T00:00:00-05:00</updated>
    <id>http://pragmati.st/2008/02/07/expectations</id>
    <content type="html"><![CDATA[<p><a href="http://ianlotinsky.wordpress.com">Ian</a> and I are currently working on adding support for <a href="http://www.authorize.net/solutions/merchantsolutions/merchantservices/cim/">Authorize.Net <span class="caps">CIM</span></a> to <a href="http://www.activemerchant.org/">ActiveMerchant</a>. Things were going pretty well until we made a mistake and basically locked our test account.</p>
<p><span class="caps">CIM</span> is a service that lets you store your customer&#8217;s credit card information on Authorize.Net&#8217;s secure servers. You provide a customer&#8217;s payment information, and they give you back a unique identifier for the customer. Then when you want to charge a customer or update their information you simply provide that unique identifier. The problem is, there is no way to lookup that identifier, and you can&#8217;t create duplicate profiles, so if you lose it you&#8217;re screwed. This shouldn&#8217;t be a big issue when running in production as we&#8217;ll take great care to store the ID in a database and to keep the database backed up, but it bit us in test. We broke one of our remote tests, didn&#8217;t delete the customer profile, and lost the customer profile ID. So now we can&#8217;t run any of our remote tests unless we change all of our test data (which we obviously don&#8217;t want to do)</p>
<p>And now for the point of this story. So Ian called their support line to see if they could reset our test account. The automated recording said that wait time was about 30 minutes, but if we left our number they would call us when a representative was available. Ian entered his number, and they told him to expect a call in approximately 52 minutes. We actually remarked on how good their customer service was because they were using virtual hold. I&#8217;ve ranted before about how <a href="http://pragmati.st/2007/3/18/outages-are-an-opportunity-to-show-character">making people wait on hold is disrespectful of their time before</a> Unfortunately, they didn&#8217;t call in 52 minutes, in fact the never called us back. We weren&#8217;t outside of normal business hours; we called at 1:00 on a Tuesday.</p>
<p>Ian called again today at noon, was told to expect a call back in 58 minutes, and as of 3:15pm still hasn&#8217;t received a call back.</p>
<p>Providing mediocre service is bad. But to raise customer expectations and then fail to meet them is far worse. I&#8217;d have rather just waited on hold. Seth Godin wrote a <a href="http://sethgodin.typepad.com/seths_blog/2007/02/setting_expecta.html">good post</a> about this last year that really hit the nail on the head.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Azureus Error: Malformed RSS XML: The reference to entity "xxx" must end with the ';' delimiter.]]></title>
    <link href="http://pragmati.st/2008/01/24/azureus-error-malformed-rss-xml-the-reference-to-entity-xxx-must-end-with-the-delimiter/"/>
    <updated>2008-01-24T00:00:00-05:00</updated>
    <id>http://pragmati.st/2008/01/24/azureus-error-malformed-rss-xml-the-reference-to-entity-xxx-must-end-with-the-delimiter</id>
    <content type="html"><![CDATA[<p>I have <a href="http://azureus.sourceforge.net/">Azureus</a> set up with the <a href="http://azureus.sourceforge.net/plugin_details.php?plugin=rssfeed">RSSFeed Scanner</a> plugin to check a few <a href="http://www.mininova.org/">Mininova</a> torrent feeds for a few shows. I recently started getting the error:</p>
<p><code>Malformed RSS XML: The reference to entity "num" must end with the ';' delimiter.</code></p>
<p>The problem was that I neglected to encode an ampersand in the feed url. For instance, the feed <span class="caps">URL</span></p>
<p><code>http://www.mininova.org/rss.xml?cat=8&amp;num=50</code></p>
<p>will cause an error. Instead it should read as the following:</p>
<p><code>http://www.mininova.org/rss.xml?cat=8&amp;amp;num=50</code></p>
<p>This is what the feed options should look like:</p>
<p><img src="http://img.skitch.com/20080124-1nhaiammi1y8xdu8hutb3397cw.png" alt="Azureus"/></p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[User Experience at the Doctor's Office]]></title>
    <link href="http://pragmati.st/2008/01/23/user-experience-at-the-doctor-s-office/"/>
    <updated>2008-01-23T00:00:00-05:00</updated>
    <id>http://pragmati.st/2008/01/23/user-experience-at-the-doctor-s-office</id>
    <content type="html"><![CDATA[<p>Last week, I went to the doctor for a checkup for the first time since I was in High School. I could not believe how bad the user experience was. I&#8217;d like to be clear that I&#8217;m not blaming this particular doctor, as I have had pretty much the same experience at every doctor I have ever visited. I think the problems are endemic to the health care industry as a whole.</p>
<h3>Making an Appointment</h3>
<p>I called the doctor&#8217;s office at 3PM on a Thursday. They were closed (they only have morning hours on Thursday) so I had to call back on Friday. When I called back, the receptionist took my name, address, phone number, and email address and we scheduled an appointment.</p>
<p><strong>Criticism:</strong> Not being able to make an appointment during business hours is pretty bad. Even banks stay open until 7pm now.</p>
<p><strong>What I Want:</strong> I would like to be able to make appointments online at any time. I think you should be able to schedule appointments by phone hours at least until 7pm and preferably later. At the very minimum, I should be able to call and schedule an appointment from 9am-5pm Monday-Friday.</p>
<h3>Office Design</h3>
<p>This is a minor gripe, but going to the doctor is a stressful experience. I&#8217;ve always thought that a little bit of interior design work would go a long way to ease that stress. Kathy Sierra described it best when talking about her dentist&#8217;s office in <a href="http://headrush.typepad.com/creating_passionate_users/2006/week41/index.html">Reducing Fear is the Killer App</a>. Suffice it to say that this office (and every other doctor I&#8217;ve ever gone to) looked pretty much exactly like the <a href="http://headrush.typepad.com/photos/uncategorized/dentistoffice.jpg">black and white picture</a> in Kathy&#8217;s article: receptionist behind a medical window, ugly chairs, sterile smell.</p>
<p><strong>Criticism:</strong> The office was functional but it didn&#8217;t do anything to put me at ease or improve my experience and actually increased my stress.</p>
<p><strong>What I Want:</strong> A desk for the receptionist instead of a glass window. Furniture that appears to have been designed in the two decades. Tasteful wall decorations instead of posters saying &#8220;Africa is fun. Typhoid fever is not.&#8221; Maybe a television showing sports or news (without volume) Preferably some option for beverages (coffee, tea, water, etc.)</p>
<h3>Filling out Patient History</h3>
<p>When I came in for my appointment they handed me a clipboard with several forms to fill out. The forms were an Insurance Form, a Medical History, and a Privacy Notice. On each of these three forms I had to fill out my name, address, phone number, and social security number. All in all filling out the forms took about 15 minutes.</p>
<p><strong>Criticism:</strong> This was terrible. There is no reason I should have to fill out the same information on multiple forms.</p>
<p><strong>What I Want:</strong> When I made my appointment they took my name, address, phone number, and email address. I would like to receive an email confirming the appointment, along with an iCal event so I can add the appointment to my calendar. Furthermore, I would like the email to include a link to electronic versions of the forms that I could complete at my convenience before my appointment (with the information the receptionist already took pre-filled)</p>
<p>When I got to the office they should have the completed forms waiting for my signature. If I did not fill the forms out in advance they should have copies of the forms pre-filled with the information they took over the phone.</p>
<h3>How Things Got This Way</h3>
<p>I think that the user experience at doctor&#8217;s offices is so bad because of the way that doctors in the United States get paid. Most doctors are paid primarily by insurance companies, not the patients themselves. Since prices are fixed by the insurance companies the doctors don&#8217;t have much incentive to providing a better experience. This isn&#8217;t to say that insurance is a bad thing, but rather that the health industry is a prime example of the mediocre product you get when the person who consumes a service isn&#8217;t the person who pays for the service. Enterprise software is another example of a terrible user experience that is the result of the users not being the ones who actually purchase the product.</p>
<p>Furthermore, since the cost of switching doctors is so high (in time, inconvenience, and stress) and the services provided are so similar doctors do not have to worry much about patients leaving.</p>
<p>Standard, open formats for electronic medical records could provide some hope by lowering the cost of switching doctors. Unfortunately, I don&#8217;t think we&#8217;ll see them any time soon.</p>
<h3>Interesting Ideas</h3>
<p><a href="http://www.jayparkinsonmd.com/index.html">This doctor in Brooklyn</a> seems to be trying some interesting things. He doesn&#8217;t have an office, makes house calls, and is available by cell phone, IM, email, and video chat. I think his model may be a bit extreme, but it does sound like it would serve healthy young people better than the existing setup.</p>
<p>The <a href="http://emr.liferecord.com/">Electronic Medical Record System</a> that he uses looks interesting, but doesn&#8217;t seem to have much focus on the patient themselves.</p>
<p>The truth is I don&#8217;t need much health care, but it would be extremely valuable to have someone to call when I have questions, or steer me in the direction of more affordable services when I do need care. (Instead of going to an emergency room to receive $20 a pill ibuprofen like I did when I dislocated my finger last year.)</p>
<h3>The Future</h3>
<p>I am hopeful for the future. My generation is the first to grow up with computers and the internet and my peers are just now finishing medical school. As a more tech savvy generation of doctors moves into private practice I may get to see some of the things I want actually implemented.</p>
<p>In the meantime, if anyone knows of a doctor in the DC area who seems genuinely concerned with the experience of their patients please let me know.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[alias versus alias_method]]></title>
    <link href="http://pragmati.st/2008/01/22/alias-versus-alias_method/"/>
    <updated>2008-01-22T00:00:00-05:00</updated>
    <id>http://pragmati.st/2008/01/22/alias-versus-alias_method</id>
    <content type="html"><![CDATA[<p>Last week Ian and I were running into a problem with <code>alias_method</code>. It turned out that we were passing the method name to alias method as you would to alias, instead of passing a string or a symbol of the method name. Here is the correct usage of alias and alias method</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="k">alias</span> <span class="n">new_method_name</span> <span class="n">old_method_name</span>
</span><span class='line'>  <span class="n">alias_method</span> <span class="ss">:new_method_name</span><span class="p">,</span> <span class="ss">:old_method_name</span>
</span><span class='line'>  <span class="n">alias_method</span> <span class="s1">&#39;new_method_name&#39;</span><span class="p">,</span> <span class="s1">&#39;old_method_name&#39;</span>
</span></code></pre></td></tr></table></div></figure></div></notextile></p>
<p>Here is the <a href="http://emmanueloga.wordpress.com/2007/11/01/alias-versus-alias_method/">blog post</a> that pointed out our error. It is in Spanish, so for the first time ever all that time I spent learning Spanish helped me as a programmer ;).</p>
<p>For the benefit of English speakers I decided to translate the blog post. Here is the translated text:</p>
<p>alias and alias_method do the same thing: copy a method and assign it a different name.</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="k">class</span> <span class="nc">Test</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">test</span>
</span><span class='line'>      <span class="nb">puts</span> <span class="s2">&quot;hello&quot;</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>    <span class="k">alias</span> <span class="n">test_copy</span> <span class="nb">test</span>
</span><span class='line'>    <span class="n">alias_method</span> <span class="ss">:test_copy2</span><span class="p">,</span> <span class="ss">:test</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="no">Test</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">test</span>        <span class="c1"># &gt; &quot;hello&quot;</span>
</span><span class='line'>  <span class="no">Test</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">test_copy</span>   <span class="c1"># &gt; &quot;hello&quot;</span>
</span><span class='line'>  <span class="no">Test</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">test_copy2</span>  <span class="c1"># &gt; &quot;hello&quot;</span>
</span></code></pre></td></tr></table></div></figure></div></notextile></p>
<p>That piqued my curiosity to know the difference between alias and alias_method. It turns out that they are the same, except that:</p>
<ol>
	<li>alias is a reserved keyword in Ruby</li>
	<li>alias takes the method identifiers as parameters, without the need to use symbols or strings (for example in &#8220;def method_name&#8221;, method_name is an identifier and not a string or a symbol) This behavior can be pretty confusing when you&#8217;re starting out.</li>
	<li>alias_method is a method of the class Module</li>
	<li>alias_method takes its parameters separated by comma, just like any other method.</li>
</ol>
<p>The consequences are simple:</p>
<ul>
	<li>alias_method can be redefined, and alias can&#8217;t.</li>
	<li>alias can be used incorrectly (outside the context of method definitions)</li>
</ul>
<p>By being a method of Module, alias_method makes it easier to use it correctly: in the context of method definition of a class or module.</p>
<p>Conclusion: In the majority of cases, alias_method is what you need.</p>]]></content>
  </entry>
  
</feed>

