<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:html="http://www.w3.org/1999/html" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">
<channel>
   <title>Extra Cheese</title>
   <link>http://blog.extracheese.org</link>
   <description>Gary Bernhardt's blog</description>
   <language>en</language>
   <copyright>Copyright 2007 Gary Bernhardt</copyright>
   <ttl>60</ttl>
   <pubDate>Mon, 15 Feb 2010 19:36 GMT</pubDate>
   <managingEditor>gary.bernhardt at gmail</managingEditor>
   <generator>PyBlosxom http://pyblosxom.sourceforge.net/ 1.4.2 8/16/2007</generator>
<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/extracheese" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="extracheese" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
   <title>Python vs. Ruby: A Battle to The Death</title>
   <guid isPermaLink="false">2010/02/python-vs-ruby-a-battle-to-the-death</guid>
   <link>http://blog.extracheese.org/2010/02/python-vs-ruby-a-battle-to-the-death.html</link>
   <description><![CDATA[

<p>
    At <a href="http://www.seapig.org/NWPD10">Northwest Python Day 2010</a> on
    January 30th, I gave two talks; this is the second, which was the last
    talk of the day.  I tuned it to its audience and time slot, making it
    biased toward an audience that already knows Python, as well as being
    lighter than originally intended. I still quite like the result.
</p>

<p>
    During my talk, I mention <a
    href="http://www.infoq.com/presentations/braithwaite-rewrite-ruby">Ruby.rewrite(Ruby)</a>,
    a talk by Reg Braithwithe. I recommend it. It also happens to contain my
    favorite quote from any talk, ever, which I will not repeat here. You'll
    just have to guess!
</p>

<p>
    I've removed a few small bits from the audio &ndash; one grossly incorrect
    statement, one slide that could be misinterpreted in ways I want to avoid,
    and a couple of audience questions that I basically had no answer for.
    None of these edits affects the content of the talk in my opinion.
</p>

<p>
    The talk is dense and necessarily glosses over a lot of subtleties. I talk
    about the Zen of Python, monkey patching (several times), the Ruby
    community's reckless hastiness, the syntax of RSpec and cucumber, beauty
    and ugliness in languages and testing tools, the complexity of the
    languages' grammars, syntactic vs. semantic complexity, the relative taste
    of grasshoppers and tree bark, etc., etc. There's way too much here to
    give anything a fair treatment. I hope that you'll keep this in mind while
    watching, avoid interpreting the talk as a claim to absolute truth, and
    simply enjoy it for what it is.
</p>

<p>
    Shortly after the event, Geoffrey Grosenbach posted <a
    href="http://blog.peepcode.com/tutorials/2010/what-pythonistas-think-of-ruby">
    his thoughts</a>. You should take a look for another viewpoint.
</p>

<p>
    I'll be at PyCon later this week, by the way, so feel free to commiserate
    with, or rant at, me. With that, here's the talk:
</p>

<object width="400" height="225"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=9471538&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=9471538&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="225"></embed></object><p><a href="http://vimeo.com/9471538">Python vs. Ruby: A Battle to The Death</a> from <a href="http://vimeo.com/user1043515">Gary Bernhardt</a> on <a href="http://vimeo.com">Vimeo</a>.</p>


]]></description>
   <category domain="http://blog.extracheese.org">/2010/02</category>
   <pubDate>Mon, 15 Feb 2010 19:36 GMT</pubDate>
</item>
<item>
   <title>Functional and Non-Functional Testing</title>
   <guid isPermaLink="false">2010/01/functional-and-non-functional-testing</guid>
   <link>http://blog.extracheese.org/2010/01/functional-and-non-functional-testing.html</link>
   <description><![CDATA[

<p>
    Different types of complexity interact with test suites in different ways.
    Consider <a
        href="/2009/07/a-brief-history-of-bitbacker-a-startup.html">BitBacker</a>,
    an online backup product that I worked on for three years. It had very few
    functional requirements. At its core, it only had to let the user choose
    files, back them up, and restore them. Almost all of the complexity was
    non-functional: it had to look good and be easy to use, of course, but it
    also had to be fast and secure. I spent most of my development effort on
    the "fast" and "secure" parts.
</p>

<p>
    (Note that when I say "functional" here, I'm talking about requirements
    for a system's behavior. This has nothing to do with functional
    programming.)
</p>

<p>
    In this type of app, where there are so few functional requirements,
    functional test fragility is less of a problem. In a recent discussion
    with <a href="http://www.wavethenavel.com">Jonathan Penn</a>, I mentioned
    that the backup and restore functionality were tested at the unit,
    subsystem, and full-stack levels: three different levels of tests, all
    testing the same thing. He asked me whether this made refactoring
    difficult. It didn't.
</p>

<p>
    BitBacker's functional requirements were never going to change. When the
    user backed up and then restored files, they had to be identical to the
    originals. That's all. It took 17,000 lines of code to make that happen
    efficiently and securely, but the surface area of the user-facing problem
    is tiny.
</p>

<p>
    I didn't know this at the time. If I was building a business app instead
    of a backup system, I probably would've ended up with a similar test
    suite, and in that situation it would've been a burden. Fortunately, I got
    lucky, and I've learned this lesson by retrospecting about my luck rather
    than retrospecting about some pain that I felt.
</p>

<p>
    What about automated non-functional tests? The topic is murky in general,
    and I only know how to test small subsets of the non-functional
    requirement space. I don't know how to automate testing of user
    experience, for example.
</p>

<p>
    I have done automated performance testing, however. At one point, I wrote
    tests for BitBacker that ran backups across a wide range of file counts
    and asserted that the backup time grew linearly with the number of files.
    That's clearly a non-functional test, but how fragile is it?
</p>

<p>
    It's very fragile, of course, unless you run it on massive file counts
    that would've taken far too long for my patience at the time. I left the
    file counts small, so it ran fast but broke constantly, which eventually
    led me to remove it.
</p>

<p>
    I replaced the test with a system that could kick off various predefined
    processes ("do an empty backup", "back up 1,000 files", etc.), graphing
    the runtimes and memory footprints across revisions in version control.
    One look at those performance graphs would show whether, and where, there
    was a problem.  This gave me a different kind of feedback: instead of
    defining "success" and "failure", it would alert me to a change, which I
    could then investigate on my own.
</p>

<p>
    I suspect that this is a fundamental property of non-functional testing.
    Trying to fully automate it and boil it down to a set of pass/fail
    assertions, while sometimes possible, seems prone to fragility. It may be
    that non-functional testing is best achieved by dashboard apps, like my
    performance-over-revisions graph, or an app that renders every page in a
    user flow automatically and highlights recent changes in appearance.
</p>


]]></description>
   <category domain="http://blog.extracheese.org">/2010/01</category>
   <pubDate>Thu, 21 Jan 2010 22:56 GMT</pubDate>
</item>
<item>
   <title>Test Double Injection Inversion</title>
   <guid isPermaLink="false">2010/01/test-double-injection-inversion</guid>
   <link>http://blog.extracheese.org/2010/01/test-double-injection-inversion.html</link>
   <description><![CDATA[

<p>
    In <a
    href="http://blog.objectmentor.com/articles/2010/01/17/dependency-injection-inversion">Dependency
    Injection Inversion</a>, Uncle Bob wonderfully explains the difference
between Dependency Injection and Dependency Injection <em>Frameworks</em>, a
topic I've done a lot of thinking about recently. You should go read his post
right now if you haven't yet.
</p>

<p>
    At the end, he provides the test code below as an example of testing some
    dependency-injected Java code:
</p>

<pre><code>public class BillingServiceTest {
  private LogSpy log;

  @Before
  public void setup() {
    log = new LogSpy();
  }

  @Test
  public void approval() throws Exception {
    BillingService bs = new BillingService(new Approver(), log);
    bs.processCharge(9000, "Bob");
    assertEquals("Transaction by Bob for 9000 approved",
                 log.getLogged());
  }

  @Test
  public void denial() throws Exception {
    BillingService bs = new BillingService(new Denier(), log);
    bs.processCharge(9000, "Bob");
    assertEquals("Transaction by Bob for 9000 denied",
                 log.getLogged());
  }
}

class Approver implements CreditCardProcessor {
  public boolean approve(int amount, String id) {
    return true;
  }
}

class Denier implements CreditCardProcessor {
  public boolean approve(int amount, String id) {
    return false;
  }
}

class LogSpy implements TransactionLog {
  private String logged;

  public void log(String s) {
    logged = s;
  }

  public String getLogged() {
    return logged;
  }
}</code></pre>

<p>
    It's perfectly fine Java code, and it wonderfully demonstrates the power
    of injection. After the code, Uncle bob says:
</p>

<blockquote>
    It would have been tragic to use a mocking framework for such a simple set
    of tests.
</blockquote>

<p>
    In Java, I agree completely. In a more modern language, I
    <em>disagree</em> completely!  I've translated his example to Python using
    my <a href="http://bitbucket.org/garybernhardt/dingus/">Dingus</a> test
    double library to illustrate the simplicity that doubles can provide:
</p>

<pre><code>class BillingServiceTest:
    def setup(self):
        self.log = Dingus()

    def test_approval(self):
        approver = Dingus(approve__returns=True)
        bs = BillingService(approver, self.log)
        bs.process_charge(9000, 'Bob')
        assert self.log.calls(
            'log',
            'Transaction by Bob for 9000 approved').once()

    def test_denial(self):
        denier = Dingus(approve__returns=False)
        bs = BillingService(approver, self.log)
        bs.process_charge(9000, 'Bob')
        assert self.log.calls(
            'log',
            'Transaction by Bob for 9000 denied').once()
</code></pre>

<p>
    In a real system, I'd factor these tests slightly differently; I've left
    them as close to Bob's as possible. This is 13 ELOC vs. Bob's 38 &ndash;
    only about a third as much code! Some of the difference is in his testing
    library's ceremony, but most of it is in his test doubles. For example, he
    says:
</p>

<pre><code>class Approver implements CreditCardProcessor {
  public boolean approve(int amount, String id) {
    return true;
  }
}</code></pre>

<p>
    That is a lot of code! All it really says is "the approve method always
    returns true", with the rest being a complex dance around Java's rigidity.
    This is a liability for programmers working in such languages, as well as
    a learning barrier for new testers. In my Python version, the following
    takes the place of the Approver class, as well as its instantiation:
</p>

<pre><code>approver = Dingus(approve__returns=True)</code></pre>

<p>
    That line of code is so close to "the approve method always returns true"
    that I can't imagine it being any clearer.  Of course, if the magic double
    underscores turn you off, you can also say:
</p>

<pre><code>approver = Dingus(approve=returner(True))</code></pre>

<div class="digression">
    <h4>Digression</h4>
    <p>
        I'd love to hear what you think about those two alternate forms. I
        want to deprecate one, but I don't know which.
    </p>
</div>

<p>
    I fear that statements like Uncle Bob's about test doubles may lead newer
    programmers, and static-only programmers, astray. His advice is wonderful,
    but only in certain domains. Like so many things in software, doubling is
    far easier when the shackles of Javaesque type systems are removed. And,
    if you worry that the complexity is simply moved into the test double
    library, fear not: <a
        href="http://bitbucket.org/garybernhardt/dingus/src/tip/dingus.py">Dingus</a>
    is currently 193 ELOC long, including plenty of features not mentioned
    here!
</p>


]]></description>
   <category domain="http://blog.extracheese.org">/2010/01</category>
   <pubDate>Thu, 21 Jan 2010 22:56 GMT</pubDate>
</item>
<item>
   <title>String Calculator Kata in Python</title>
   <guid isPermaLink="false">2010/01/string-calculator-kata-in-python</guid>
   <link>http://blog.extracheese.org/2010/01/string-calculator-kata-in-python.html</link>
   <description><![CDATA[

<p>
    For those who aren't familiar, katas are those impressive sequences of
    movements that you've surely seen martial arts guys perform. Code katas
    are the same idea applied to writing code: you solve a problem many times,
    mastering the movements, and then perform it for others.
</p>

<p>
    My friend <a href="http://www.coreyhaines.com">Corey Haines</a> has worked
    with some other people to run a <a
    href="http://www.katacasts.com">Katacast</a> site dedicated to code katas,
    posting them roughly once per week. Recently, there's been a string of
    solutions to the same problem, with my Python version as this week's
    entry.
</p>

<p>
    Briefly, here's the problem I solve. I have numbers coming in as a string,
    separated by commas or newlines. My job is to add those numbers and return
    the sum. There are two complications:
</p>

<ol>
    <li>If the first line of the string is of the form "//*", then * is also
    a possible delimiter. This works for any string, not just *.</li>
    <li>Negative numbers must be rejected.</li>
</ol>

<p>
    You can see the kata and read my brief commentary on the <a
    href="http://katas.softwarecraftsmanship.org/?p=128">Katacasts</a> site,
    or go straight to <a href="http://vimeo.com/8569257">Vimeo</a> to watch
    it. It's only 4:32 long, so it's not a big commitment.
</p>

<p>
    <a href="http://vimeo.com/8569257"><img src="/2010/01/string_calculator_python_katacast_thumbnail.png"></a>
    <a href="http://vimeo.com/8569257">String Calculator Kata In Python</a> from <a href="http://vimeo.com/user1043515">Gary Bernhardt</a> on <a href="http://vimeo.com">Vimeo</a>.
</p>

<p>
    My screencasts always prompt questions about my Vim configuration, so take
    a look at my <a
    href="http://bitbucket.org/garybernhardt/dotfiles">dotfiles repo</a> if
    you're interested. For this kata, I'm slowing down intentionally &ndash;
    typing slower and inserting small, regular pauses so the viewer has time
    to look around a bit. I may post a "hard mode" version at full speed if
    people show interest.
</p>

<p>
    Comments are encouraged, of course &ndash; the purpose of a kata is
    improvement!
</p>

<p>
    If you like this, by the way, you may also enjoy the <a
    href="/2009/11/refactoring_a_cyclomatic_complexity_script.html">refactoring</a>
    screencast I posted recently.
</p>


]]></description>
   <category domain="http://blog.extracheese.org">/2010/01</category>
   <pubDate>Wed, 06 Jan 2010 18:04 GMT</pubDate>
</item>
<item>
   <title>On Abstraction</title>
   <guid isPermaLink="false">2009/12/on_abstraction</guid>
   <link>http://blog.extracheese.org/2009/12/on_abstraction.html</link>
   <description><![CDATA[

<p>
    Some people seem to consider <em>abstraction</em> a bad word. I think that
    this is misguided and impedes progress &ndash; all software is
    abstraction.  Understanding what our abstractions mean, and what makes
    them good or bad, is the core of design.
</p>

<p>
    For now, let's define abstractions as concepts; nothing more. If it's a
    concept in your head, it's an abstraction. (I've tried to define the word
    more fully about ten times, deleting each definition in turn.)
</p>

<p>
    The interesting part of abstractions is their violation.  First, the
    textual definition of an abstraction &ndash; a class, for example &ndash;
    can violate <em>itself</em>. This happens when a class presents
    information at more than one level of abstraction.  Here's Grady Booch,
    from "Object Oriented Analysis and Design":
</p>

<blockquote>
    [The] class Dog is functionally cohesive if its semantics embrace the
    behavior of a dog, the whole dog, and nothing but the dog."
</blockquote>

<p>
    It's a wonderfully terse explanation, but doesn't go far enough for our
    purposes because it doesn't address relationships.
</p>

<blockquote class="digression">
    <h4>Example</h4>
    A Person class can have a first_name field. But should Person also have a
    set of address fields like street and zip_code? Probably not. These fields
    are part of an Address, which is a concept that exists independent of
    Person.  Moving them into an Address class reifies this natural
    abstraction in our code, making it mirror the way the ideas are
    structured in our brains.
</blockquote>

<p>
    This is sort of a restatement of the Single Responsibility Principle
    (SRP), which is sort of a restatement of the principle of cohesion. We
    have many tools for thinking about this idea because it's important.
</p>

<p>
    Abstractions can also be violated from <em>outside</em>. If an object
    exposes a set of fields to me, I should avoid looking into those fields'
    structure.  In other words, I must respect the abstraction provided by the
    object.  If I feel the need to violate the abstraction, I need to
    reconsider how to modify the boundaries to match that need, rather than
    violating the boundaries by crossing them.
</p>

<p>
    This is the moment when design happens: I can take the path of short-term
    gain by reaching into my collaborators' collaborators, or I can take the
    path of long-term gain by refactoring my design to match the conceptual
    model.
</p>

<blockquote class="digression">
    <h4>Example</h4>
    <p>
        Suppose I have a Person and need to tell the SnailMailer to send him
        mail. The SnailMailer, as currently designed, takes a street, a
        zip_code, etc. I could pull the data out of the address fields, like
        person.address.zip_code, then pass them to the SnailMailer. But in
        doing that, I would violate the Person abstraction.
    </p>

    <p>
        Instead, I should have stepped back and thought about the contract of
        the SnailMailer. It would be better to pass in the Person's Address
        instead of its components. That way, I rely only on the Person
        abstraction (it has an Address) and the SnailMailer abstraction (it
        sends to addresses). I remove my dependency on the structure of a
        Person's Address (street, zip, etc.) and I remove my dependency on the
        SnailMailer's expectations about address fields (street, zip, etc.)
        The SnailMailer can decide how to deal with those.
    </p>
</blockquote>

<p>
    This is sort of a restatement of the Law of Demeter, which is sort of a
    restatement of part of the principle of coupling. These are symmetric with
    the definition side of abstraction in a pleasing way:
</p>

<ul>
    <li>My abstraction vs. your use of it;</li>
    <li>Single Responsibility Principle vs. Law of Demeter;</li>
    <li>Cohesion vs. Coupling.</li>
</ul>

<p>
    Most of the design principles we talk about regularly, like those listed
    above, are syntactic &ndash; they are properties of the text of the code.
    But syntax is only a means; the thing that really matters is that the
    semantic model of the code mirror the semantic model in our brains.
    Thinking about (or being preached to about) the design principles in
    isolation can make them feel arbitrary; it's much better to view them in
    the light of abstraction integrity.
</p>

<p>
    Abstraction is important! The result of programming isn't simply a
    computation; it's also a set of ideas made concrete in a programming
    language. Nothing can beat the long-term business value of ideas expressed
    clearly in code.
</p>


]]></description>
   <category domain="http://blog.extracheese.org">/2009/12</category>
   <pubDate>Wed, 16 Dec 2009 21:10 GMT</pubDate>
</item>
</channel>
</rss>
