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

  <title><![CDATA[The Code Whisperer]]></title>
  <link href="http://blog.thecodewhisperer.com/atom.xml" rel="self"/>
  <link href="http://blog.thecodewhisperer.com/"/>
  <updated>2013-04-14T15:00:21+00:00</updated>
  <id>http://blog.thecodewhisperer.com/</id>
  <author>
    <name><![CDATA[J. B. Rainsberger]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Primitive Obsession Obsession]]></title>
    <link href="http://blog.thecodewhisperer.com/2013/03/04/primitive-obsession-obsession/"/>
    <updated>2013-03-04T12:18:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2013/03/04/primitive-obsession-obsession</id>
    <content type="html"><![CDATA[<p>A Twitter conversation about Primitive Obsession caught my eye today. That conversation began with this tweet:</p>

<blockquote class="twitter-tweet"><p>Re. &#8220;primitive obsession,&#8221; I say this poker-scoring program wouldn&#8217;t be bettered avoiding integers for rank and suit. <a href="http://t.co/qfc3Kyc9SD" title="http://www.jsoftware.com/jwiki/TracyHarms/PokerHandsScoring">jsoftware.com/jwiki/TracyHar…</a></p>&mdash; Tracy Harms (@kaleidic) <a href="https://twitter.com/kaleidic/status/308298155869499393">March 3, 2013</a></blockquote>
<script async="" src="http://blog.thecodewhisperer.com//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>I can’t read J, so I can’t decide much about the quality of the code Tracy wrote, but I do notice one thing:</p>

<blockquote>
  <p>There aren’t many functions that operate on the primitive data (card rank, card suit, hand classification), they’re close by each other, and they’re all quite short.</p>
</blockquote>

<p>Regarding this one example, then, Primitive Obsession doesn’t pose much of a problem yet. Using primitives to represent values with special constraints can lead to low cohesion and high duplication. The low cohesion consists of scattering related ideas throughout the code base, where programmers have a hard time finding them. Such scattering can lead to duplicating special processing logic, and worse, duplicating it inaccurately. That leads to mistakes. This makes me ask a question:</p>

<blockquote>
  <p>When does Primitive Obsession not smell?</p>
</blockquote>

<p>I suppose it doesn’t smell when we use other means to keep cohesion high and duplication low. We can use primitives safely when we keep the special processing logic for those primitive values close together and use willpower (effectively) to avoid duplicating it.</p>

<p>I still can’t account for Tracy’s observation that Primitive Obsession doesn’t figure prominently in array programming, where it ought to run rampant and create serious problems. Some guesses:</p>

<ul>
  <li>Teams of programmers working in these languages don’t create large, low-cohesion systems, like they do in Java/C#/C++.</li>
  <li>Teams of programmers working in these languages name things better in general, and so create fewer opportunities for misunderstanding.</li>
  <li>Teams of programmers working in these languages work together more closely in general, and so smooth over their misunderstandings more easily and more promptly.</li>
</ul>

<p>Any ideas?</p>

<h3 id="references">References</h3>

<p>Martin Fowler, <a href="http://link.jbrains.ca/Z2isb3">Refactoring: Improving the Design of Existing Code</a>. This book introduced me to Primitive Obsession as a code smell.</p>

<p>Ward Cunningham, <a href="http://link.jbrains.ca/UJl7q0">“The CHECKS Pattern Language of Information Integrity”</a>. This article includes a section on Whole Value, which counters the effects of Primitive Obsession. Whole Values should become <em>attractive code</em> when you introduce them into a system.</p>

<p>James Shore, <a href="http://link.jbrains.ca/15tt4S8">“Primitive Obsession”</a>. I recommend this article to my students to learn more about Primitive Obsession.</p>

<p>Corey Haines and J. B. Rainsberger, <a href="http://link.jbrains.ca/12F96Ug">“Primitive Obsession”</a>. Corey and I discussed Primitive Obsession while in Bucharest in early 2010. This article includes a 14-minute video of the two of us chatting about the topic.</p>

<p><a href="http://www.coderetreat.org">Code Retreat</a>. We very commonly use the “no primitives” constraint at Code Retreat to encourage programmers to practise introducing Whole Values very early. I don’t <em>always</em> design this way, but I believe that programmers should understand more deeply the differences between design with and without promitives, so I encourage them to practise.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Modularity. Details. Pick One.]]></title>
    <link href="http://blog.thecodewhisperer.com/2013/01/31/modularity-details-pick-one/"/>
    <updated>2013-01-31T14:50:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2013/01/31/modularity-details-pick-one</id>
    <content type="html"><![CDATA[<p>The bottom line:</p>

<blockquote>
  <p>Modularity. Details. Pick <strong>one</strong>.</p>
</blockquote>

<p>I routinely work with programmers who feel uncomfortable with tiny methods and tiny classes, in spite of all the benefits of tiny methods and tiny classes:</p>

<ul>
  <li>easier to test</li>
  <li>easier to read</li>
  <li>easier to understand</li>
  <li>easier to build correctly</li>
  <li>easier to compose into working systems</li>
</ul>

<p>The programmers who don’t like them cite these problems most often:</p>

<ul>
  <li>“I can’t find stuff!”</li>
  <li>“I have to click too much to see what’s happening!” </li>
</ul>

<p><a href="http://link.jbrains.ca/WCa40C">This article by Kevin Rutherford</a> reminded me of this issue. While Kevin extols the virtues of tiny methods, he doesn’t address this phenomenon, although he admits to running into it himself. I wanted to share what I do with him, but it doesn’t fit well into a comment. When I hear programmers complain about these things, I offer the following two responses to them.</p>

<h2 id="you-appear-to-be-navigating-would-you-like-help-with-that">You appear to be navigating. Would you like help with that?</h2>

<p>I have paired, albeit mostly briefly, with hundreds of programmers by now. Most of them, to my surprise, <em>navigate</em> their code bases to find things. By this, I mean that they open up folders in a navigator view in their IDE, or navigate the file system, in order to locate a file containing the code that they want to read or change. <a href="http://link.jbrains.ca/WDuMdZ">Not wanting to make pair programming suck</a>, I hold my tongue until I’ve built up more trust with the person. If I think they trust me, then I stop them and suggest:</p>

<blockquote>
  <p>Don’t navigate when you can search.</p>
</blockquote>

<p>I just don’t care <em>where</em> to find things any more. Just knowing that “they’re somewhere in this room”<sup id="fnref:summer-school"><a href="#fn:summer-school" rel="footnote">1</a></sup> suffices. Only when searching fails do I resort to navigating.</p>

<p>The classic book <a href="http://link.jbrains.ca/WNg8Se">The Pragmatic Programmer</a> teaches us to learn one editor well, which I try to do. As part of classroom training and mentoring hundreds of programmers, I find myself working in unfamiliar environments quite often. When I work in a new one, I spend some time learning how to search for things. In Eclipse, I use “Open Type” and “Open Resource” extensively. Before I knew anything useful about <code>vim</code>, I knew to press <code>/</code> to find text in a file. Before I knew anything useful about Unix, I could clumsily use <code>grep</code>, and more recently I’ve learned about <code>ack</code> and even <code>ag</code>. I don’t use Emacs any more, but I love its incremental search feature. I see this as an extension of the maxim that humans ought to delegate mechanical tasks to the computer, such as searching text for a pattern.</p>

<p>I <em>still</em> see programmers <em>scan web pages with their eyes to find text</em>, rather than use the “search” feature of their browser. I just don’t understand why they do this. I prefer to work in environments <em>where I don’t even know that it stores my code in <strong>files</strong></em>!<sup id="fnref:vajava"><a href="#fn:vajava" rel="footnote">2</a></sup> </p>

<p>This brings me to my other response.</p>

<h2 id="modularity-details-pick-one">Modularity. Details. Pick One.</h2>

<p>If you ask programmers whether they want modularity, they usually claim that they do. It sounds like something they ought to want, books on design tell them to want it, and so I imagine that some programmers claim to want it in order to look good among their peers. Unfortunately, many such programmers don’t appear to understand that modularity comes from abstraction, and that abstraction literally means hiding details, and that doesn’t mesh with their clinging to details. To them, I suggest repeating a little mantra all day today:</p>

<blockquote>
  <p>I don’t care. I don’t need to know. <strong>I don’t want to know.</strong></p>
</blockquote>

<p>Giving up details won’t lead you directly to writing modular code, but clinging to details will keep you from it. The more your code knows about its neighbors, the less you can change or replace those neighbors. Changes ripple out to the rest of the system. When you do this, you’re writing more legacy code.</p>

<blockquote>
  <p>Modularity needs abstraction. Abstraction means hiding details. If you cling to details, then you won’t create abstractions, and you won’t achieve modularity. <strong>Modularity begins with your refusal to let others burden you with unnecessary detail.</strong></p>
</blockquote>

<p>I noticed that my designs improved once I began stubbornly refusing to know any more than I needed to achieve my current goal. Try starting there. “I don’t care. I don’t need to know. <strong>I don’t want to know</strong>.”</p>

<p>Look at the SOLID principles and how they relate to not wanting to know details.</p>

<ul>
  <li>Single Responsibility: I don’t want to know about any other behavior in this system right now.</li>
  <li>Open/Closed: I don’t want to know how things work in order to extend them.</li>
  <li>Liskov Substitution: I don’t want to know which implementation of each interface this code uses.</li>
  <li>Interface Segregation: I don’t want to know anything more than the minimum I need to do my job.</li>
  <li>Dependency Inversion: I don’t want to know how the rest of the system uses me.</li>
</ul>

<p>I don’t think I can make it any plainer than that.</p>

<p>Of course, I’ve assumed in this article that we <em>want</em> modular systems. You might not. I don’t want to argue the merits of modularity here. Instead, I want to make one thing clear:</p>

<blockquote>
  <p><strong>Modularity and obsession with details exclude one another. If you want one, then you can’t have the other, so pick one.</strong></p>
</blockquote>

<div class="footnotes">
  <ol>
    <li id="fn:summer-school">
      <p>Find and watch <a href="http://www.imdb.com/title/tt0094072">this film</a>. Don’t be put off by the inclusion of Kirstie Alley.<a href="#fnref:summer-school" rel="reference">&#8617;</a></p>
    </li>
    <li id="fn:vajava">
      <p>I would really have loved Visual Age for Java if it didn’t corrupt the workspace so frequently.<a href="#fnref:vajava" rel="reference">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Demystifying the Dependency Inversion Principle]]></title>
    <link href="http://blog.thecodewhisperer.com/2013/01/29/consequences-of-dependency-inversion-principle/"/>
    <updated>2013-01-29T16:55:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2013/01/29/consequences-of-dependency-inversion-principle</id>
    <content type="html"><![CDATA[<p>Another “demystifying” article. Great! I know… bear with me.</p>

<p>Of the SOLID principles, the Dependency Inversion Principle remains somewhat misunderstood. I’d like to help with that. I hope you’ll ask questions and challenge these ideas, so that I can improve this little article.</p>

<p>I learned the Dependency Inversion Principle from <a href="http://link.jbrains.ca/11bh6NX">Bob Martin’s article</a>, the salient part of which states:</p>

<blockquote>
  <p>High level modules should not depend upon low level modules. Both should depend upon abstractions.</p>
</blockquote>

<p>or</p>

<blockquote>
  <p>Abstractions should not depend upon details. Details should depend upon abstractions.</p>
</blockquote>

<p>I’ve noticed that I spend the vast majority of my time introducing abstractions and inverting dependencies (abstractions that use concrete things) when rescuing legacy code or adding behavior to legacy systems. Sometimes I feel like I don’t know any other useful trick than <em>invert this dependency</em>. One could make a drinking game out of it.</p>

<p>Even so, not enough people understand and apply DIP. Perhaps if I share a few examples or equivalent formulations, they will.</p>

<h2 id="move-specificity-towards-the-tests">Move Specificity Towards the Tests</h2>

<p>Moving details from production code towards tests clarifies the tests. In particular, I find it easier to relate the inputs to the expected outputs. It eliminates duplication between tests and production code. It highlights opportunities for abstraction and reuse. Corey Haines interviewed me about this in summer 2009.</p>

<iframe src="http://player.vimeo.com/video/5895145" width="500" height="375" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
<p><a href="http://vimeo.com/5895145">JB Rainsberger - Move Specificity Towards the Tests</a> from <a href="http://vimeo.com/coreyhaines">Corey Haines</a> on <a href="http://vimeo.com">Vimeo</a>.</p>

<p>(If you can’t watch the embedded video, then <a href="http://link.jbrains.ca/119weXi">click here</a>.)</p>

<h2 id="move-implementation-choices-up-the-call-stack">Move Implementation Choices Up the Call Stack</h2>

<p>Dependency injection confuses and annoys people, partly because some people miss the point. Injecting a dependency makes testing easier, by letting us substitute implementations in our tests that make those tests easier to write and understand. Don’t stop there. When in doubt, push <code>new</code> up the call stack. In particular, don’t instantiate a <em>service</em> if you can get your caller to do that. Keep pushing, even more than you think you should. Let all the choices of implementation of each service interface bubble up the call stack until they collect in your application’s or component’s entry point. This shines a huge floodlight on otherwise obscure duplication. It also paves the way for <em>sane</em> use of a dependency injection container, even though you don’t need a container to inject dependencies well. This movement of <code>new</code> up the call stack leaves in its wake a loosely-coupled network of abstractions talking to each other over well-defined interfaces with well-understood contracts. Using this technique helps me remove duplication, which decreases errors, particularly of the “I forgot to change that one” type. Using this technique also encourages me to write code that depends on narrower interfaces, which slowly become more generic interfaces, which makes the code depend less on its context and more suitable to use in other contexts.</p>

<h2 id="abstraction-in-code-details-in-metadata">Abstraction in Code; Details in Metadata</h2>

<p>I first learned this principle from the book <a href="http://link.jbrains.ca/WNg8Se">The Pragmatic Programmer</a>. You’ll find it as “tip 38”. I encourage you to buy the book and the read the tip yourself. The authors state among the benefits:</p>

<ul>
  <li>a more robust program</li>
  <li>a more flexible program</li>
  <li>opportunity to reuse the “engine” with different metadata</li>
  <li>opportunity to express metadata in the language of the domain</li>
  <li>opportunity to customise code without rebuilding it</li>
</ul>

<p>Who could argue with all that?</p>

<h2 id="quick-summary">Quick Summary</h2>

<p>If you agree with the specific principles I’ve cited here, then you also agree with the Dependency Inversion Principle. Said differently:</p>

<blockquote>
  <p><strong>Push details up towards the client and push generic patterns down towards the server.</strong></p>
</blockquote>

<p>This principle, applied everywhere, makes testing easier, promotes reuse, both of which reduce the incidence of errors and the cost of development.</p>

<p>So tell me:</p>

<ul>
  <li>If you already felt you understood the DIP well, how faithfully did I represent it here?</li>
  <li>If you didn’t quite understand the DIP well before, how much has this article helped or hindered your understanding?</li>
  <li>If you explain the DIP to others, how do you do it?</li>
  <li>If you still think the DIP is a load of nonsense, how do you justify that? I’d like the chance to help you as well as fix holes in my own understanding and reasoning.</li>
</ul>

<h2 id="one-more-thing">One More Thing</h2>

<p>If you hate Spring’s dependency injection container, then I know why: you have code that <em>depends</em> on the container.</p>

<p>Don’t do that.</p>

<p>Dependency injection is related to the Inversion of Control principle, also known as the Hollywood Principle:</p>

<blockquote>
  <p>Don’t call us; we’ll call you.</p>
</blockquote>

<p>Spring’s dependency injection container calls you; you never call it. Never.</p>

<p>Fine: you call it only from a smoke test that verifies that you’ve wired up your dependencies correctly, but you <strong>never call your dependency injection container from production code</strong>.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Liskov Substitution Principle Demystified]]></title>
    <link href="http://blog.thecodewhisperer.com/2013/01/08/liskov-substitution-principle-demystified/"/>
    <updated>2013-01-08T14:03:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2013/01/08/liskov-substitution-principle-demystified</id>
    <content type="html"><![CDATA[<p>I apologise for the pompous title; I wrote it just for fun. If this “demystifies” anything, I’ll consider that a coincidence.</p>

<p>Of the SOLID principles, the most pompous-sounding is the one named for a person: Barbara Liskov. I don’t label her pompous – I never knew her – but of those five principles, only LSP has a common formulation that looks like the kind of mathematics so many programmers like to avoid, while others flock to.</p>

<blockquote>
  <p>Let <em>q(x)</em> be a property provable about objects <em>x</em> of type <em>T</em>. Then <em>q(y)</em> should be provable for objects <em>y</em> of type <em>S</em> where <em>S</em> is a subtype of <em>T</em>.</p>
</blockquote>

<p>Or, if you prefer:</p>

<blockquote>
  <p>Subtypes must not change any supertype’s significant behavior. Here, “significant behavior” means behavior upon which clients of those objects expressly depend.</p>
</blockquote>

<p>If you like the language of contracts, then you might prefer this formulation:</p>

<blockquote>
  <p>Subtypes must respect the contracts of their supertypes.</p>
</blockquote>

<p>If, like me, you like to check contract compliance with <a href="http://link.jbrains.ca/13e1S9Y">contract tests</a>, then you might prefer <em>this</em> formulation:</p>

<blockquote>
  <p>Subtypes must pass the same set of contract tests that their supertypes pass.</p>
</blockquote>

<p>Remember that <em>subtype</em> here means any implementation of an interface or subclass of a class.</p>

<p>So, what does it look like when we violate the Liskov Substitution Principle? Usually like this:</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>
</pre></td><td class="code"><pre><code class=""><span class="line">// This should never happen</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>You can’t trace <em>all</em> such problems to a violation of LSP. Sometimes you have a simpler disagreement between a client and its collaborator. Even so, subtyping without careful attention to the type’s contract opens the door wide to breaking the contract, which creates disagreement between a client and a collaborator whose type <em>we sometimes only know at runtime</em>. You’ve experienced this if you’ve ever ended a 2-hour-long debugging session by yelling “You idiot! How did you expect that <em>ever</em> to work?!” You’ve discovered a fundamental contract disagreement.</p>

<p>While the LSP doesn’t receive the same attention as the Single Responsibility Principle, breaking the LSP leads to painful, costly mistakes. Understanding LSP, clarifying and respecting contracts helps you avoid this frustration.</p>

<p>I hope this helps.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Inquisition By Contract]]></title>
    <link href="http://blog.thecodewhisperer.com/2013/01/03/inquisition-by-contract/"/>
    <updated>2013-01-03T14:47:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2013/01/03/inquisition-by-contract</id>
    <content type="html"><![CDATA[<p>Just a fun link today.</p>

<p>I read about Design by Contract first, didn’t understand it, then read about Test-Driven Development and began to think of TDD as a kind of DbC by example. Accordingly, I have respect for both practices and have even combined them on projects. Moreover, “<a href="http://blog.thecodewhisperer.com/blog/categories/integrated-tests-are-a-scam">Integrated Tests are a Scam</a>” amounts to little more than Isolating Layers by Contract.</p>

<p>When I saw <a href="http://link.jbrains.ca/Wnd5i1">the Vigil programming language</a> today, I fell in love. To quote its README:</p>

<blockquote>
  <p>When a Vigil program is executed, Vigil itself will monitor all oaths (implorations and swears) that have been made. If an oath is broken, the offending function (the caller in the case of implore and the callee in the case of swear) will be duly punished.</p>
</blockquote>

<p>I know for sure I’ll try Vigil at the next <a href="http://www.coderetreat.org">Code Retreat</a>.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Responsible Design for Android Nearing Completion]]></title>
    <link href="http://blog.thecodewhisperer.com/2013/01/02/responsible-design-android-nearing-completion/"/>
    <updated>2013-01-02T17:54:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2013/01/02/responsible-design-android-nearing-completion</id>
    <content type="html"><![CDATA[<iframe width="160" height="400" style="float: right; padding-left: 10px; padding-bottom: 10px" src="https://leanpub.com/ResponsibleDesignAndroid-Part1/embed" frameborder="0" allowtransparency="true"></iframe>

<p>A month ago I <a href="http://blog.thecodewhisperer.com/2012/12/03/announcing-a-new-book">announced a new book</a>. The book is now nearing completion.</p>

<p>In the past month I have published over 240 pages, filled with code, demonstrating how to test-drive the first feature of an Android app.</p>

<p>If you want to see how to bring the benefits of evolutionary design to Android, then this book is absolutely for you. In it, you’ll see example after example of designing with tests, refactoring, and running commentary on what goes in to making the design decisions I make. It’s my opportunity to show you how all the principles, practices, techniques and ideas I have about design work together.</p>

<ul>
  <li>Get out of the simulator as quickly as possible</li>
  <li>Integrated tests are still a scam!</li>
  <li>Move details down the call stack and abstractions up the call stack</li>
  <li>How fast tests lead to great design</li>
</ul>

<p>Android development <em>can</em> make Java programming fun again. In this book, I show you how I do it, so buy your copy today!</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Publish posts later with Jekyll/Octopress]]></title>
    <link href="http://blog.thecodewhisperer.com/2012/12/06/publish-posts-later-with-jekyll-slash-octopress/"/>
    <updated>2012-12-06T12:52:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2012/12/06/publish-posts-later-with-jekyll-slash-octopress</id>
    <content type="html"><![CDATA[<style type="text/css">
span.keep-together { white-space: nowrap; }
</style>

<p>I really like Octopress, which is built on Jekyll. You can read a lot of articles about the advantages and disadvantages of pre-baked blogs, so I won’t bore you with those details. Instead, I’ll bore you on the subject of the one feature I miss with pre-baked blogs: scheduling posts for later publication.</p>

<p>When I switched to a pre-baked blogging tool like Octopress, I gave up the ability to upload a post, but publish it later. Well, I didn’t really give it up entirely, but pre-baking my blog means thinking of my blog as a static web site, rather than a dynamic one, which implies having to re-deploy every time I wanted to change its content. This makes scheduling posts in the future a bit more tricky. </p>

<p>Using Heroku and its read-only file system make it even trickier, since I can’t regenerate the blog in production.</p>

<p>I just wanted to share my solution with you, in case it interests you.</p>

<p>First, I added to Octopress the ability to generate the blog without future-dated posts. This looked difficult, especially with Octopress’s existing “preview mode” feature, but I discovered that Jekyll supports omitting future-dated posts directly with <span class="keep-together"><code>jekyll --no-future</code></span>, so I augmented Octopress to use this feature. If you’d like to explore the details, <a href="http://link.jbrains.ca/11rxWGB">click here</a>.<sup id="fnref:pull-request"><a href="#fn:pull-request" rel="footnote">1</a></sup></p>

<p>Next, I needed a way to republish my Octopress site regularly in order to include new posts as their publication instant arrives. I asked my tweeps for ideas, and we agreed that we couldn’t get around having a machine Out There Somewhere that’s always on that would poll a <code>git</code> repository for changes, then regenerate and publish to Heroku. I settled on the following architecture.</p>

<p><img src="http://blog.thecodewhisperer.com/images/PublishLater-Octopress-Heroku/blog-architecture.png" alt="You can smell the Architecture!" /></p>

<p>I followed these basic steps:</p>

<ol>
  <li>Added an SSH public key from “Monitor/Staging” to “Production”, so that the former could <code>push</code> to the latter.</li>
  <li>Installed a script into “Monitor/Staging” to, well, monitor, stage, then <code>push</code>.</li>
  <li>Cloned my local <code>git</code> repository to “Integration” so that it will always be available to “Monitor/Staging”.</li>
</ol>

<p>Complicated, sure, but–and you’ll tell me if you disagree–just barely sufficiently complicated, and no worse. I can handle that.</p>

<p>My workflow hasn’t changed much. I compose posts, preview, and <code>push</code> to “Integration” when I finish. “Monitor/Staging” runs the following script every 10 minutes.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span> (deploy-blog.thecodewhisperer.com.sh)</span> <a href="http://blog.thecodewhisperer.com/_code//deploy-blog.thecodewhisperer.com.sh">download</a></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>
</pre></td><td class="code"><pre><code class="sh"><span class="line"><span class="c">#! /bin/bash</span>
</span><span class="line"><span class="nb">pushd</span> <span class="nv">$HOME</span>/Workspaces/blog.thecodewhisperer.com
</span><span class="line"><span class="c"># I have to do this by hand, apparently.</span>
</span><span class="line">. .rvmrc
</span><span class="line">
</span><span class="line"><span class="c"># I can&#39;t assume that I&#39;m on the right branch</span>
</span><span class="line">git checkout -q master
</span><span class="line">git pull -q origin master
</span><span class="line">git checkout -q publish
</span><span class="line">git merge -q master
</span><span class="line">
</span><span class="line"><span class="c"># Check the diff /before/ regenerating, to avoid spurious</span>
</span><span class="line"><span class="c"># timestamp differences</span>
</span><span class="line"><span class="nv">DIFF</span><span class="o">=</span><span class="s2">&quot;$(git diff --stat publish heroku/master)&quot;</span>
</span><span class="line"><span class="nv">NOW</span><span class="o">=</span><span class="sb">`</span>date<span class="sb">`</span>
</span><span class="line"><span class="k">if</span> <span class="o">[</span> -n <span class="s2">&quot;$DIFF&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class="line"><span class="k">  </span><span class="nb">echo</span> <span class="s2">&quot;Publishing $NOW...&quot;</span>
</span><span class="line">  bundle <span class="nb">exec </span>rake generate
</span><span class="line">  git add -A <span class="o">&amp;&amp;</span> git commit -m <span class="s2">&quot;Published $NOW&quot;</span> <span class="o">&amp;&amp;</span> git push heroku publish:master
</span><span class="line"><span class="k">else</span>
</span><span class="line"><span class="k">  </span><span class="nb">echo</span> <span class="s2">&quot;No need to publish at $NOW.&quot;</span>;
</span><span class="line"><span class="k">fi</span>
</span><span class="line"><span class="nb">popd</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>I write posts to the branch <code>master</code>, and “Monitor/Staging” merges them to the branch <code>publish</code>, then deploys them to “Production”’s branch <code>master</code>.</p>

<p>Of course, I will monitor this closely over the next few days, looking for anomalies. In particular, I worry a little about what happens when “Monitor/Staging” can’t merge <code>master</code> to <code>publish</code> automatically. I suppose in that case I’ll have something to worry about, and in the worst case, no changes will publish to production, which could cause annoyance, but sounds like safe default behavior.</p>

<p>If you see any problems with this setup, please don’t keep them to yourself!</p>

<div class="footnotes">
  <ol>
    <li id="fn:pull-request">
      <p>I’ve submitted a <a href="http://link.jbrains.ca/11Hde4E">pull request</a> for this, but I think Octopress’s maintainer has other, more important stuff to do these days.<a href="#fnref:pull-request" rel="reference">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Announcing a New Book]]></title>
    <link href="http://blog.thecodewhisperer.com/2012/12/03/announcing-a-new-book/"/>
    <updated>2012-12-03T14:03:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2012/12/03/announcing-a-new-book</id>
    <content type="html"><![CDATA[<p>I’m pleased to announce that I have started writing a new book, entitled <a href="http://link.jbrains.ca/SpIUHM"><em>Responsible Design for Android</em></a>. I really envision this as a <em>series of short books</em>, not wanting to repeat the 750-page behemoth that was <a href="http://link.jbrains.ca/TEDGGm">JUnit Recipes</a>. </p>

<p>In Part 1, <em>Dancing with the Android SDK</em>, I explore a sensible architecture for the basic Android app, emphasising <em>context independence</em> to avoid letting the Android framework swallow my app whole. I use tactics that have worked to great effect in working with older frameworks such as Servlets and EJB.</p>

<p>I toyed with the idea of writing an Android app in Ruby using Rhodes, but decided to return to my roots and Java, so if you’re writing Android apps in Java, and have run into maintenance or extensibility problems, then I’m writing this book for you.</p>

<p>I say “I’m writing”, because I’ve decided to use <a href="http://www.leanpub.com">LeanPub</a> to compose and publish the book. This means that you can read the book as I write it, and your feedback and questions could help direct its contents. As of this writing, I’ve published three versions of the book, and plan to publish a new version approximately twice per week until I’ve written enough.</p>

<p>The sooner you purchase the book, the less you pay, and once you purchase the book, you receive all future updates free of charge. I have already raised the minimum price of the book once, as I have published more content.</p>

<p>If you’d like to take a look, <a href="http://link.jbrains.ca/XfFImB">click here</a> to download a sample chapter, then <a href="http://link.jbrains.ca/SpIUHM">click here</a> to buy the book.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[A new twist on an old pattern]]></title>
    <link href="http://blog.thecodewhisperer.com/2012/11/19/a-new-twist-on-an-old-pattern/"/>
    <updated>2012-11-19T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2012/11/19/a-new-twist-on-an-old-pattern</id>
    <content type="html"><![CDATA[<p>I’m coding like it’s 2000, meaning in Java. I thought I’d never see anything new regarding writing a test that expects to catch a specific exception. I saw something new, and I wonder who else has independently discovered it.</p>

<div><script src="https://gist.github.com/4111662.js?file="></script>
<noscript><pre><code>@Test
public void ioFailure() throws Exception {
    final IOException ioFailure = new IOException(&quot;Simulating a failure writing to the file.&quot;);
    try {
        new WriteTextToFileActionImpl() {
            @Override
            protected FileWriter fileWriterOn(File path) throws IOException {
                return new FileWriter(path) {
                    @Override
                    public void write(String str, int off, int len) throws IOException {
                        throw ioFailure;
                    }
                };
            }
        }.writeTextToFile(&quot;::text::&quot;, new File(&quot;anyWritableFile.txt&quot;));
        fail(&quot;How did you survive the I/O failure?!&quot;);
    } catch (IOException success) {
        if (success != ioFailure)
            throw success;
    }
}
</code></pre></noscript></div>

<p>Please add your comments at <a href="https://gist.github.com/4111662#comments">gist.github.com</a>.</p>

<p>(If you can’t see the code snippet inline, then <a href="https://gist.github.com/4111662">click here</a>.)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[10 Ways to Kill Your Design]]></title>
    <link href="http://blog.thecodewhisperer.com/2012/02/19/ten-ways-to-kill-your-design/"/>
    <updated>2012-02-19T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2012/02/19/ten-ways-to-kill-your-design</id>
    <content type="html"><![CDATA[<p>I wish that I could take credit for this article, but I can’t. Instead, I have to credit two people: <a href="http://www.twitter.com/#!/lassekoskela">Lasse Koskela</a> and <a href="http://twitter.com/#!/mhevery">Miško Hevery</a>. I credit Lasse for writing the manuscript that led me to Miško’s article. Look for Lasse’s upcoming book <em>Unit Testing in Java</em> <a href="http://manning.com/koskela2/">at Manning Publications’ site</a>. Let me summarise Miško’s article here, then you can read the details at <a href="http://misko.hevery.com/2008/07/30/top-10-things-which-make-your-code-hard-to-test/">his blog</a>.</p>

<p>Why would I simply summarise someone else’s article on this site? Isn’t that dishonest? Not in this case: Miško wrote essentially the same thing that I say over and over again in my own articles and in my training classes. I consider it unfortunate that he and I have never met nor worked together. We really should. You should read his stuff.</p>

<p>So… 10 ways to kill your design.</p>

<ol>
  <li>Instantiate <a href="http://link.jbrains.ca/NKRylh">Services</a> wherever the hell you want.</li>
  <li>Grab what you want when you want it.</li>
  <li>Do real work in your constructors.</li>
  <li>Publicise state.</li>
  <li>Embrace singletons.</li>
  <li>Make methods <code>static</code>. (Admittedly, this is more of a problem in Java/C# than Ruby/Python.)</li>
  <li>Inherit implementation.</li>
  <li>Reimplement polymorphism.</li>
  <li>Mix <a href="http://link.jbrains.ca/NKRylh">Services and Values</a>.</li>
  <li>Keep <a href="http://dictionary.reference.com/browse/conjunction">conjunctions</a> in your variable, method and class names.</li>
</ol>

<p><a href="http://misko.hevery.com/2008/07/30/top-10-things-which-make-your-code-hard-to-test/">Read more about the problems that these “techniques” cause</a>.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[From dependent tests to independent tests to independent assertions]]></title>
    <link href="http://blog.thecodewhisperer.com/2011/12/20/from-dependent-tests-to-independent-tests-to-independent-assertions/"/>
    <updated>2011-12-20T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2011/12/20/from-dependent-tests-to-independent-tests-to-independent-assertions</id>
    <content type="html"><![CDATA[<p><span style="float: right; margin-left: 10px; margin-bottom: 10px; width: 3cm"><img src="http://blog.thecodewhisperer.com/images/dhemery-small.jpg" alt="Dale Emery" /></span>
[We might choose to] write tests so that a failure in a predecessor test causes dependent tests not to execute. In object tests, we do this by writing a test method with multiple assertions. – Dale Emery</p>

<p>When multiple assertions check very tightly related things, I don’t mind them, but when they check relatively loosely related things, they act as integrated tests for multiple behaviors that we should consider separating. This is even subtler than the simpler idea of “one action per test”.</p>

<p>If you’d like a <strong>Novice algorithm</strong> to follow:</p>

<ol>
  <li>Look for any test with multiple assertions.</li>
  <li>Move those assertions to the bottom of the test. (If they aren’t already at the bottom, then you might have more than one action per test; this refactoring will help you discover that.)</li>
  <li>Extract all the assertions together into a single method.</li>
</ol>

<p>Now look at the new method. How many different objects does the method use?</p>

<p>If it’s more than one, then you almost certainly have unrelated assertions in the same place, so consider splitting the unrelated assertions into separate methods, then split the test into two so that each test invokes one of the two new separated assertion methods.</p>

<p>If your new assertion method uses only one object, then it might not be so clear whether those assertions are related. You can try this simple test: put all the values you’re checking in your assertions into a single object. Can you think of a good name for it? If yes, then perhaps you’ve just identified a missing abstraction in your system; and if not, then perhaps the assertions have too little to do with each other, in which case, try the trick in the preceding paragraph.</p>

<p>I apologise for not having a good example of this right now. If you point me to one, I’ll analyse it in this space.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Stop. Write a Learning Test.]]></title>
    <link href="http://blog.thecodewhisperer.com/2011/12/14/when-to-write-learning-tests/"/>
    <updated>2011-12-14T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2011/12/14/when-to-write-learning-tests</id>
    <content type="html"><![CDATA[<h1 id="the-30-second-version">The 30-second version</h1>

<ul>
  <li><a href="http://www.google.com/search?q=yak+shaving">Where did that yak come from?</a></li>
  <li>When you try to learn a new library at the same time as explore the behavior and design of your application, you slow down more than you think.</li>
  <li>When you can’t figure out how to make the new library work for this thing you want to build, you might spend hours fighting, debugging, swearing.</li>
</ul>

<p>Stop. Write a Learning Test.</p>

<ol>
  <li>Start a new test suite, test class, spec file, whatever you want to call it.</li>
  <li>Write a test that checks the things you tried to check earlier with debug statements.</li>
  <li>Write a test that has nothing to do with your application and its domain.</li>
  <li>Remove unnecessary details from your test.</li>
</ol>

<p>When this test passes, then you understand what that part of the library does. If it behaves strangely, then you have the perfect test to send to the maintainers of the library.<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>

<h1 id="the-details">The Details</h1>

<p>I just did this on a project using the context-free grammar parser <a href="https://github.com/nathansobo/treetop"><em>treetop</em></a>. Of course, I hadn’t used <em>treetop</em> before, so I had to learn it at the same time as design the grammar for the language I wanted to parse. I reached the point where I couldn’t write a <em>grammar rule</em> correctly, and spent probably an hour trying to figure out get it to work.<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup> Fortunately, at that moment, my laptop ran out of power, so I left the coffee shop<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup> and did the usual thing: <a href="http://c2.com/cgi/wiki?RubberDucking">I explained the problem to my wife so that I could hear myself doing that</a>. After about 15 minutes away from the problem, I decided to write some <a href="http://c2.com/cgi/wiki?LearningTest">Learning Tests</a>.</p>

<h1 id="summary-of-what-i-did">Summary of what I did</h1>

<ol>
  <li>I wrote a Learning Test for a simple case that I thought I already understood well.</li>
  <li>I wrote a Learning Test similar to the problem I had to deal with, to make sure I understood <em>that</em> well.</li>
  <li>I wrote a Learning Test for the exact case that behaved unexpectedly.</li>
</ol>

<p>The whole thing took an hour, and I understood the problem well enough to explain it to my wife. She understood it and agreed that it sounded like a mistake in the library.<sup id="fnref:4"><a href="#fn:4" rel="footnote">4</a></sup> I used this Learning Test to open an issue at github. Now I can proceed without pulling my own hair out.</p>

<h1 id="do-you-want-to-see-the-learning-tests">Do you want to see the Learning Tests?</h1>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>The case I already understood well  (single_simple_rule_spec.rb)</span> <a href="http://blog.thecodewhisperer.com/_code//learning_tests/single_simple_rule_spec.rb">download</a></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>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
<span class="line-number">34</span>
<span class="line-number">35</span>
<span class="line-number">36</span>
<span class="line-number">37</span>
</pre></td><td class="code"><pre><code class="ruby"><span class="line"><span class="nb">require</span> <span class="s1">&#39;treetop&#39;</span>
</span><span class="line">
</span><span class="line"><span class="n">describe</span> <span class="s2">&quot;Grammar with a simple rule&quot;</span> <span class="k">do</span>
</span><span class="line">  <span class="n">let</span><span class="p">(</span><span class="ss">:subject</span><span class="p">)</span> <span class="p">{</span> <span class="no">Treetop</span><span class="o">.</span><span class="n">load_from_string</span><span class="p">(</span>
</span><span class="line"><span class="o">&lt;&lt;</span><span class="no">GRAMMAR</span>
</span><span class="line"><span class="sh">grammar SimpleRule</span>
</span><span class="line"><span class="sh">  rule word</span>
</span><span class="line"><span class="sh">    [A-Za-z]+</span>
</span><span class="line"><span class="sh">  end</span>
</span><span class="line"><span class="sh">end</span>
</span><span class="line"><span class="no">GRAMMAR</span>
</span><span class="line">  <span class="p">)}</span>
</span><span class="line">
</span><span class="line">  <span class="n">let</span> <span class="p">(</span><span class="ss">:parser</span><span class="p">)</span> <span class="p">{</span> <span class="n">subject</span><span class="o">.</span><span class="n">new</span> <span class="p">}</span>
</span><span class="line">
</span><span class="line">  <span class="n">it</span> <span class="s2">&quot;doesn&#39;t match empty string&quot;</span> <span class="k">do</span>
</span><span class="line">    <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">should</span> <span class="n">be_false</span>
</span><span class="line">  <span class="k">end</span>
</span><span class="line">
</span><span class="line">  <span class="n">context</span> <span class="s2">&quot;matching single letter, the match result&quot;</span> <span class="k">do</span>
</span><span class="line">    <span class="n">let</span><span class="p">(</span><span class="ss">:result</span><span class="p">)</span> <span class="p">{</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">)</span> <span class="p">}</span>
</span><span class="line">
</span><span class="line">    <span class="n">it</span> <span class="p">{</span> <span class="n">result</span><span class="o">.</span><span class="n">should</span> <span class="n">be_true</span> <span class="p">}</span>
</span><span class="line">    <span class="n">it</span> <span class="p">{</span> <span class="n">result</span><span class="o">.</span><span class="n">text_value</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="s2">&quot;a&quot;</span> <span class="p">}</span>
</span><span class="line">    <span class="n">it</span> <span class="p">{</span> <span class="n">result</span><span class="o">.</span><span class="n">to_s</span><span class="o">.</span><span class="n">should_not</span> <span class="o">==</span> <span class="s2">&quot;a&quot;</span> <span class="p">}</span>
</span><span class="line">    <span class="n">it</span> <span class="p">{</span> <span class="n">result</span><span class="o">.</span><span class="n">should_not</span> <span class="n">respond_to</span><span class="p">(</span><span class="ss">:word</span><span class="p">)</span> <span class="p">}</span>
</span><span class="line">  <span class="k">end</span>
</span><span class="line">
</span><span class="line">  <span class="n">context</span> <span class="s2">&quot;matching many letters, the match result&quot;</span> <span class="k">do</span>
</span><span class="line">    <span class="n">let</span><span class="p">(</span><span class="ss">:result</span><span class="p">)</span> <span class="p">{</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">&quot;aBcDeF&quot;</span><span class="p">)</span> <span class="p">}</span>
</span><span class="line">
</span><span class="line">    <span class="n">it</span> <span class="p">{</span> <span class="n">result</span><span class="o">.</span><span class="n">should</span> <span class="n">be_true</span> <span class="p">}</span>
</span><span class="line">    <span class="n">it</span> <span class="p">{</span> <span class="n">result</span><span class="o">.</span><span class="n">text_value</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="s2">&quot;aBcDeF&quot;</span> <span class="p">}</span>
</span><span class="line">    <span class="n">it</span> <span class="p">{</span> <span class="n">result</span><span class="o">.</span><span class="n">to_s</span><span class="o">.</span><span class="n">should_not</span> <span class="o">==</span> <span class="s2">&quot;aBcDeF&quot;</span> <span class="p">}</span>
</span><span class="line">    <span class="n">it</span> <span class="p">{</span> <span class="n">result</span><span class="o">.</span><span class="n">should_not</span> <span class="n">respond_to</span><span class="p">(</span><span class="ss">:word</span><span class="p">)</span> <span class="p">}</span>
</span><span class="line">  <span class="k">end</span>
</span><span class="line"><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>The cases I wasn&#8217;t sure I understood  (single_rule_using_labels_spec.rb)</span> <a href="http://blog.thecodewhisperer.com/_code//learning_tests/single_rule_using_labels_spec.rb">download</a></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>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
<span class="line-number">34</span>
<span class="line-number">35</span>
<span class="line-number">36</span>
<span class="line-number">37</span>
<span class="line-number">38</span>
<span class="line-number">39</span>
<span class="line-number">40</span>
<span class="line-number">41</span>
<span class="line-number">42</span>
<span class="line-number">43</span>
</pre></td><td class="code"><pre><code class="ruby"><span class="line"><span class="nb">require</span> <span class="s1">&#39;treetop&#39;</span>
</span><span class="line">
</span><span class="line"><span class="n">describe</span> <span class="s2">&quot;Grammar with a simple rule that uses a label&quot;</span> <span class="k">do</span>
</span><span class="line">  <span class="n">context</span> <span class="s2">&quot;Labeled subexpression followed by another expression&quot;</span> <span class="k">do</span>
</span><span class="line">    <span class="n">let</span><span class="p">(</span><span class="ss">:subject</span><span class="p">)</span> <span class="p">{</span> <span class="no">Treetop</span><span class="o">.</span><span class="n">load_from_string</span><span class="p">(</span>
</span><span class="line"><span class="o">&lt;&lt;</span><span class="no">GRAMMAR</span>
</span><span class="line"><span class="sh">grammar SimpleRuleWithLabel</span>
</span><span class="line"><span class="sh">  rule word</span>
</span><span class="line"><span class="sh">    letters:[A-Za-z]+ [A-Za-z]*</span>
</span><span class="line"><span class="sh">  end</span>
</span><span class="line"><span class="sh">end</span>
</span><span class="line"><span class="no">GRAMMAR</span>
</span><span class="line">    <span class="p">)}</span>
</span><span class="line">
</span><span class="line">    <span class="n">let</span> <span class="p">(</span><span class="ss">:parser</span><span class="p">)</span> <span class="p">{</span> <span class="n">subject</span><span class="o">.</span><span class="n">new</span> <span class="p">}</span>
</span><span class="line">
</span><span class="line">    <span class="n">context</span> <span class="s2">&quot;matching many letters, the match result&quot;</span> <span class="k">do</span>
</span><span class="line">      <span class="n">let</span><span class="p">(</span><span class="ss">:result</span><span class="p">)</span> <span class="p">{</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">&quot;aBcDeF&quot;</span><span class="p">)</span> <span class="p">}</span>
</span><span class="line">
</span><span class="line">      <span class="n">it</span> <span class="p">{</span> <span class="n">result</span><span class="o">.</span><span class="n">should</span> <span class="n">respond_to</span><span class="p">(</span><span class="ss">:letters</span><span class="p">)</span> <span class="p">}</span>
</span><span class="line">      <span class="n">it</span> <span class="p">{</span> <span class="n">result</span><span class="o">.</span><span class="n">letters</span><span class="o">.</span><span class="n">text_value</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="s2">&quot;aBcDeF&quot;</span> <span class="p">}</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">context</span> <span class="s2">&quot;Labeled subexpression without another expression&quot;</span> <span class="k">do</span>
</span><span class="line">    <span class="n">it</span> <span class="s2">&quot;does not represent a valid grammar, even though I think it should&quot;</span> <span class="k">do</span>
</span><span class="line">      <span class="nb">lambda</span> <span class="p">{</span>
</span><span class="line">        <span class="no">Treetop</span><span class="o">.</span><span class="n">load_from_string</span><span class="p">(</span>
</span><span class="line"><span class="o">&lt;&lt;</span><span class="no">GRAMMAR</span>
</span><span class="line"><span class="sh">grammar SimpleRuleWithLabel</span>
</span><span class="line"><span class="sh">  rule word</span>
</span><span class="line"><span class="sh">    letters:[A-Za-z]+</span>
</span><span class="line"><span class="sh">  end</span>
</span><span class="line"><span class="sh">end</span>
</span><span class="line"><span class="no">GRAMMAR</span>
</span><span class="line">      <span class="p">)}</span><span class="o">.</span><span class="n">should</span> <span class="n">raise_error</span><span class="p">(</span><span class="no">RuntimeError</span><span class="p">,</span> <span class="sr">/Expected \#/</span><span class="p">)</span>
</span><span class="line">    <span class="k">end</span>
</span><span class="line">
</span><span class="line">    <span class="n">it</span> <span class="s2">&quot;really should let me refer to the expression as #letters&quot;</span> <span class="k">do</span>
</span><span class="line">      <span class="n">pending</span> <span class="s2">&quot;https://github.com/nathansobo/treetop/issues/21&quot;</span>
</span><span class="line">    <span class="k">end</span>
</span><span class="line">  <span class="k">end</span>
</span><span class="line"><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<div class="footnotes">
  <ol>
    <li id="fn:1">
      <p>Remember, we don’t call them bugs anymore: we call them “mistakes”. In this case, we can’t call it a “mistake” yet, because we might simply have a difference of opinion or mindset.<a href="#fnref:1" rel="reference">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>Note the wording: I already assuming that <em>I</em> have it right and <em>they</em> have it wrong. Bad programmer.<a href="#fnref:2" rel="reference">&#8617;</a></p>
    </li>
    <li id="fn:3">
      <p>They have a Second Cup in Romania. Canadians get why I’d find that weird.<a href="#fnref:3" rel="reference">&#8617;</a></p>
    </li>
    <li id="fn:4">
      <p>Smart woman, my wife.<a href="#fnref:4" rel="reference">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Refactor Your Way to a Dependency Injection Container]]></title>
    <link href="http://blog.thecodewhisperer.com/2011/12/07/refactor-your-way-to-a-dependency-injection-container/"/>
    <updated>2011-12-07T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2011/12/07/refactor-your-way-to-a-dependency-injection-container</id>
    <content type="html"><![CDATA[<h1 id="the-30-second-version">The 30-second version</h1>

<ul>
  <li>Invert the dependency on a Service, moving the <code>new</code> statement up one level in the call stack.<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></li>
  <li>Repeat for all dependencies on Services until the corresponding <code>new</code> statements arrive at your application’s entry point. The entry point now creates a large object graph of all your Services in its <code>initialise</code> function.</li>
  <li>Remove duplication in <code>EntryPoint.initialise()</code>:
    <ul>
      <li>Instantiate common objects only once, passing them into the necessary constructors, replacing any Singletons with plain objects.</li>
      <li>Extract the choice of implementation for each Service interface into a lookup table mapping interface type to implementation type.</li>
      <li>Externalise the lookup table to a file, if you like.</li>
    </ul>
  </li>
</ul>

<p>Now you have a customised Dependency Injection Container for your application. To go a little farther:</p>

<ul>
  <li>Remove duplication in <code>EntryPoint.initialise()</code> among three applications.</li>
</ul>

<p>Now you have a generic Dependency Injection Container that probably provides 80% or more of the features you’ll ever need.</p>

<p>I recommend trying this incrementally. Think of the <code>new</code> statements flowing up the call stack, into the entry point, then changing from code into data. Nice, no?</p>

<h1 id="the-details">The Details</h1>

<p>I don’t have much to add.</p>

<p>I hope this helps to demystify dependency injection containers. To read about the technique of injecting dependencies, I refer you to <a href="http://link.jbrains.ca/vN1IiF">one of my articles</a> and then <a href="http://www.google.com/search?q=dependency+injection">a trusty web search</a>.</p>

<p>This technique applies the <a href="http://www.objectmentor.com/resources/articles/dip.pdf">Dependency Inversion Principle</a> repeatedly to move the choice of implementation for an interface up the call stack. This way, concrete things depend on abstract things.</p>

<p>Removing duplication in the entry point respects the principle <a href="http://link.jbrains.ca/s2V3Co">Abstractions in Code, Details in Data</a>, but it does rely on reflection, which can cause some problems. All the better not to scatter this reflection throughout the code causing a serious cohesion problem. Using reflection like this, all in one place, helps balance using a powerful technique with a design that everyone can understand.</p>

<p>Now you know what about 70% of what a dependency injection container does. You can build one. Even if you don’t go that far, the Dependency Inversion Principle will help reducing coupling and highlight cohesion problems in your design. It provides <a href="http://link.jbrains.ca/gmeMhh">another set of mechanics to practise on the way to becoming an accomplished designer</a>.</p>

<div class="footnotes">
  <ol>
    <li id="fn:1">
      <p>I mean “Service” in the <a href="http://link.jbrains.ca/6AtyK">Domain-Driven Design</a> sense.<a href="#fnref:1" rel="reference">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rescuing Legacy Code by Extracting Pure Functions]]></title>
    <link href="http://blog.thecodewhisperer.com/2011/11/27/rescuing-legacy-code-by-extracting-pure-functions/"/>
    <updated>2011-11-27T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2011/11/27/rescuing-legacy-code-by-extracting-pure-functions</id>
    <content type="html"><![CDATA[<p>After running a handful of <a href="http://www.legacycoderetreat.org">Legacy Code Retreats</a> I’ve had the chance to try a number of exercises related to rescuing legacy code. I’d like to share one that has met with very positive reactions from people: extracting <em>pure functions</em>. I use the term <em>pure function</em> to describe a function that only operates on local variables and parameters, but does not touch any state outside the function. No object fields, no global data. I have very little experience in functional programming, so I hope I use the term in a standard way.</p>

<p>No doubt you already know about the <a href="http://c2.com/ppr/wiki/WikiPagesAboutRefactoring/ComposedMethod.html">Composed Method</a> design pattern, which we commonly use to help understand code as we read it. Most commonly you encounter a block of code with a comment that describes what that code does. You then extract that block of code into a method whose name matches the comment. I’ve used this technique for well on a decade to raise the level of abstraction in code, help code document itself, and eliminate misleading comments. While introducing these methods helps me read the code, it sometimes hides the tangle of dependencies that makes separating responsibilities so difficult. For this reason, I recommend trying to extract pure functions instead.</p>

<p>To introduce a pure function, start with a block of code and extract a method for it. Now look at all the fields and global variables that the method reads and introduce each one as a parameter to the method. Now look at all the fields and global variables that the method writes to and turn these into return values. Where the old code invokes the new function, assign each new return value to the corresponding field or global variable. You know you’ve done this correctly if, of course, the overall behhavior of the program hasn’t changed and you can mark the new function as <code>static</code> or whatever your language calls a class-level function.</p>

<p>In some languages, like Java, you’ll have to introduce a new little class to allow you to return multiple values from the new function. If you don’t want to do that right away, then return a <code>Map</code> of return values. Once you see that you need to return similar <code>Map</code>s from different functions, consider replacing those <code>Map</code>s with a new class. Perhaps that new class will attract some code!</p>

<p>When I’ve used this technique, two key things have happened: either I’ve noticed duplication in the parameter lists of the new functions or introducing a parameter has changed the behavior of the system. In the first case, I introduce Parameter Objects for the duplicated parameters, which then probably attract code and become useful domain objects. In the second case, I’ve detected temporal coupling, which requires me to separate the function into two smaller ones so that some output from the first becomes input to the second. This helps me uncover cohesion problems, usually of the type of different things written too close together.</p>

<p>I realise that an example would help right about now, but I would rather create some screencasts than write out examples in code, but I don’t know when exactly I intend to do that. I wanted to share this idea with you without waiting for the energy to put together a suitable screencast.</p>

<p>I invite you to try introducing pure functions into some legacy code and practising the technique as a kata. Get used to the various maneuvers, like introducing Parameter Objects or Return Value Objects or solving temporal coupling by splitting the function in two. It sounds crazy, but I’d like to try a Legacy Code Retreat where we practise only this technique all day. I don’t know whether anyone else would find it valuable enough to try it together for an entire day, over and over and over.</p>

<p>Would you? Add your comments below.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Detecting Changes in Third-Party Code]]></title>
    <link href="http://blog.thecodewhisperer.com/2011/11/26/detecting-changes-in-third-party-code/"/>
    <updated>2011-11-26T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2011/11/26/detecting-changes-in-third-party-code</id>
    <content type="html"><![CDATA[<p>One of the people who watched <a href="http://www.infoq.com/presentations/integration-tests-scam">the 2009 version of Integrated Tests Are A Scam</a> recently asked me: <em>I wonder how you deal with updates of third-party libraries. How do you detect subtle API or behaviour changes? At the moment, I write state-based integration tests for these cases and I wonder whether this isn’t a sensible use of integration tests.</em></p>

<p>I write Learning Tests to discover how a third-party library works. I isolate myself from the third-party library through a layer of interfaces and adapter classes that evolve from the common ways I use the third-party library. I call this the “Pattern of Usage API”, as it represents the way my application uses that third-party library. Now my application uses the third-party library through a layer of interfaces, which means that I can introduce Contract Tests on those interfaces. These Contract Tests effectively describe the subset of the third-party library’s behavior on which I depend.</p>

<p>Now when I upgrade the third-party library, I run the Contract Tests against my adapters to that library. Test failures usually indicate a backwards incompatible change in the third-party library. (Sometimes they indicate a trivial difference in the API which requires a trivial fix, such as an API call having been renamed or something.)</p>

<p>Of course, this only helps me detect behavior changes related to computing answers, and not related to responsiveness, reliability, scalability, and so on. For that, I’ll always need system tests.</p>

<p>The Contract Tests are almost always state-based integration tests. I simply limit these to the implementation of Pattern of Usage API and don’t let it leak farther up the call stack. At some point you have to integrated with the Outside World. I simply teach people to look to make that integration thinner.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[When should I remove duplication?]]></title>
    <link href="http://blog.thecodewhisperer.com/2011/09/29/when-should-i-remove-duplication/"/>
    <updated>2011-09-29T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2011/09/29/when-should-i-remove-duplication</id>
    <content type="html"><![CDATA[<p>As I learn to become a better programmer, I continue to follow <a href="http://link.jbrains.ca/g9P6Jw">the four elements of simple design</a>. Of these, I have observed that “remove duplication” helps me discover an appropriate structure for the thing I want to build. In my classes, we practise removing duplication a lot, in part because most people understand the rule “remove duplication” well enough to find it useful. After the first few weeks of practice, however, programmers following this rule observe varying results: sometimes removing the duplication makes the design much clearer, and sometimes it muddies the water. At this stage, she usually looks for more detailed rules to help decide when to remove duplication and when to leave it alone. I offer some simple rules and guidelines for this situation.</p>

<p>When I can’t decide whether to remove a certain bit of duplication I’ve found, I fall back on two rules:</p>

<ol>
  <li>Remove duplication only after you see <a href="http://link.jbrains.ca/qUxm1s"><em>three</em> copies</a>.</li>
  <li>If you don’t know how to remove this particular kind of duplication, then write more tests. Either you need more examples to see the pattern, or more examples will show a different, better pattern.</li>
</ol>

<p>I also remember two guidelines:</p>

<ol>
  <li>Don’t be afraid to remove duplication by introducing a method or class or interface with a stupid name. Remember that <a href="http://link.jbrains.ca/nP9Fvk">you can always improve the name later</a>.</li>
  <li>If you sense duplication, but don’t really see it, or can’t explain it to others, then <a href="http://link.jbrains.ca/nP9Fvk">make the surrounding names more precise</a>; then maybe you will see the duplication.</li>
</ol>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Writing Contract Tests in Java differently]]></title>
    <link href="http://blog.thecodewhisperer.com/2011/07/17/writing-contract-tests-in-java-differently/"/>
    <updated>2011-07-17T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2011/07/17/writing-contract-tests-in-java-differently</id>
    <content type="html"><![CDATA[<p>I just wanted to know whether anyone has tried nesting the concrete tests inside the abstract test like this, and if you have, then how do/did you like it?</p>

<div><script src="https://gist.github.com/1084541.js?file="></script>
<noscript><pre><code>
package ca.jbrains.junit;

import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.junit.Test;

public abstract class ListContract {
    @Test
    public void emptyList() throws Exception {
        assertTrue(createEmptyList().isEmpty());
    }

    public abstract List&lt;Object&gt; createEmptyList();

    public static class ArrayListRespectsListContract extends ListContract {
        @Override
        public List&lt;Object&gt; createEmptyList() {
            return new ArrayList&lt;Object&gt;();
        }
    }

    public static class LinkedListRespectsListContract extends ListContract {

        @Override
        public List&lt;Object&gt; createEmptyList() {
            return new LinkedList&lt;Object&gt;();
        }
    }
}
</code></pre></noscript></div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Contract Tests: An Example]]></title>
    <link href="http://blog.thecodewhisperer.com/2011/07/07/contract-tests-an-example/"/>
    <updated>2011-07-07T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2011/07/07/contract-tests-an-example</id>
    <content type="html"><![CDATA[<p>I found an example of contract tests in Arlo Belshee’s <a href="http://arlobelshee.com/tag/no-mocks">series of articles about mock-free testing</a>. I must strongly, strongly point out that Arlo uses the term “mock” narrowly to refer to runtime- or bytecode-generated proxies that intercept interface method invocations and provide the ability to set method expectations, in the way that JMock and NMock do. He <em>does not</em> mean the generic term “mock”, where he uses the term “test double” instead. I thank him for that.</p>

<p>If you click <a href="https://github.com/arlobelshee/ArsEditorExample/blob/master/SimulatableApi.Tests/FileSystemCanLocateFilesAndDirs.cs">here</a> you’ll see an almost textbook example of a contract test: that is, a test class that can run the same set of tests for two different implementations of the same interface. I would change only one thing: I’d extract the tests into an abstract superclass—something I otherwise hate to do—and pull the declaration of the method <code>MakeTestSubject()</code> up there, leaving two subclasses, one for the real file system and one for the simulated one. “YAGNI,” you say, and I agree, but I prefer the symmetry of the abstract superclass design to the asymmetry of having one class inherit from the other. I find it easier to grok quickly.</p>

<p>Either way, I feel good seeing contract tests out in the wild. I’m not so crazy after all.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Adding behavior with confidence]]></title>
    <link href="http://blog.thecodewhisperer.com/2011/06/22/adding-behavior-with-confidence/"/>
    <updated>2011-06-22T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2011/06/22/adding-behavior-with-confidence</id>
    <content type="html"><![CDATA[<h1 id="the-30-second-version">The 30-second version</h1>

<ul>
  <li>Adding behavior confidently involves having fewer parts to change (low duplication), knowing which ones to change (high cohesion), ease of changing just the part you want to change (low coupling), and understanding how you’ve changed it (strong tests).</li>
  <li>Adding behavior requires breaking an existing assumption.</li>
  <li>In a well-factored design, we can easily find the one place we have made that assumption. (Otherwise, why bother refactoring?)</li>
  <li>First, make room for the new code, then add it.</li>
  <li>To make room for the new code, extract the existing code into a method whose name describes the generalisation we want to make, or the idea we want to introduce.</li>
  <li>By making room for the new code, we make that code easier to reuse by reducing its dependence on its surrounding context.</li>
</ul>

<h1 id="want-to-learn-more">Want to learn more?</h1>

<ul>
  <li>Visit the links in this article.</li>
  <li>Attend <a href="http://www.jbrains.ca/training/agile-design-beyond-the-basics">Agile Design: Beyond the Basics</a>.</li>
  <li><a href="http://www.jbrains.ca/schedule-a-working-session">Pair with me</a>.</li>
</ul>

<h1 id="the-details">The Details</h1>

<p>We all want to add behavior to a system confidently, and I have observed that my confidence in adding behavior depends on two factors:</p>

<ul>
  <li>I know where to add code.</li>
  <li>I understand the behavior of the code I am adding.</li>
</ul>

<p>I use test-driven development as the main technique for handling the second of these two factors, but what about the first? I have uncovered a technique that I both use and teach, and I’d like to share that with you. I call this “making room for the new code”, naming it for a phrase I vaguely remember reading in one of the Grand Old XP books. (Did Kent Beck or Ron Jeffries write it? I can’t remember.) This technique helps me quickly find a reasonable first-draft place in the code base to put new code. After I have put the new code in place, and I feel confident that it does what I expect, I then use the <a href="http://link.jbrains.ca/g9P6Jw">Four Elements of Simple Design</a> to guide me in refactoring to improve the design.</p>

<h1 id="a-premise">A premise</h1>

<p>I start with the premise that <strong>adding behavior means breaking an assumption</strong>. By this I mean that whenever we add code to a system in order to extend its behavior, we have to falsify at least one assumption we’ve previously made. For example:</p>

<ul>
  <li>In a payroll system, in order to support a second cheque printer, we likely have to break the assumption that there is only one cheque format.</li>
  <li>In a point of sale system, in order to support separate cash and card payment reports, we likely have to break the assumption that all “we made a sale” events look the same.</li>
  <li>In a mobile phone monitoring system, in order to support billing by the second, we likely have to break the assumption that we only have to count the number of minutes a call lasted.</li>
</ul>

<p>Some of these seem obvious, and others less so, and it bears emphasising that the specific assumption or assumptions we break depends heavily on what we’ve built so far and the way we articulate the soon-to-be-added behavior. Even so, I conjecture that <span class="highlight"><em>for every behavior we want to add to a system, we can identify a non-empty list of assumptions that we <strong>need</strong> to break</em></span>.</p>

<h1 id="the-technique">The technique</h1>

<ol>
  <li>Identify an assumption that the new behavior needs to break.</li>
  <li>Find the code that implements that assumption.</li>
  <li>Extract that code into a method whose name represents the generalisation you’re about to make.</li>
  <li>Enhance the extracted method to include the generalisation.</li>
</ol>

<p>The less duplication you have in the system, the better this works, because duplicate code makes it difficult to find all the code that implements the assumption in question. Similarly, the more appropriate the names in your system, the better this works, because unsuitable names make it difficult to know which code implements the assumption in question, as opposed to something unrelated. You’ll notice that these points relate both to the <a href="http://link.jbrains.ca/g9P6Jw">Four Elements of Simple Design</a> and to the core concepts of <a href="http://link.jbrains.ca/jSNrEJ">Coupling and Cohesion</a>.</p>

<p>Yes, yes…</p>

<div style="text-align: center"><img style="width: 200px" src="http://images.jbrains.ca/handy-right-about-now.png" /></div>

<h1 id="an-example">An example</h1>

<p>We are building a point of sale system, and we’ve just decided to implement sales tax. I live in PEI, Canada, where not only do we exclude sales tax from the price, we have two sales taxes, and we charge the second one <em>on top of</em> the first one. For example:</p>

<p class="example">A $125 item that attracts both GST (the &#8220;Goods and Services&#8221; tax) and PST (provincial sales tax) costs a total of $144.38. GST at 5% costs $6.25, then PST at 10% of $131.25 (= $125 + $6.25) costs $13.13. The total is $125 + $6.25 + $13.13 = $144.38.</p>

<p>Notice that this example implies that GST or PST might or might not apply to a given product, so even before we identify the old assumption to break, we need to note the new assumption we’ll make: <em>we assume that all products attract both GST and PST</em>. Our customers won’t like it, but the tax authorities will love it, and only they have the power to treat us guilty until proven innocent.</p>

<p>Our code has a class like this in it.</p>

<div><script src="https://gist.github.com/1040052.js?file=UserGestureListener.rb"></script>
<noscript><pre><code>class UserGestureListener
  def on_barcode_scanned(barcode)
    product = @catalog.find(barcode)
    if product.nil?
      @display.display_message(ProductNotFoundMessage.with(barcode))
    else
      @display.display_product(product)
      @sale_total += product.price
    end
  end
end</code></pre></noscript></div>

<p>What do we assume now that we can’t allow ourselves to assume any longer? <strong>The sale total should increment by the (net) price of the item we sell.</strong> By <em>net price</em> here, I refer to the pre-tax price, because of course, until now, our system has no notion of “tax”. Fortunately, because we’ve ruthlessly removed duplication so far, computing the running total of the sale requires only this line of code. We can pretty safely apply the technique of this article right here. To do this, we extract the assumption into a new method whose name represents the generalisation we’re about to make. In this case, we don’t want to increase the sale total by the product’s <em>price</em>, but rather by its <em>cost</em>, which includes any additional charges beyond net price. So, we introduce a method for accumulating the scanned product’s cost.</p>

<div><script src="https://gist.github.com/1040052.js?file=UserGestureListener-AddedMethodDescribingGeneralisation.rb"></script>
<noscript><pre><code>class UserGestureListener
  def on_barcode_scanned(barcode)
    product = @catalog.find(barcode)
    if product.nil?
      @display.display_message(ProductNotFoundMessage.with(barcode))
    else
      @display.display_product(product)
      accumulate_cost(product)
    end
  end

  def accumulate_cost(product)
      @sale_total += product.price
  end
end</code></pre></noscript></div>

<p>This creates space for the new code. We test-drive the new code, and end up with this delightful monstrosity.</p>

<div><script src="https://gist.github.com/1040052.js?file=UserGestureListener-Generalised.rb"></script>
<noscript><pre><code>&lt;!DOCTYPE html&gt;
&lt;!--

Hello future GitHubber! I bet you're here to remove those nasty inline styles,
DRY up these templates and make 'em nice and re-usable, right?

Please, don't. https://github.com/styleguide/templates/2.0

--&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta http-equiv=&quot;Content-type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
    &lt;title&gt;Unicorn! &amp;middot; GitHub&lt;/title&gt;
    &lt;style type=&quot;text/css&quot; media=&quot;screen&quot;&gt;
      body {
        background: #f1f1f1;
        font-family: &quot;HelveticaNeue&quot;, Helvetica, Arial, sans-serif;
        text-rendering: optimizeLegibility;
        margin: 0; }

      .container { margin: 50px auto 40px auto; width: 600px; text-align: center; }

      a { color: #4183c4; text-decoration: none; }
      a:visited { color: #4183c4 }
      a:hover { text-decoration: none; }

      h1 { letter-spacing: -1px; line-height: 60px; font-size: 60px; font-weight: 100; margin: 0px; text-shadow: 0 1px 0 #fff; }
      p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; }

      ul { list-style: none; margin: 25px 0; padding: 0; }
      li { display: table-cell; font-weight: bold; width: 1%; }
      .divider { border-top: 1px solid #d5d5d5; border-bottom: 1px solid #fafafa;}


    &lt;/style&gt;
  &lt;/head&gt;
  &lt;body&gt;

    &lt;div class=&quot;container&quot;&gt;
      &lt;p&gt;
        &lt;img src=&quot;data:image/png;base64,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&quot;&gt;
      &lt;/p&gt;

      &lt;p&gt;&lt;strong&gt;This page is taking way too long to load.&lt;/strong&gt;&lt;/p&gt;
      &lt;p&gt;Sorry about that. Please try refreshing and contact us if the problem persists.&lt;/p&gt;
      &lt;div class=&quot;divider&quot;&gt;&lt;/div&gt;
      &lt;ul id=&quot;error-suggestions&quot;&gt;
          &lt;li&gt;&lt;a href=&quot;https://github.com/contact&quot;&gt;Contact Support&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;http://status.github.com&quot;&gt;Status Site&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;http://twitter.com/github&quot;&gt;@github&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;&lt;img width=&quot;109&quot; height=&quot;48&quot; title=&quot;&quot; alt=&quot;&quot; src=&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAG0AAAAwCAYAAAAb6PR/AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjdCQkMxMDhEQjI4MTFFMDk4REM4M0Q4MjE0NzE1RkUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjdCQkMxMDlEQjI4MTFFMDk4REM4M0Q4MjE0NzE1RkUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyMjMxMjA2QkRCMjYxMUUwOThEQzgzRDgyMTQ3MTVGRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyMjMxMjA2Q0RCMjYxMUUwOThEQzgzRDgyMTQ3MTVGRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PhqQs8QAAArlSURBVHja7FwJY9q4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&quot; /&gt;&lt;/p&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre></noscript></div>

<p>It looks ugly, but it works. In addition to looking ugly, this method has <a href="http://link.jbrains.ca/kqLJMj">Feature Envy</a>. Specifically, the calculation part of <code>#accumulate_cost</code> only talks to <code>product</code>, and so it can move onto the class <code>Product</code>, leaving only the accumulating left behind. You could also say that this method had <a href="http://link.jbrains.ca/lUrZh4">two responsibilities</a>, so I separated them, then notice the feature envy in one of them, then moved it. I can almost always take smaller steps.</p>

<div><script src="https://gist.github.com/1040052.js?file=UserGestureListener-Refactored.rb"></script>
<noscript><pre><code>class UserGestureListener
  def on_barcode_scanned(barcode)
    product = @catalog.find(barcode)
    if product.nil?
      @display.display_message(ProductNotFoundMessage.with(barcode))
    else
      @display.display_product(product)
      @sale_total += product.cost
    end
  end
end

class Product
  def cost
    ((price * 1.05).round * 1.1).round
  end
end
</code></pre></noscript></div>

<p>Notice the <a href="http://amzn.to/mB7yLf">context independence</a> we’ve achieved with the method <code>Product#cost</code>. We can now refine the notion of “cost” freely without worrying about how someone will use that information. We have an easy-to-find, easy-to-extend part of the system where we can add behavior for determining which products attract which taxes, supporting multiple tax calculation policies, and even including shipping, handling and restocking fees. Now we can really add future behavior with confidence.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[A model for improving names]]></title>
    <link href="http://blog.thecodewhisperer.com/2011/06/15/a-model-for-improving-names/"/>
    <updated>2011-06-15T00:00:00+00:00</updated>
    <id>http://blog.thecodewhisperer.com/2011/06/15/a-model-for-improving-names</id>
    <content type="html"><![CDATA[<p style="text-align: center"><a href="http://assets.jbrains.ca/ImprovingNames.pdf"><img style="width: 500px; margin: 0px auto" src="http://30.media.tumblr.com/tumblr_lmsovxnwmq1qa6fh7o1_500.png" /></a></p>

<p>A model for improving the names of variables, fields, interfaces, classes and namespaces in a system. Practise this and more in my course, <a href="http://www.jbrains.ca/training/agile-design-beyond-the-basics">Agile Design: Beyond the Basics</a>.</p>
]]></content>
  </entry>
  
</feed>
