<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Object Mentor Blog: Category Uncle Bob's Blatherings</title>
    <link>http://blog.objectmentor.com/articles/category/uncle-bobs-blatherings</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Software Calculus - The Missing Abstraction.</title>
      <description>&lt;p&gt;The problem of infinity plagued mathematicians for millennia.  Consider Xeno&amp;#8217;s paradox; the one with Achilles and the tortoise.  While it was intuitively clear that Achilles would pass the Tortoise quickly, the algebra and logic of the day seemed to suggest that the Tortoise would win every race given a head start. &lt;em&gt;Every time&lt;/em&gt; Achilles got to where the tortoise was, the tortoise would have moved on.  The ancients had no way to see that an infinite sum could be finite.&lt;/p&gt;


	&lt;p&gt;Then came Leibnitz and everything changed.  Suddenly infinity was tractable.  Suddenly you could sum infinite series and write the equations that showed Achilles passing the tortoise.  Suddenly a whole range of calculations that had either been impossible or intractable became trivial.&lt;/p&gt;


	&lt;p&gt;Calculus was a watershed invention for mathematics.  It opened up vistas that we have yet to fully plumb.  It made possible things like Newtonian mechanics, Maxwell&amp;#8217;s equations, special and general relativity and quantum mechanics.  It supports the entire framework of our modern world.  We need a watershed like that for software.&lt;/p&gt;


	&lt;p&gt;If you listen to my keynote: &lt;a href="http://en.oreilly.com/rails2010/public/schedule/detail/14134"&gt;Twenty-Five Zeros&lt;/a&gt; you&amp;#8217;ll hear me go on and on about how even though software has changed a lot in form over the last fifty years, it has changed little in substance.  Software is still the organization of sequence, selection, and iteration.&lt;/p&gt;


	&lt;p&gt;For fifty years we have been inventing new languages, notations, and formulations to manage Sequence, Selection, and Iteration (SSI).  Structured Programming is simply a way to organize &lt;span class="caps"&gt;SSI&lt;/span&gt;.  Objects are another way to organize &lt;span class="caps"&gt;SSI&lt;/span&gt;.  Functional is still another.  Indeed, almost all of our software technologies are just different ways of organizing Sequence, Selection, and Iteration.&lt;/p&gt;


	&lt;p&gt;This is similar to Algebra in the days before calculus.  We knew how to solve linear and polynomial equations.  We knew how to complete squares and find roots.  But in the end it was all just different ways to organize adding.  That may sound simplistic, but it&amp;#8217;s not.  Subtracting is just adding in reverse.  Multiplying is just adding repeatedly.  Division is just multiplication in reverse.  In short, Algebra is an organizational strategy for adding.&lt;/p&gt;


	&lt;p&gt;Algebra went through many different languages and notations too, just like software has.  Think about Roman and Greek numerals.  Think how long it took to invent the concept of zero, or the positional exponential notation we use today.&lt;/p&gt;


	&lt;p&gt;And then one day Newton saw an apple fall, and he changed the way we &lt;em&gt;thought&lt;/em&gt; about mathematics.  Suddenly it wasn&amp;#8217;t about adding anymore.  Suddenly it was about infinities and differentials. Mathematical reasoning was raised to a new order of abstraction.&lt;/p&gt;


	&lt;p&gt;Where is that apple for software (pun intended).  Where is the Newton or Leibnitz that will transform everything about the way we &lt;em&gt;think&lt;/em&gt; about software.  Where is that long-sought new level of abstraction?&lt;/p&gt;


	&lt;p&gt;For awhile we thought it would be &lt;span class="caps"&gt;MDA&lt;/span&gt;.  Bzzzzt, wrong.  We thought it would be logic programming like prolog&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;.  Bzzzt.   We thought it would be database scripts and 4GLs.  Bzzzt.  None of those did it.  None of those can do it.  They are still just various ways of organizing sequence, selection, and iteration.&lt;/p&gt;


	&lt;p&gt;Some people have set their sights on quantum computing.  While I&amp;#8217;ll grant you that computations with bits that can be both states simultaneously is &lt;em&gt;interesting&lt;/em&gt;, in the end I think this is just another hardware trick to increase throughput as opposed to a whole new way to think about software.&lt;/p&gt;


	&lt;p&gt;This software transformation, whatever it is, is coming.  It must come; because we simply cannot keep piling complexity upon complexity.   We need some new organizing principle that revamps the very foundations of the way we think about software and opens up vistas that will take us into the 22nd century.&lt;/p&gt;


	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt;  Prolog comes closest to being something more than a simple reorganization of sequence, selection, and iteration.  At first look logic programming seems very different.  In the end, however, an algorithm expressed in prolog can be translated into any of the other languages, demonstrating the eventual equivalence.&lt;/p&gt;</description>
      <pubDate>Mon, 05 Jul 2010 20:26:15 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:4780351e-b2f2-4152-b4ef-0691cab0ff92</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/07/05/software-calculus-the-missing-abstraction</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>TDD in Clojure</title>
      <description>&lt;p&gt;OO is a tell-don&amp;#8217;t-ask paradigm.  Yes, I know people don&amp;#8217;t always use it that way, but one of Kay&amp;#8217;s original concepts was that objects were like cells in a living creature.  The cells in a living creature do not ask any questions.  They simply tell each other what to do.  Neurons are tellers, not askers.  Hormones are tellers not askers.  In biological systems, (and in Kay&amp;#8217;s original concept for OO) communication was half-duplex.&lt;/p&gt;


	&lt;p&gt;Clojure is a functional language.  Functional languages are ask-dont-tell.  Indeed, the whole notion of &amp;#8220;tell&amp;#8221; is to change the state of the system.  In a functional program there is no state to change.  So &amp;#8220;telling&amp;#8221; makes little sense.&lt;/p&gt;


	&lt;p&gt;When we use &lt;span class="caps"&gt;TDD&lt;/span&gt; to develop a tell-don&amp;#8217;t-ask system, we start at the high level and write tests using mocks to make sure we are issuing the correct &amp;#8220;tells&amp;#8221;.  We proceed from the top of the system to the bottom of the system.  The last tests we write are for the utilities at the very bottom.&lt;/p&gt;


	&lt;p&gt;In an ask-don&amp;#8217;t-tell system, data starts at the bottom and flows upwards.  The operation of each function depends on the data fed to it by the lower level functions.  There is no mocking framework.  So we write tests that start at the bottom, and we work our way up the the top.&lt;/p&gt;


	&lt;p&gt;Therein lies the rub.&lt;/p&gt;


	&lt;p&gt;In a tell-don&amp;#8217;t-ask system, the tells at the high level are relatively complex.  They branch out into lower subsystems getting simpler, but more numerous as they descend.  Testing these tells using mocks is not particularly difficult because we don&amp;#8217;t need to depend on the lower level functions being there.  The mocks make them irrelevant.&lt;/p&gt;


	&lt;p&gt;In an ask-don&amp;#8217;t-tell system the asks at the low level are simple, but as the data moves upwards it gets grouped and composed into lists, maps, sets, and other complex data structures.  At the top the data is in it&amp;#8217;s most complex form.  Writing tests against that complex data is difficult at best.  And there is currently no way to mock out the lower levels&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; so all tests written at the high level depend on all the functions below.&lt;/p&gt;


	&lt;p&gt;The perception of writing tests from the bottom to the top can be horrific at first.  Consider, for example, the &lt;a href="http://github.com/unclebob/clojureOrbit"&gt;Orbit program&lt;/a&gt; I just wrote.  This program simulates N-body gravitation.  Imagine that I am writing tests at the top level.  I have three bodies at position Pa, Pb, and Pc.  They have masses Ma, Mb, and Mc.  They have velocity vectors of Va, Vb, Vc.  The test I want to write needs to make sure that new positions Pa&amp;#8217;, Pb&amp;#8217;, Pc&amp;#8217;, and new Velocity vectors Va&amp;#8217;, Vb&amp;#8217;, and Vc&amp;#8217; are computed correctly.  How do I do that?&lt;/p&gt;


Should I write a test that looks like this?
&lt;pre&gt;
test-update {
  Pa = (1,1)
  Ma = 2
  Va = (0,0)

  Pb = (1,2)
  Mb = 3
  Vb = (0,0)

  Pc = (4,5)
  Mc = 4
  Vc = (0,0)

  update-all

  Pa should == (1.096, 4.128)
  Va should == (0.096, 3.128)

  Pb should == (1.1571348402636772, 0.1571348402636774)
  Vb should == (0.15713484026367727, -1.8428651597363226)

  Pc should == (3.834148869802242, 4.818148869802242)
  Vc should == (-0.16585113019775796, -0.18185113019775795)
}
&lt;/pre&gt;
A test like this is awful.  It&amp;#8217;s loaded with magic numbers, and secret information.  It tells me nothing about &lt;em&gt;how&lt;/em&gt; the update-all function is working.  It only tells me that it generated certain numbers.  Are those numbers correct?  How would I know?

	&lt;p&gt;But wait!  I&amp;#8217;m working in a &lt;em&gt;functional language&lt;/em&gt;.  That means that every function I call with certain inputs will &lt;em&gt;always&lt;/em&gt; return the same value; no matter how many times I call it.  Functions don&amp;#8217;t change state!  And that means that I can write my tests quite differently.&lt;/p&gt;


	&lt;p&gt;How does update-all work?  Simple, given a list of objects it performs the following operations (written statefully):&lt;/p&gt;


&lt;pre&gt;
  update-all(objects) {
    for each object in objects {
      accumulate-forces(object, objects)
    }
    for each object in objects {
      accelerate(object)
      reposition(object)
    }
  }
&lt;/pre&gt; 

	&lt;p&gt;This is written in stateful form to make is easier for our non-functional friends to follow.  First we accumulate the force of gravity between all the objects.  This amounts to evaluating Newton&amp;#8217;s F=Gm1m1/r^2 formula for each pair of objects, and adding up the force vectors.&lt;/p&gt;


	&lt;p&gt;Then, for each object we accelerate that object by applying the force vector to it&amp;#8217;s mass, and adding the resultant delta-v vector to it&amp;#8217;s velocity vector.&lt;/p&gt;


	&lt;p&gt;Then, for each object we reposition that object by applying the velocity vector to it&amp;#8217;s current position.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s the clojure code for update-all&lt;/p&gt;


&lt;pre&gt;
(defn update-all [os]
  (reposition-all (accelerate-all (calculate-forces-on-all os))))
&lt;/pre&gt;

	&lt;p&gt;In this code you can clearly see the bottom-to-top flow of the application.  First we calculate forces, then we accelerate, and finally we reposition.&lt;/p&gt;


	&lt;p&gt;Now, what do these -all functions look like?  Here they are:&lt;/p&gt;


&lt;pre&gt;
(defn calculate-forces-on-all [os]
  (map #(accumulate-forces % os) os))

(defn accelerate-all [os]
  (map accelerate os))

(defn reposition-all [os]
  (map reposition os))
&lt;/pre&gt;

	&lt;p&gt;If you don&amp;#8217;t read clojure, don&amp;#8217;t worry.  the map function simply creates a new list from an old list by applying a function to each element of the old list.  So in the case of reposition-all it simply calls reposition on the list of objects (os) producing a new list of objects that have been repositioned.&lt;/p&gt;


	&lt;p&gt;From this we can determine that the function of update-all is to call the three functions (accumulate-forces, accelerate, and reposition) on each element of the input list, producing a new list.&lt;/p&gt;


	&lt;p&gt;Notice how similar that is to a statement we might make about a high level method in an OO program.  (It&amp;#8217;s got to call these three functions on each element of the list).  In an OO language we would mock out the three functions and just make sure they&amp;#8217;d been called for each element.  The calculations would be bypassed as irrelevant.&lt;/p&gt;


	&lt;p&gt;Oddly, we can make the same statement in clojure.  Here&amp;#8217;s the test for update-all&lt;/p&gt;


&lt;pre&gt;
(testing "update-all" 
  (let [
    o1 (make-object ...)
    o2 (make-object ...)
    o3 (make-object ...)
    os [o1 o2 o3]
    us (update-all os)
    ]
    (is (= (nth us 0) (reposition (accelerate (accumulate-forces os o1)
    (is (= (nth us 1) (reposition (accelerate (accumulate-forces os o2)
    (is (= (nth us 2) (reposition (accelerate (accumulate-forces os o3)
    )
  )
&lt;/pre&gt;  

	&lt;p&gt;If you don&amp;#8217;t read clojure don&amp;#8217;t worry.  All this is saying is that we test the update-all function by calling the appropriate functions for each input object, and then see if the elements in the output list match them.&lt;/p&gt;


	&lt;p&gt;In an OO program we&amp;#8217;d find this dangerous because of side-effects.  We couldn&amp;#8217;t be sure that the functions could safely be called without changing the state of some object in the system.  But in a functional language it doesn&amp;#8217;t matter how many times you call a function.  So long as you pass in the same data, you will get the same result.&lt;/p&gt;


	&lt;p&gt;So this test simply checks that the appropriate three functions are getting called on each element of the list.  This is exactly the same thing an OO programmer would do with a mock object!&lt;/p&gt;


	&lt;h3&gt;Is &lt;span class="caps"&gt;TDD&lt;/span&gt; necessary in Clojure?&lt;/h3&gt;


	&lt;p&gt;If you follow the code in the Orbit example, you&amp;#8217;ll note that I wrote tests for all the computations, but did not write tests for the Swing-Gui.  This is typical of the way that I work.  I try to test all business rules, but I &amp;#8220;fiddle&amp;#8221; with the &lt;span class="caps"&gt;GUI&lt;/span&gt; until I like it.&lt;/p&gt;


	&lt;p&gt;If you look carefully you&amp;#8217;ll find that amidst the &lt;span class="caps"&gt;GUI&lt;/span&gt; functions there are some &amp;#8220;presentation&amp;#8221; functions that &lt;em&gt;could&lt;/em&gt; have been tested, but that I neglected to write with &lt;span class="caps"&gt;TDD&lt;/span&gt;[2].  These functions were the worst to get working.  I continuously encountered NPEs and Illegal Cast exceptions while trying to get them to work.&lt;/p&gt;


	&lt;p&gt;My conclusion is that Clojure without &lt;span class="caps"&gt;TDD&lt;/span&gt; is just as much a nightmare as Java or Ruby without &lt;span class="caps"&gt;TDD&lt;/span&gt;.&lt;/p&gt;


	&lt;h3&gt;Summary&lt;/h3&gt;


	&lt;p&gt;In OO we tend to &lt;span class="caps"&gt;TDD&lt;/span&gt; our way from the top to the bottom by using Mocks.  In Clojure we tend to &lt;span class="caps"&gt;TDD&lt;/span&gt; our way from the bottom to the top.  In either case we can compose our tests in terms of the functions they should call on the lower level objects.  In the case of OO we use mocks to tell us if the functions have been called properly.  This protects us from side-effects and allows us to decouple our tests from the whole system.  In clojure we can rely on the fact that the language is functional, and that no matter how many times you call a function it will return the same value.&lt;/p&gt;


	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Brian Marick is working on something that looks a lot like a mocking framework for clojure.  If his ideas pan out, we may be able to &lt;span class="caps"&gt;TDD&lt;/span&gt; from the top to the bottom in Clojure.&lt;/p&gt;


	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; This is an unconscious game we all play with ourselves.  When we have a segment of code that we consider to be immune to &lt;span class="caps"&gt;TDD&lt;/span&gt; (like &lt;span class="caps"&gt;GUI&lt;/span&gt;) then we unconsciously move lots of otherwise testable code into that segment.  Yes, I heard my green band complain every time I did it; but I ignored it because I was in the &lt;span class="caps"&gt;GUI&lt;/span&gt;.  Whoops.&lt;/p&gt;</description>
      <pubDate>Thu, 03 Jun 2010 12:33:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:496c0f47-16d5-480d-9530-125b7ee235d8</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/06/03/tdd-in-clojure</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Orbit in Clojure</title>
      <description>&lt;p&gt;I spent the last two days (in between the usual BS) writing a simple orbital simulator in Clojure using Java interop with Swing.  This was a very pleasant experience, and I like the way the code turned out &amp;#8211; even the swing code!&lt;/p&gt;


	&lt;p&gt;You can see the source code &lt;a href="http://github.com/unclebob/clojureOrbit"&gt;here&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Those of you who are experienced with Clojure, I&amp;#8217;d like your opinion on my use of namespaces and modules and other issues of style.&lt;/p&gt;


	&lt;p&gt;Those of you who are not experienced with Clojure, should start.  You might want to use this application as a tutorial.&lt;/p&gt;


	&lt;p&gt;And just have fun watching the simulation of the coalescence of an accretion disk around a newly formed star.&lt;/p&gt;</description>
      <pubDate>Wed, 02 Jun 2010 17:08:56 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:6e0975f7-8396-4428-90d5-1500c373c64a</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/06/02/orbit-in-clojure</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Clojure Prime Factors</title>
      <description>&lt;p&gt;Can anyone create a simpler version of prime factors in Clojure?&lt;/p&gt;


&lt;pre&gt;
(ns primeFactors)

(defn of
  ([n]
    (of [] n 2))
  ([factors n candidate]
    (cond
      (= n 1) factors
      (= 0 (rem n candidate)) (recur (conj factors candidate) (quot n candidate) candidate)
      (&amp;gt; candidate (Math/sqrt n)) (conj factors n)
      :else (recur factors n (inc candidate))
      )
    )
  )
&lt;/pre&gt;</description>
      <pubDate>Sat, 15 May 2010 19:09:59 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:dc11f22c-be2f-4173-b06e-1f6926e7c70c</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/05/15/clojure-prime-factors</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Sufficient Design means Damned Good Design.</title>
      <description>&lt;p&gt;@JoshuaKerievsky wrote a &lt;a href="https://elearning.industriallogic.com/gh/submit?Action=PageAction&amp;#38;album=blog2009&amp;#38;path=blog2009/2010/sufficientDesign&amp;#38;devLanguage=Java"&gt;blog&lt;/a&gt; entitled &amp;#8220;Sufficient Design&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;Josh makes this point:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&amp;#8216;Yet some programmers argue that the software design quality of every last piece of code ought to be as high as possible. &amp;#8220;Produce clean code or you are not a software craftsman!&amp;#8221;&amp;#8217;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;He goes on to say:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&amp;#8220;Yet ultimately the craftsmanship advice fails to consider simple economics: If you take the time to craft code of little or moderate value to users, you&amp;#8217;re wasting time and money.&amp;#8221;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Now this sounds like heresy, and I can imagine that software craftsmanship supporters (like me) are ready to storm the halls of Industrial Logic and string the blighter up by his toenails!&lt;/p&gt;


	&lt;p&gt;But hold on there craftsmen, don&amp;#8217;t get the pitchforks out yet. Look at the scenario that Josh describes.  It&amp;#8217;s quite revealing.&lt;/p&gt;


	&lt;p&gt;Josh&amp;#8217;s example of &amp;#8220;not being a craftsman&amp;#8221; is his niggling worry over a function that returns a string but in one derivative case ought to return a void.&lt;/p&gt;


	&lt;p&gt;Horrors!  Horrors!  He left a bit of evolved cruft in the design!  Revoke his craftsman license and sick the dogs on him!&lt;/p&gt;


	&lt;p&gt;Ah, but wait.  He also says that he spent a half-day trying to refactor this into a better shape but eventually had to give up.&lt;/p&gt;


	&lt;p&gt;The fool!  The nincompoop!  The anti-craftsman!  A pox on him and all his ilk!&lt;/p&gt;


&lt;hr&gt;

	&lt;p&gt;OK, enough hyperbole.  It seems to me that Josh was behaving exactly as a craftsman should.  He was worrying about exactly the kinds of things a craftsman ought to worry about.  He was making the kinds of pragmatic decisions a craftsman ought to make.  He was not leaving a huge mess in the system and rushing on to the next feature to implement.  Instead he was taking care of his code.  The fact that he put so much energy, time, and thought into such a small issue as an inconsistent return type speaks volumes for Josh&amp;#8217;s integrity as a software craftsman.&lt;/p&gt;


	&lt;p&gt;So, as far as Josh Kerievsky is concerned &amp;#8220;Sufficient Design&amp;#8221; is &amp;#8220;Pretty Damned Good Design&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;Look, all our software will have little tiny warts.  There&amp;#8217;s no such thing as a perfect system.  Craftsmen like Josh work hard to keep those warts as small as possible, and to sequester them into parts of the system where they can do the least harm.&lt;/p&gt;


	&lt;p&gt;So the only aspect of Josh&amp;#8217;s post that I disagree with is his contention that the &amp;#8220;craftsman&amp;#8221; message is one of unrelenting perfection.  Craftsmen are first and foremost pragmatists.  They seek very high quality code; but they are not so consumed with perfection that they make foolish economic tradeoffs.&lt;/p&gt;</description>
      <pubDate>Wed, 28 Apr 2010 18:02:10 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:7af1f4ce-c8d6-40c7-aa72-57d9c40f32be</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/04/28/sufficient-design-means-damned-good-design</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
    </item>
    <item>
      <title>Certification:  Don't Waste Your Time!</title>
      <description>&lt;p&gt;As I have said before, there&amp;#8217;s nothing particularly wrong with the current mania for certification.  If you want to be certified at the cost of a 2-day course, by all means get certified.  If you want to certify people for attending your 2-day course, by all means hold the course and hand out the certificates.  It&amp;#8217;s all good.  Make money!  Be fruitful and multiply!&lt;/p&gt;


	&lt;p&gt;But be careful not to waste your time.&lt;/p&gt;


	&lt;p&gt;How could certification be a waste of time?  That depends on your motive.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;If you are getting certified in order to impress someone, like a hiring manager, or a recruiter, or your peers, &lt;em&gt;you are wasting your time.&lt;/em&gt;  Nobody worth impressing is going to find this certification impressive.  Indeed, the people you &lt;em&gt;really&lt;/em&gt; want to impress are likely to find it a bit mundane.  &lt;/li&gt;
		&lt;li&gt;If you are getting certified in order to get hired, &lt;em&gt;you are wasting your time&lt;/em&gt;.  Nobody is going to hire you simply because of that &amp;#8220;C&amp;#8221;, and nobody worth working for is going to require that &amp;#8220;C&amp;#8221;. &lt;/li&gt;
		&lt;li&gt;If you have decided to hire only &lt;em&gt;certified&lt;/em&gt; people, &lt;em&gt;you are wasting your time&lt;/em&gt;.  The population of certified people is not richer in talent, skill, or knowledge.  Indeed, it may be poorer.  Remember, those who have talent don&amp;#8217;t &lt;em&gt;need&lt;/em&gt; certification as much as those who don&amp;#8217;t.&lt;/li&gt;
	&lt;/ul&gt;


&lt;p/&gt;
&lt;br/&gt;

	&lt;p&gt;What part of certification is &lt;em&gt;not&lt;/em&gt; a waste of time?&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;The primary benefit you are getting is the instruction; but be careful: There are lots of pretty mediocre instructors out there.  Some of the instructors teach pretty good courses, but others are just hoping that all you care about is the certification.  &lt;/li&gt;
		&lt;li&gt;So do a little research and find the best instructors.  You may, in fact, find that some of the best instructors and courses do not offer certification.  That shouldn&amp;#8217;t stop you from considering them.&lt;/li&gt;
	&lt;/ul&gt;


&lt;p/&gt;
&lt;br/&gt;
But wait, aren&amp;#8217;t the instructors certified as trainers?

	&lt;ul&gt;
	&lt;li&gt;Sure.  They paid the money and took the course to become a certified trainer.  &lt;/li&gt;
		&lt;li&gt;But that doesn&amp;#8217;t necessarily mean that they:
	&lt;ul&gt;
	&lt;li&gt;are a good instructor.&lt;/li&gt;
		&lt;li&gt;know what they are teaching.&lt;/li&gt;
		&lt;li&gt;have done what they are teaching.&lt;/li&gt;
		&lt;li&gt;are qualified to teach &lt;em&gt;you&lt;/em&gt;.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


&lt;p/&gt;
&lt;br/&gt;
OK, but isn&amp;#8217;t there &lt;em&gt;some&lt;/em&gt; benefit to the certification itself?  

	&lt;ul&gt;
	&lt;li&gt;Sure.  A nice piece of paper.&lt;/li&gt;
	&lt;/ul&gt;</description>
      <pubDate>Tue, 27 Apr 2010 15:11:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0bd59c14-765c-48d4-9a9f-537c09e56da7</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/04/27/certification-dont-waste-your-time</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>The Tricky Bit</title>
      <description>&lt;p&gt;I once heard a story about the early days of the Concorde.  A british MP was on board for a demonstration flight.  As the jet went supersonic he disappointedly commented to one of the designers that it didn&amp;#8217;t feel any different at all.  The designer beamed and said: &amp;#8220;Yes, &lt;em&gt;that&lt;/em&gt; was the tricky bit.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;I wonder if the MP would have been happier if the plane had begun to vibrate and shake and make terrifying noises.&lt;/p&gt;


	&lt;p&gt;While at #openvolcano10, Gojko Adzic and Steve Freeman told the story of a company in which one team, among many, had gone agile.  Over time that team managed to get into a nice rhythm, passing it&amp;#8217;s continuous builds, adding lots of business value, working normal hours, and keeping their customers happy.  Meanwhile other teams at this company were facing delays, defects, frustrated customers, and lots of overtime.&lt;/p&gt;


	&lt;p&gt;The managers at this company looked at the agile team, working like a well-oiled machine, and looked at all the other teams toiling in vain at the bilge pump, and came to the conclusion that the project that the agile team was working on was too simple to keep them busy.  That the other teams&amp;#8217; projects were far more difficult.  It didn&amp;#8217;t even occur to them that the agile team had figured out the tricky bit.&lt;/p&gt;</description>
      <pubDate>Fri, 23 Apr 2010 04:28:35 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:51763c35-d308-49f1-8291-7aa690e33425</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/04/23/the-tricky-bit</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Agile Methods</category>
    </item>
    <item>
      <title>The R.E.A.L.I.T.Y. principles of Agile Software Certification.</title>
      <description>&lt;p&gt;As you are probably aware the Scrum Alliance is planning to offer a &lt;em&gt;Certified Scrum Developer&lt;/em&gt; program.  You can read about it &lt;a href="http://www.scrumalliance.org/CSD"&gt;here&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Interestingly enough Microsoft, in collaboration with Ken Schwaber, is offering a &lt;em&gt;Professional Scrum Developer&lt;/em&gt; program.  You can read about that &lt;a href="http://www.scrum.org/newsandupdates/tag/certified-scrum-developer"&gt;here&lt;/a&gt; (look carefully at the url).&lt;/p&gt;


	&lt;p&gt;The scrum alliance program seems to be about agile skills.  The Microsoft program seems to be about Visual Studio.  So all is right with the world.&lt;/p&gt;


	&lt;p&gt;Is there anything wrong with this?  Is this somehow immoral or &lt;em&gt;bad&lt;/em&gt;?  Not at all.  This is just people doing what people do: Selling services and making money.  I&amp;#8217;m all for it.  I expect the courses to be of a quality that you&amp;#8217;d expect from professionals; and I&amp;#8217;m sure that students will learn useful information.  Indeed, from time to time, even I have offered &lt;span class="caps"&gt;CSM&lt;/span&gt; courses taught by people I trust and respect.&lt;/p&gt;


	&lt;p&gt;There are, however, some claims that need to be dealt with.  The most important is that these programs &lt;em&gt;shorten&lt;/em&gt; the recruiting process.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve been thinking about offering a &lt;em&gt;Certified Recruiter for Agile Professionals&lt;/em&gt; course.  This fifty-two week course will teach, and reteach, a number of principles of Agile Software Certification.  I call this repertoire of principles: R.E.A.L.I.T.Y.&lt;/p&gt;


	&lt;p&gt;The first principle is the &lt;em&gt;Redaction of Certification Principle&lt;/em&gt; (RCP).  The principle states:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;em&gt;Certifications generally certify nothing whatever about experience, knowledge, or skill.  Generally they certify that the certificate holder has attended (or at least paid to attend) a course.  Perhaps they took (and maybe even passed) an exam based on that course.&lt;/em&gt;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Based on this principle, any recruiter taking my &lt;em&gt;Certified Recruiter for Agile Professionals&lt;/em&gt; course will not be allowed to complete the course or receive their certification until they have taken the following oath.&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt; As a &lt;em&gt;Cerftified Recruiter for Agile Professionals&lt;/em&gt; I solemnly swear before Knuth and all here present:&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;That before I read a resume, I will find every use of the word &amp;#8220;certified&amp;#8221; on that document and redact it with whiteout.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;That if a candidate uses the word &amp;#8220;certified&amp;#8221; in an interview, I will ask the candidate to repeat him- or herself without using that word.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;That I will pay &lt;em&gt;no&lt;/em&gt; attention whatever to any implications of that word, nor will that word in any way influence my opinions regarding that candidate.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;This oath is an exemplar of the &lt;em&gt;Certification Nullification Principle&lt;/em&gt; (CNP), which is another of the R.E.A.L.I.T.Y. principles of common sense and moderately competent thinking.  The principle states:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;The word &amp;#8220;certified&amp;#8221;, when used in the context of Agile Software Development, is a filler word that has no bearing on anything salient or interesting about individuals, skills, knowledge, or anything else.  It is a marketing word similar to &amp;#8220;new&amp;#8221;, &amp;#8220;improved&amp;#8221;, &amp;#8220;natural&amp;#8221; and &amp;#8220;organic&amp;#8221;.  It can safely be removed from all documents and discussions without changing their meaning.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;This principle leads to the well known &lt;em&gt;Certification Uncertainty Principle&lt;/em&gt; (CUP), yet another of the R.E.A.L.I.T.Y. principles.  This principle states:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Any acronym that includes the letter &amp;#8216;C&amp;#8217; standing for the word &amp;#8220;Certification&amp;#8221; can be safely changed into a similar acronym that eliminates the letter &amp;#8216;C&amp;#8217; and puts a &amp;#8217;?&amp;#8217; at the end.  This transformation of the acronym vastly improves the meaning of the orginal.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;That last sentence probably requires some justification.  After all, extraordinary claims require extraordinary substantiation.  So lets try a few experiments:&lt;/p&gt;


&lt;pre&gt;
Statement                    Ac'nm   CUP  Resulting Statement 
---------------------------- -----   ---- ---------------------
Certified Scrum Master        CSM    SM?  Scrum Master?
Certified Scrum Developer     CSD    SD?  Scrum Developer?
Certified Scrum Trainer       CST    ST?  Scrum Trainer?
Certified Scrum Professional  CSP    SP?  Scrum Professional?
Certified Scrum Product Owner CSPO   SPO? Scrum Product Owner?
Certified Scrum Coach         CSC    SC?  Scrum Coach?       
&lt;/pre&gt;

	&lt;p&gt;As we can see, the meanings of the statements are indeed clarified. In my course the &lt;em&gt;Certified Recruiter for Agile Professionals&lt;/em&gt; is taught that the question mark is the most significant aspect of each of the resultant statements.&lt;/p&gt;


	&lt;p&gt;In recent weeks we have uncovered a potentially profound new principle which we may find necessary to include in the R.E.A.L.I.T.Y. repertoire.  This is the so-called &lt;em&gt;Scrum Exclusion Principle&lt;/em&gt; (SEP) which tentatively states:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Wherever the word &lt;span class="caps"&gt;SCRUM&lt;/span&gt; appears in any statement, or is represented within any acronym, it can be safely excluded without changing any meaning.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;The following table show just how profound the effects of this principle are:&lt;/p&gt;


&lt;pre&gt;
Statement                    Ac'nm   CUP  SEP   Resulting Statement 
---------------------------- -----   ---- ----  ---------------------
Certified Scrum Master        CSM    SM?  M?    Master?
Certified Scrum Developer     CSD    SD?  D?    Developer?
Certified Scrum Trainer       CST    ST?  T?    Trainer?
Certified Scrum Professional  CSP    SP?  P?    Professional?
Certified Scrum Product Owner CSPO   SPO? PO?   Product Owner?
Certified Scrum Coach         CSC    SC?  C?    Coach?       
&lt;/pre&gt;

	&lt;p&gt;We are not yet willing to say that these transformation are a reliable feature of nature.  We can only say that, at this point, there are very troubling implications that support it.&lt;/p&gt;


	&lt;p&gt;Our final advice to &lt;em&gt;Certified Recruiters for Agile Professionals&lt;/em&gt; is based on one final principle: The &lt;em&gt;Smoke and Mirrors&lt;/em&gt; principle, (SAM) which states:&lt;/p&gt;


	&lt;p&gt;Well&amp;#8230;  You know what it states.&lt;/p&gt;</description>
      <pubDate>Wed, 21 Apr 2010 05:29:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:9ebfb589-8dc1-482f-a1bc-b170e3605e75</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/04/21/the-r-e-a-l-i-t-y-principles-of-agile-software-certification</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>The Mayans are Coming!</title>
      <description>&lt;p&gt;This one is just a quickie; too long for a tweet.&lt;/p&gt;


	&lt;p&gt;I gave a lightning keynote (actually a key-rant) today at #accu2010.  It was about a bet between John Lakos and Kevlin Henney.  Kevlin &amp;#8220;won&amp;#8221; the bet last night by showing that he could get a C++ program to behave in a way that John said couldn&amp;#8217;t be done.  My rant was about how both of them were wrong (not technically, but morally) and so they both owed &lt;em&gt;me&lt;/em&gt; the sum of the bet.  (I&amp;#8217;m always happy to insert myself into any available revenue stream.)&lt;/p&gt;


	&lt;p&gt;The problem they had coded, and for which I presented a &lt;em&gt;far superior&lt;/em&gt; solution in Clojure, was that old work-horse of prob/stat: &amp;#8220;What&amp;#8217;s the probability that out of N people in a room two will have the same birthday?&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Now, just to show you how strange James Bach is (and why his strangeness is in some bizarre way actually valuable); once my talk was done, James got up and said &amp;#8220;What if some of the people in the room are ancient Mayans who use a completely different kind of calendar making it impossible to compare their birthdays?&amp;#8221;&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve long said that testers were deviant souls with twisted minds that delight in reducing helpless software systems into piles of smoking slag.  I believe James may be the exemplar.&lt;/p&gt;</description>
      <pubDate>Sat, 17 Apr 2010 11:22:59 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:edce528f-1582-4928-b139-3d3393c0e5ae</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/04/17/the-mayans-are-coming</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Sapient Testing: The &amp;quot;Professionalism&amp;quot; meme.</title>
      <description>&lt;p&gt;James Bach gave a stirring keynote today at &lt;span class="caps"&gt;ACCU 2010&lt;/span&gt;.  He described a vision of testing that our industry sorely needs.  Towit: Testing requires sapience.&lt;/p&gt;


	&lt;p&gt;Testing, according to Bach, is not about assuring conformance to requirements; rather it is about &lt;em&gt;understanding&lt;/em&gt; the requirements.  Even that&amp;#8217;s not quite right.  It is not sufficient to simply understand and verify the requirements.  A good tester uses the behavior of the system and the descriptions in the requirements, (and face-to-face interaction with the authors of both) to &lt;em&gt;understand the motivation behind the system&lt;/em&gt;.  Ultimately it is the tester&amp;#8217;s job to divine the system that the customer &lt;em&gt;imagined&lt;/em&gt;; and then to illuminate those parts of the system that are not consistent with that imagination.&lt;/p&gt;


	&lt;p&gt;It seems to me that James is attempting to define &amp;#8220;professionalism&amp;#8221; as it applies to testing.  A professional tester does not blindly follow a test plan.  A professional tester does not simply write test plans that reflect the stated requirements.  Rather a professional tester takes responsibility for &lt;em&gt;interpreting&lt;/em&gt; the requirements with intelligence.  He tests, not only the system, but also (and more importantly) the assumptions of the programmers, and specifiers.&lt;/p&gt;


	&lt;p&gt;I like this view.  I like it a lot.  I like the fact that testers are seeking professionalism in the same way that developer are.  I like the fact that testing is becoming a &lt;em&gt;craft&lt;/em&gt;, and that people like James are passionate about that craft.  There may yet be hope for our industry!&lt;/p&gt;


	&lt;p&gt;There has been a long standing frission between James&amp;#8217; view of testing and the Agile emphasis on &lt;span class="caps"&gt;TDD&lt;/span&gt; and automated tests.  Agilists have been very focussed on creating suites of automated tests, and exposing the insanity (and inanity) of huge manual testing suites.  This focus can be (and has been) misinterpreted as an &lt;em&gt;anti-tester&lt;/em&gt; bias.&lt;/p&gt;


	&lt;p&gt;It seems to me that professional testers are completely compatible with agile development.  No, that&amp;#8217;s wrong.  I think professional testers are &lt;em&gt;utterly essential&lt;/em&gt; to agile development. I don&amp;#8217;t want testers who rotely execute brain-dead manual test plans.  I want testers &lt;em&gt;using their brains&lt;/em&gt;!  I want testers to be partners in the effort to create world-class, high-quality software.  As a professional developer I want &amp;#8211; I need &amp;#8211; professional testers helping me find my blind spots, illuminating the naivete of my assumptions, and partnering with me to satisfy the needs of our customers.&lt;/p&gt;</description>
      <pubDate>Thu, 15 Apr 2010 06:18:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:b9343975-d80a-4e70-86ef-41a3c95ec5fd</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/04/15/sapient-testing-the-professionalism-meme</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
      <category>Agile Methods</category>
    </item>
    <item>
      <title>20% more bugs?  Or 20% less features?</title>
      <description>&lt;p&gt;People often make the argument that time to market is more important that quality.  I&amp;#8217;m not sure just what they mean by that.  Do they mean that it&amp;#8217;s ok if 20% of the features don&amp;#8217;t work so long as they deliver quickly?  If so, that&amp;#8217;s just stupid.  Why not develop 20% fewer features, and develop them well.  It seems to me that &lt;em&gt;choosing&lt;/em&gt; which 20% you are not going to develop and then &lt;em&gt;choosing&lt;/em&gt; to develop the other 80% to a high standard of quality is a better management decision than telling the developers to work sloppily.&lt;/p&gt;</description>
      <pubDate>Tue, 06 Apr 2010 22:03:23 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:9282cb2f-5432-45d6-a819-1df5fde99b61</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/04/06/20-more-bugs-or-20-less-features</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Developer Certification WTF?</title>
      <description>&lt;p&gt;Watch the following video.  It will convince you that we have to do &lt;em&gt;something&lt;/em&gt; about the horrible state of software engineering.&lt;/p&gt;


&lt;object width="400" height="300"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=9981123&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=9981123&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;p&gt;&lt;a href="http://vimeo.com/9981123"&gt;Bad Code&lt;/a&gt; from &lt;a href="http://vimeo.com/user947916"&gt;unclebob&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;

	&lt;p&gt;How could any team of disciplined professionals have produced a wretched mess like that?  Clearly they were ignorant of good practices. Clearly they were inexperienced novices.  Clearly their priorities and values were all wrong.  If only they had been taught good coding practices, and good development skills.  If only we could have gotten to them before they made such a horrible mess.&lt;/p&gt;


	&lt;p&gt;What we need to do is create a &lt;em&gt;certification program&lt;/em&gt; that provides developers with the knowledge and skills that they need.  This program will involve a course that teaches good development practice, and a &lt;em&gt;certification&lt;/em&gt; that they are now knowledgeable developers.  They can use that certification to prove to their employers and their fellow professionals that they are worthy of being considered true and clean software developers.&lt;/p&gt;


	&lt;p&gt;That&amp;#8217;s what we need.  Right?....&lt;/p&gt;


	&lt;h1&gt;&lt;strong&gt;Eagle&amp;#8217;s Entrails!  Deer Droppings!  and Elephant Phlatulence!&lt;/strong&gt;&lt;/h1&gt;


	&lt;p&gt;I&amp;#8217;m sorry, am I being vague?  Is my opinion not clear enough?  All right then, allow me to elaborate.&lt;/p&gt;


	&lt;h2&gt;What Problem does Certification solve?&lt;/h2&gt;


	&lt;p&gt;Certainly there are certification organizations who have the problem of dwindling revenues.  A new developer certification program would likely solve &lt;em&gt;their&lt;/em&gt; problem.&lt;/p&gt;


	&lt;p&gt;And just as certainly there are tin-men who need hearts, lions who need courage, scarecrows who need brains, and developers who need self-esteem. A new developer certification program might just help those lackluster developers.&lt;/p&gt;


	&lt;p&gt;But who else is served by a developer certification program?  Employers?&lt;/p&gt;


	&lt;h2&gt;The Trials of Hercules.&lt;/h2&gt;


	&lt;p&gt;Consider Doctors and Lawyers.  When a medical student earns an M.D., or a law student passes the Bar, that&amp;#8217;s an &lt;em&gt;achievement&lt;/em&gt;.  The certification, in those cases is deeply meaningful because the certification is &lt;em&gt;not easily won&lt;/em&gt;.  To get it you have to spend many years, and many tens of thousands of dollars.  What&amp;#8217;s more, you have to acquire in-depth knowledge and at least a modicum of provable skill.  You have to do something &lt;em&gt;significant&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;If we had a developer certification like &lt;em&gt;that&lt;/em&gt;, then employers might find it useful.  But I know of no developer certification program (except for one that I&amp;#8217;ll mention later) that offers proof that the developer has accomplished anything of significance.  Most certification programs prove little more than that the &amp;#8220;developer&amp;#8221; paid to attend a 3-5 day course.  As an employer, I&amp;#8217;m not particularly interested in the ability of a developer to pay to attend a 3-5 day course.  As an employer I want to know what the developer can &lt;em&gt;do&lt;/em&gt;.&lt;/p&gt;


	&lt;h2&gt;Michaelangelo&amp;#8217;s Apprentice.&lt;/h2&gt;


	&lt;p&gt;If you were hiring a guitarist for your band, you might be very impressed with someone who toured with Clapton.  You don&amp;#8217;t get to tour with Clapton unless you are talented.  But more than just talented, you have to show up every day, you have to work well with others, you have to be willing to get the job done under pressure.  Clapton doesn&amp;#8217;t work with slouches!&lt;/p&gt;


	&lt;p&gt;A signed letter of recommendation from &lt;em&gt;Clapton&lt;/em&gt; is a certification of &lt;em&gt;significance&lt;/em&gt;!  Not just anyone can get one of those.  That letter will impress potential employers forever after.&lt;/p&gt;


	&lt;p&gt;As an employer, I want to hire people who have succeeded at working with others in the past.  The more I trust those others, the better!  No developer certification program that I know of (except for one that I&amp;#8217;ll mention later) provides that kind of credible reference.&lt;/p&gt;


	&lt;h2&gt;Over-promise and Under-deliver.&lt;/h2&gt;


	&lt;p&gt;The certification programs that I know of (except for one that I&amp;#8217;ll mention later) make implicit promises that they can&amp;#8217;t hope to begin to deliver.  The implied promise is that the certificant has been shown to have some &lt;em&gt;significant&lt;/em&gt; skill, ability, or knowledge.  The reality is that you have to look at the word &amp;#8220;significant&amp;#8221; through the wrong end of some very powerful binoculars before it matches the truth.  Indeed, there are certification programs that show absolutely nothing about the certificant except that they bought a seat in a class.&lt;/p&gt;


	&lt;p&gt;Notice that I said that the promises were &lt;em&gt;implicit&lt;/em&gt;.  That&amp;#8217;s the whole key to making lightweight certifications profitable.  The goal is to imply that the benefits of certification are so huge that people will pay to get the certification.  Often that implication can be as simple and subtle as the choice of words used to &lt;em&gt;name&lt;/em&gt; the certification.&lt;/p&gt;


	&lt;p&gt;Consider, for example, the title of &amp;#8220;Certified Development Chief&amp;#8221; imprinted on the certificate of someone who just took a &amp;#8220;Development Chief&amp;#8221; course.  Who wouldn&amp;#8217;t want to be a &lt;em&gt;Certified&lt;/em&gt; Development Chief?  And if you aren&amp;#8217;t a &lt;em&gt;Certified&lt;/em&gt; Development Chief, then what kind of Development Chief are you?&lt;/p&gt;


	&lt;h2&gt;A course, a card, and a Bridge to sell.&lt;/h2&gt;


	&lt;p&gt;What significant accomplishment can a developer make by paying to attend (or even actually attending) an 3-5 day course?  How credible a recommendation about any of the 20-odd students could an instructor of such a course make?  I can answer both questions in two words, with apologies to &lt;span class="caps"&gt;SNL&lt;/span&gt;.  &amp;#8220;Jack&amp;#8221; and &amp;#8220;Cheese&amp;#8221;.  The accomplishment is miniscule, and the recommendation is meaningless.&lt;/p&gt;


	&lt;p&gt;So as an employer of developers I think you can take your course and card and show it to some other sucker.  It don&amp;#8217;t impress me much.  Go away and come back later when you&amp;#8217;ve accomplished the trials of Hercules and apprenticed under Michaelangelo.  And make sure you bring letters of reference.  &lt;span class="caps"&gt;NEXT&lt;/span&gt;!&lt;/p&gt;


	&lt;h2&gt;The one I said I&amp;#8217;d mention later.&lt;/h2&gt;


	&lt;p&gt;I&amp;#8217;ve got an idea for a certification program that just might work.  Now, bear with me because this is a little complicated.  It&amp;#8217;s an idea so revolutionary, so different, so incredibly &lt;em&gt;new&lt;/em&gt; that I&amp;#8217;m getting giddy just thinking about it.&lt;/p&gt;


	&lt;p&gt;What if we asked young graduates to actually get jobs as &amp;#8220;interns&amp;#8221; for awhile.  What if we gave out responsibility to them in small incremental measures.  What if they gradually learned more and more things while working for us.  What if we guided them to ever greater accomplishments.  What if we slowly gave them trials of Hercules to follows, and had them work with Michaelangelos.&lt;/p&gt;


	&lt;p&gt;Of course some of our people might leave and go to greener pastures.  We&amp;#8217;ll need to replace them.  Also, our company might succeed and grow, so we&amp;#8217;ll need to hire more good developers.  So what if we&amp;#8230;&lt;/p&gt;


	&lt;p&gt;OK, now hold on to your hat because this is where it gets really tricky.   You might want to get up and walk around a bit, get a diet coke, eat a twinkie, or something to get your brain working.&lt;/p&gt;


	&lt;p&gt;Ready?  OK, here we go&amp;#8230;&lt;/p&gt;


	&lt;p&gt;So what if we&amp;#8230; &lt;em&gt;interviewed&lt;/em&gt; ... candidate developers?  What if we asked them what accomplishments they&amp;#8217;d achieved in previous employment.  What if we asked them who they used to work with.  And&amp;#8230;  ok, this is even wilder   ...  what if we &lt;em&gt;called&lt;/em&gt; those references and checked them out?&lt;/p&gt;


	&lt;p&gt;Are you still with me?&lt;/p&gt;


	&lt;p&gt;What if we&amp;#8230;.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;Naaaaahhhhh.&lt;/em&gt;  Dumb idea.&lt;/p&gt;


	&lt;p&gt;Honestly, I think I&amp;#8217;ve wasted your time.  It&amp;#8217;s a stupid idea.  Never mind.  We should all just go get certified instead.&lt;/p&gt;</description>
      <pubDate>Sun, 07 Mar 2010 12:16:43 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:0867886b-db75-4f5a-a52c-c00ea09f6b89</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/03/07/developer-certification-wtf</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Software on the Cheap</title>
      <description>&lt;p&gt;When it comes to software, you get what you pay for.&lt;/p&gt;


	&lt;p&gt;Have you ever stopped to wonder how much a line of code costs?  
It ought to be easy to figure out.&lt;/p&gt;


	&lt;p&gt;In the last 14 months, I have written about 20KSLOC in FitNesse.  Of course that was part time.  My real job is running Object Mentor, consulting, teaching, mentoring, writing, and a whole load of other things.  Programming takes up perhaps 15% of my time.&lt;/p&gt;


	&lt;p&gt;On the other hand most programmers have lots of other things to do.  They go to meetings, and then they go to more meetings.  When they are done with those meetings, they go to meetings.  And then there are the meetings to go to.  Oh yeah, and then there&amp;#8217;s all the fiddling around with time accounting tools, and horrific source code control systems that perform like a salamander crawling through frozen mud.&lt;/p&gt;


	&lt;p&gt;So, maybe 15% isn&amp;#8217;t such a bad ratio.&lt;/p&gt;


	&lt;p&gt;The loaded rate (Salary plus everything else) for a typical programmer is on the order of $200K. (I know that sounds like a lot, but you can look it up.) So $200K / (20KSLOC / 14mo * 12mo) = $11.66/SLOC.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s look at one of those lines: &lt;code&gt;StringBuffer nameBuffer = new StringBuffer();&lt;/code&gt;
Does that look like $11.66 to you?  Would you pay that much for it?  Well, don&amp;#8217;t answer yet, because for each &lt;code&gt;StringBuffer&lt;/code&gt; line you buy, you get &lt;code&gt;import java.lang.StringBuffer;&lt;/code&gt; absolutely free!&lt;/p&gt;


	&lt;p&gt;Some factories pay their employees a &amp;#8220;piece rate&amp;#8221;.  Would you accept $11.66 per line of code instead of a salary? Of course it couldn&amp;#8217;t just be any old line of code.  It&amp;#8217;d have to be tested!&lt;/p&gt;


	&lt;p&gt;Hey, I bet all programmers would do &lt;span class="caps"&gt;TDD&lt;/span&gt; if we paid them a piece rate!&lt;/p&gt;


	&lt;h2&gt;Down to business.&lt;/h2&gt;


	&lt;p&gt;The point of that silly analysis was to demonstrate that software is &lt;em&gt;expensive&lt;/em&gt;.  Even the dumbest little app will likely require more than 1,000 lines of code; and that means it could cost $12K to write!&lt;/p&gt;


	&lt;p&gt;Imagine that you aren&amp;#8217;t a programmer, but you have a clever idea for a new website that&amp;#8217;ll make you a zillion dollars.  You&amp;#8217;ve storyboarded it all out.  You&amp;#8217;ve worked out all the details.  Now all you need is some high-school kid to zip out the code for you. Right?  Hell, you could pay him minimum wage!  The little twerp would be happy to get it!&lt;/p&gt;


	&lt;p&gt;That tragic comedy is altogether too common.  Too many people have borrowed money against their father&amp;#8217;s retirement account to fund a terrible implementation of a good idea.  Appalled at how much the reputable firms charge per hour ($100 or more) they go looking for a cheap solution.&lt;/p&gt;


	&lt;p&gt;&amp;#8220;After all, this software is &lt;em&gt;simple&lt;/em&gt;.&amp;#8221; Or so the reasoning goes.  &amp;#8220;It&amp;#8217;s not like we&amp;#8217;re trying to send a rocket to the moon or anything.  And, besides, those expensive guys were just out to cheat us.  Software just isn&amp;#8217;t that hard to write.&amp;#8221;  Uh huh.&lt;/p&gt;


	&lt;p&gt;So the poor schmuck finds some freshman in college, or maybe a bored housewife who read a book on &lt;span class="caps"&gt;HTML&lt;/span&gt; last year and created a cute website to show off her kittens. Have these programmers heard about &lt;span class="caps"&gt;TDD&lt;/span&gt;?  Have they heard about Design Patterns?  Principles?  How about source code control?&lt;/p&gt;


	&lt;p&gt;Clearly they haven&amp;#8217;t.  They&amp;#8217;re going to sling a bunch of horrific code together, without any tests, versioning, or control.  The project will start well, with exciting initial results.  But then it will slowly grind to a halt, while the cash continues out the door unabated.&lt;/p&gt;


	&lt;p&gt;In the end the website isn&amp;#8217;t going to get built (and the poor schmuck&amp;#8217;s father won&amp;#8217;t be retiring as soon as he thought). It will be a disaster that will either be terminated, or will require double or triple the investment to get right.&lt;/p&gt;


	&lt;h2&gt;The Bottom Line.&lt;/h2&gt;


	&lt;p&gt;The bottom line is that, when it comes to software, you get what you pay for.  If you want good software done well, then you are going to pay for it, and it will probably cost you $12/line or more.  And, believe me, that&amp;#8217;s the &lt;em&gt;cheapest&lt;/em&gt; way to get your software done.&lt;/p&gt;


	&lt;p&gt;If you go out hunting for the cheap solution, then you&amp;#8217;re going to end up paying more, and losing time.  Software is one of those things that costs a fortune to write well, and double that to write poorly.  If you go for cheap, you&amp;#8217;re going to pay double; and maybe even triple.&lt;/p&gt;</description>
      <pubDate>Mon, 01 Feb 2010 16:17:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:85351364-b4f5-4faa-af8a-4fb1f604ecae</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/02/01/software-on-the-cheap</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Mocking Mocking and Testing Outcomes.</title>
      <description>&lt;p&gt;The number of mocking frameworks has proliferated in recent years.  This pleases me because it is a symptom that testing in general, and &lt;span class="caps"&gt;TDD&lt;/span&gt; in particular, have become prevalent enough to support a rich panoply of third-party products.&lt;/p&gt;


	&lt;p&gt;On the other hand, all frameworks carry a disease with them that I call &lt;em&gt;The Mount Everest Syndrome&lt;/em&gt;: &amp;#8220;I use it because it&amp;#8217;s there.&amp;#8221;  The more mocking frameworks that appear, the more I see them enthusiastically used.  Yet the prolific use of mocking frameworks is a rather serious design smell&amp;#8230;&lt;/p&gt;


	&lt;p&gt;Lately I have seen several books and articles that present &lt;span class="caps"&gt;TDD&lt;/span&gt; through the lens of a mocking framework.  If you were a newbie to &lt;span class="caps"&gt;TDD&lt;/span&gt;, these writings might give you the idea that &lt;span class="caps"&gt;TDD&lt;/span&gt; was defined by the use of mocking tools, rather than by the &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd"&gt;disciplines&lt;/a&gt; of &lt;span class="caps"&gt;TDD&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;So when should use use a mocking framework?  The answer is the same for any other framework.  You use a framework only when that framework will give you a significant advantage.&lt;/p&gt;


	&lt;p&gt;Why so austere?  Why shouldn&amp;#8217;t you use frameworks &amp;#8220;just because they are there&amp;#8221;?  Because frameworks &lt;em&gt;always&lt;/em&gt; come with a cost.  They must be learned by the author, and by all the readers.  They become part of the configuration and have to be maintained.  They must be tracked from version to version.  But perhaps the most significant reason is that once you have a hammer, everything starts to look like a nail.  The framework will put you into a constraining mindset that prevents you from seeing other, better solutions.&lt;/p&gt;


Consider, for example, this lovely bit of code that I&amp;#8217;ve been reviewing recently.  It uses the Moq framework to initialize a test double:
&lt;pre&gt;&lt;code&gt;
var vehicleMock = Mocks.Create&amp;lt;IClientVehicle&amp;gt;()
 .WithPersistentKey()
 .WithLogicalKey().WithLogicalName()
 .WithRentalSessionManager(rsm =&amp;gt;
    {
      var rs = Mocks.Create&amp;lt;IRentalSession&amp;gt;();
      rsm.Setup(o =&amp;gt; o.GetCurrentSession()).Returns(rs.Object);
      rsm.Setup(o =&amp;gt;
       o.GetLogicalKeyOfSessionMember(It.IsAny&amp;lt;string&amp;gt;(),
        It.IsAny&amp;lt;int&amp;gt;())).Returns("Rental");
    })
 .AddVehicleMember&amp;lt;IRoadFactory&amp;gt;()
 .AddVehicleMember&amp;lt;IRoadItemFactory&amp;gt;(rf =&amp;gt; rf.Setup(t =&amp;gt; 
    t.CreateItems(It.IsAny&amp;lt;IRoad&amp;gt;())).Returns(pac))
 .AddVehicleMember&amp;lt;ILegacyCorporateRental&amp;gt;()
 .AddVehicleMember&amp;lt;IRentalStation&amp;gt;(
    m =&amp;gt; m.Setup(k =&amp;gt; k.Facility.FacilityID).Returns(0))
 .AddVehicleMember&amp;lt;IRoadManager&amp;gt;(m=&amp;gt;
    m.Setup(k=&amp;gt;k.GetRoundedBalanceDue(25,It.IsAny&amp;lt;IRoad&amp;gt;())).Returns(25));
&lt;/code&gt;&lt;/pre&gt;
Some of you might think I&amp;#8217;m setting up a straw-man.  I&amp;#8217;m not.  I realize that bad code can be written in any language or framework, and that you can&amp;#8217;t blame the language or framework for bad code.  
&lt;p/&gt;&lt;p/&gt;
The point I am making is that code like this was &lt;em&gt;the way&lt;/em&gt; that all unit tests in this application were written.  The team was new to &lt;span class="caps"&gt;TDD&lt;/span&gt;, and they got hold of a tool, and perhaps read a book or article, and decided that &lt;span class="caps"&gt;TDD&lt;/span&gt; was done by using a mocking tool.  This team is not the first team I&amp;#8217;ve seen who have fallen into this trap.  In fact, I think that the &lt;span class="caps"&gt;TDD&lt;/span&gt; industry as a whole has fallen into this trap to one degree or another.

	&lt;p&gt;Now don&amp;#8217;t get me wrong.  I like mocking tools.  I use them in Ruby, Java, and .Net. I think they provide a convenient way to make test-doubles in situations where more direct means are difficult.&lt;/p&gt;


For example, I recently wrote the following unit test in FitNesse using the Mockito framework.  
&lt;pre&gt;&lt;code&gt;
  @Before
  public void setUp() {
    manager = mock(GSSManager.class);
    properties = new Properties();
  }

  @Test
  public void credentialsShouldBeNullIfNoServiceName() throws Exception {
    NegotiateAuthenticator authenticator = 
      new NegotiateAuthenticator(manager, properties);
    assertNull(authenticator.getServerCredentials());
    verify(manager, never()).createName(
      anyString(), (Oid) anyObject(), (Oid) anyObject());
  }
&lt;/code&gt;&lt;/pre&gt;
The first line in the &lt;code&gt;setUp&lt;/code&gt; function is lovely.  It&amp;#8217;s kind of hard to get prettier than that.  Anybody reading it understands that &lt;code&gt;manager&lt;/code&gt; will be a mock of the &lt;code&gt;GSSManager&lt;/code&gt; class.  
&lt;p/&gt;&lt;p/&gt;
It&amp;#8217;s not too hard to understand the test itself.  Apparently we are happy to have the &lt;code&gt;manager&lt;/code&gt; be a dummy object with the constraint that &lt;code&gt;createName&lt;/code&gt; is never called by &lt;code&gt;NegotiateAuthenticator&lt;/code&gt;.  The &lt;code&gt;anyString()&lt;/code&gt; and &lt;code&gt;anyObject()&lt;/code&gt; calls are pretty self explanatory.

	&lt;p&gt;On the other hand, I wish I could have said this:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;assertTrue(manager.createNameWasNotCalled());&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;That statement does not require my poor readers to understand anything about Mockito.  Of course it does require me to hand-roll a manager mock.  Would that be hard?  Let&amp;#8217;s try.&lt;/p&gt;


First I need to create a dummy.  
&lt;pre&gt;&lt;code&gt;
  private class MockGSSManager extends GSSManager {
    public Oid[] getMechs() {
      return new Oid[0];
    }

    public Oid[] getNamesForMech(Oid oid) throws GSSException {
      return new Oid[0];
    }

    public Oid[] getMechsForName(Oid oid) {
      return new Oid[0];
    }

    public GSSName createName(String s, Oid oid) throws GSSException {
      return null;
    }

    public GSSName createName(byte[] bytes, Oid oid) throws GSSException {
      return null;
    }

    public GSSName createName(String s, Oid oid, Oid oid1) throws GSSException {
      return null;
    }

    public GSSName createName(byte[] bytes, Oid oid, Oid oid1) throws GSSException {
      return null;
    }

    public GSSCredential createCredential(int i) throws GSSException {
      return null;
    }

    public GSSCredential createCredential(GSSName gssName, int i, Oid oid, int i1) throws GSSException {
      return null;
    }

    public GSSCredential createCredential(GSSName gssName, int i, Oid[] oids, int i1) throws GSSException {
      return null;
    }

    public GSSContext createContext(GSSName gssName, Oid oid, GSSCredential gssCredential, int i) throws GSSException {
      return null;
    }

    public GSSContext createContext(GSSCredential gssCredential) throws GSSException {
      return null;
    }

    public GSSContext createContext(byte[] bytes) throws GSSException {
      return null;
    }

    public void addProviderAtFront(Provider provider, Oid oid) throws GSSException {
    }

    public void addProviderAtEnd(Provider provider, Oid oid) throws GSSException {
    }
  }
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&amp;#8220;Oh, ick!&amp;#8221; you say.  Yes, I agree it&amp;#8217;s a lot of code.  On the other hand, it took me just a single keystroke on my &lt;span class="caps"&gt;IDE&lt;/span&gt; to generate all those dummy methods.  (In IntelliJ it was simply command-I to implement all unimplemented methods.)  So it wasn&amp;#8217;t particularly hard.  And, of course, I can put this code somewhere where nobody had to look at it unless they want to.  It has the advantage that anybody who knows Java can understand it, and can look right at the methods to see what they are returning.  No &amp;#8220;special&amp;#8221; knowledge of the mocking framework is necessary.&lt;/p&gt;


Next, let&amp;#8217;s&amp;#8217; make a test double that does precisely what this test needs.
&lt;pre&gt;&lt;code&gt;
  private class GSSManagerSpy extends MockGSSManager {
    public boolean createNameWasCalled;

    public GSSName createName(String s, Oid oid) throws GSSException {
      createNameWasCalled = true;
      return null;
    }
  }
&lt;/code&gt;&lt;/pre&gt;
Well, that just wasn&amp;#8217;t that hard.  It&amp;#8217;s really easy to understand too. 

Now, let&amp;#8217;s rewrite the test.
&lt;pre&gt;&lt;code&gt;
  @Test
  public void credentialsShouldBeNullIfNoServiceNameWithHandRolledMocks() throws Exception {
    NegotiateAuthenticator authenticator = new NegotiateAuthenticator(managerSpy, properties);
    assertNull(authenticator.getServerCredentials());
    assertFalse(managerSpy.createNameWasCalled);
  }
&lt;/code&gt;&lt;/pre&gt;
Well, that test is just a &lt;em&gt;load&lt;/em&gt; easier to read than &lt;code&gt;verify(manager, never()).createName(anyString(), (Oid) anyObject(), (Oid) anyObject());&lt;/code&gt;.
&lt;p/&gt;&lt;p/&gt;
&amp;#8220;But Uncle Bob!&amp;#8221; I hear you say.  &amp;#8220;That scenario is too simple.  What if there were lots of dependencies and things&amp;#8230;&amp;#8221; 

I&amp;#8217;m glad you asked that question, because the very next test is just such a situation.  
&lt;pre&gt;&lt;code&gt;
  @Test
  public void credentialsShouldBeNonNullIfServiceNamePresent() throws Exception {
    properties.setProperty("NegotiateAuthenticator.serviceName", "service");
    properties.setProperty("NegotiateAuthenticator.serviceNameType", "1.1");
    properties.setProperty("NegotiateAuthenticator.mechanism", "1.2");
    GSSName gssName = mock(GSSName.class);
    GSSCredential gssCredential = mock(GSSCredential.class);
    when(manager.createName(anyString(), (Oid) anyObject(), (Oid) anyObject())).thenReturn(gssName);
    when(manager.createCredential((GSSName) anyObject(), anyInt(), (Oid) anyObject(), anyInt())).thenReturn(gssCredential);
    NegotiateAuthenticator authenticator = new NegotiateAuthenticator(manager, properties);
    Oid serviceNameType = authenticator.getServiceNameType();
    Oid mechanism = authenticator.getMechanism();
    verify(manager).createName("service", serviceNameType, mechanism);
    assertEquals("1.1", serviceNameType.toString());
    assertEquals("1.2", mechanism.toString());
    verify(manager).createCredential(gssName, GSSCredential.INDEFINITE_LIFETIME, mechanism, GSSCredential.ACCEPT_ONLY);
    assertEquals(gssCredential, authenticator.getServerCredentials());
  }
&lt;/code&gt;&lt;/pre&gt;
Now I&amp;#8217;ve got three test doubles that interact with each other; and I am verifying that the code under test is manipulating them all correctly.  I &lt;em&gt;could&lt;/em&gt; create hand-rolled test doubles for this; but the wiring between them would be scattered in the various test-double derivatives.  I&amp;#8217;d also have to write a significant number of accessors to get the values of the arguments to &lt;code&gt;createName&lt;/code&gt; and &lt;code&gt;createCredential&lt;/code&gt;.  In short, the hand-rolled test-double code would be harder to understand than the Mockito code.  The Mockito code puts the whole story in one simple test method rather than scattering it hither and yon in a plethora of little derivatives.
&lt;p/&gt;&lt;p/&gt;
What&amp;#8217;s more, since it&amp;#8217;s clear that I should use a mocking framework for this test, I think I should be consistent and use if for &lt;em&gt;all&lt;/em&gt; the tests in this file.   So the hand-rolled &lt;code&gt;MockGSSManager&lt;/code&gt; and &lt;code&gt;ManagerSpy&lt;/code&gt; are history.

	&lt;p&gt;&amp;#8220;But Uncle Bob, aren&amp;#8217;t we always going to have dependencies like that?  So aren&amp;#8217;t we &lt;em&gt;always&lt;/em&gt; going to have to use a mocking framework?&amp;#8221;&lt;/p&gt;


	&lt;p&gt;That, my dear reader, is the real point of this blog.  The answer to that salient questions is a profound: &amp;#8220;&lt;strong&gt;No!&lt;/strong&gt;&amp;#8220;&lt;/p&gt;


	&lt;p&gt;Why did I have to use Mockito for these tests?  Because the number of objects in play was large.  The module under test (&lt;code&gt;NegotiateAuthenticator&lt;/code&gt;) used &lt;code&gt;GSSName&lt;/code&gt;, &lt;code&gt;GSSCredential&lt;/code&gt;, and &lt;code&gt;GSSManager&lt;/code&gt;.  In other words the coupling between the module under test and the test itself was high.  (I see lightbulbs above some of your heads.) That&amp;#8217;s right, boys and girls, we don&amp;#8217;t want coupling to be high!&lt;/p&gt;


	&lt;p&gt;It is the high coupling between modules and tests that creates the need for a mocking framework.  This high coupling is also the cause of the dreaded &amp;#8220;Fragile Test&amp;#8221; problem.  How many tests break when you change a module?  If the number is high, then the coupling between your modules and tests in high.  Therefore, I conclude that those systems that make prolific use of mocking frameworks are likely to suffer from fragile tests.&lt;/p&gt;


	&lt;p&gt;Of the 277 unit test files in FitNesse, only 11 use Mockito.  The reason for small number is two-fold.  First, we test outcomes more often than we test mechanisms.  That means we test how a small group of classes behaves, rather than testing the dance of method calls between those classes.  The second reason is that our test doubles have no middle class.  They are either very simple stubs and spies or they are moderately complex fakes.&lt;/p&gt;


	&lt;p&gt;Testing outcomes is a traditional decoupling technique.  The test doesn&amp;#8217;t care &lt;em&gt;how&lt;/em&gt; the end result is calculated, so long as the end result is correct.  There may be a dance of several method calls between a few different objects; but the test is oblivious since it only checks the answer.  Therefore the tests are not strongly coupled to the solution and are not fragile.&lt;/p&gt;


	&lt;p&gt;Keeping middle-class test doubles (i.e. Mocks) to a minimum is another way of decoupling.  Mocks, by their very nature, are coupled to mechanisms instead of outcomes.  Mocks, or the setup code that builds them, have deep knowledge of the inner workings of several different classes.  That knowledge is the very definition of high-coupling.&lt;/p&gt;


	&lt;p&gt;What is a &amp;#8220;moderately complex fake&amp;#8221; and why does it help to reduce coupling?  One example within FitNesse is &lt;code&gt;MockSocket&lt;/code&gt;.  (The name of this class is historical.  Nowadays it should be called &lt;code&gt;FakeSocket&lt;/code&gt;.)  This class derives from &lt;code&gt;Socket&lt;/code&gt; and implements all its methods either to remember what was sent to the socket, or to allow a user to read some canned data.  This is a &amp;#8220;fake&amp;#8221; because it simulates the behavior of a socket.  It is not a mock because it has no coupling to any mechanisms.  You don&amp;#8217;t ask it whether it succeeded or failed, you ask it to send or recieve a string.  This allows our unit tests to test outcomes rather than mechanisms.&lt;/p&gt;


	&lt;p&gt;The moral of this story is that the point at which you start to really need a mocking framework is the very point at which the coupling between your tests and code is getting too high.  There are times when you can&amp;#8217;t avoid this coupling, and those are the times when mocking frameworks &lt;em&gt;really&lt;/em&gt; pay off.  However, you should strive to keep the coupling between your code and tests low enough that you don&amp;#8217;t need to use the mocking framework very often.&lt;/p&gt;


	&lt;p&gt;You do this by testing outcomes instead of mechanisms.&lt;/p&gt;</description>
      <pubDate>Sat, 23 Jan 2010 11:32:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:b863ec60-399c-430f-8e82-78e54684cae4</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/01/23/mocking-mocking-and-testing-outcomes</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Design Principles</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Dependency Injection Inversion</title>
      <description>&lt;p&gt;Dependency Injection is all the rage.  There are several frameworks that will help you inject dependencies into your system.  Some use &lt;span class="caps"&gt;XML&lt;/span&gt; (God help us) to specify those dependencies.  Others use simple statements in code.  In either case, the goal of these frameworks is to help you create instances without having to resort to &lt;code&gt;new&lt;/code&gt; or Factories.&lt;/p&gt;


	&lt;p&gt;I think these frameworks are great tools.  But I also think you should carefully restrict how and where you use them.&lt;/p&gt;


	&lt;p&gt;Consider, for example, this simple example using Google&amp;#8217;s Guice framework.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
 public class BillingApplication {
   public static void main(String[] args) {
    Injector injector = Guice.createInjector(new BillingModule());
    BillingService billingService = injector.getInstance(BillingService.class);
    billingService.processCharge(2034, "Bob");
  }
 }
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;My goal is to create an instance of &lt;code&gt;BillingService&lt;/code&gt;.  To do this, I first get an &lt;code&gt;Injector&lt;/code&gt; from Guice.  Then I use the &lt;code&gt;injector&lt;/code&gt; to get an instance of my &lt;code&gt;BillingService&lt;/code&gt; class.  What&amp;#8217;s so great about this?  Well, take a look at the constructor of the &lt;code&gt;BillingService&lt;/code&gt; class.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
class BillingService {
  private CreditCardProcessor processor;
  private TransactionLog transactionLog;

  @Inject
  BillingService(CreditCardProcessor processor, TransactionLog transactionLog) {
    this.processor = processor;
    this.transactionLog = transactionLog;
  }

  public void processCharge(int amount, String id) {
    boolean approval = processor.approve(amount, id);
    transactionLog.log(
      String.format("Transaction by %s for %d %s",
      id, amount, approvalCode(approval)));
  }

  private String approvalCode(boolean approval) {
    return approval?"approved":"denied";
  }
}

&lt;/code&gt;&lt;/pre&gt;
Oh ho!  The &lt;code&gt;BillingService&lt;/code&gt; constructor requires two arguments!  A &lt;code&gt;CreditCardProcessor&lt;/code&gt; and a &lt;code&gt;TransactionLog&lt;/code&gt;.  How was the &lt;code&gt;main&lt;/code&gt; program able to create an instance of &lt;code&gt;BillingService&lt;/code&gt; without those two arguments?  That&amp;#8217;s the magic of Guice (and of all Dependency Injection frameworks).  Guice knows that the &lt;code&gt;BillingService&lt;/code&gt; needs those two arguments, and it knows how to create them.  Did you see that funky &lt;code&gt;@Inject&lt;/code&gt; attribute above the constructor?  That&amp;#8217;s how it got connected into Guice.

	&lt;p&gt;And here&amp;#8217;s the magic module that tells Guice how to create the arguments for the &lt;code&gt;BillingService&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
public class BillingModule extends AbstractModule {
  protected void configure() {
    bind(TransactionLog.class).to(DatabaseTransactionLog.class);
    bind(CreditCardProcessor.class).to(MyCreditCardProcessor.class);
  }
}

&lt;/code&gt;&lt;/pre&gt;
Clever these Google-folk!  The two &lt;code&gt;bind&lt;/code&gt; functions tell Guice that whenever we need an instance of a &lt;code&gt;TransactionLog&lt;/code&gt; it should use an instance of &lt;code&gt;DatabaseTransactionLog&lt;/code&gt;.  Whenever it needs a &lt;code&gt;CreditCardProcessor&lt;/code&gt; it should use an instance of &lt;code&gt;MyCreditCardProcessor&lt;/code&gt;.

	&lt;p&gt;Isn&amp;#8217;t that cool!  Now you don&amp;#8217;t have to build factories.  You don&amp;#8217;t have to use &lt;code&gt;new&lt;/code&gt;.  You just tell Guice how to map interfaces to implementations, and which constructors to inject those implementations in to, and then call &lt;code&gt;Injector.getInstance(SomeClass.class);&lt;/code&gt; and voila!  You have your instance automatically constructed for you.  Cool.&lt;/p&gt;


	&lt;p&gt;Well, yes it&amp;#8217;s cool.  On the other hand, consider this code:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
public class BillingApplicationNoGuice {
  public static void main(String[] args) {
    CreditCardProcessor cp = new MyCreditCardProcessor();
    TransactionLog tl = new DatabaseTransactionLog();
    BillingService bs = new BillingService(cp, tl);
    bs.processCharge(9000, "Bob");
  }
}

&lt;/code&gt;&lt;/pre&gt; 
Why is this worse?  It seems to me it&amp;#8217;s better.

	&lt;p&gt;&lt;em&gt;But Uncle Bob&lt;/em&gt;, you&amp;#8217;ve violated &lt;span class="caps"&gt;DIP&lt;/span&gt; by creating concrete instances!&lt;/p&gt;


	&lt;p&gt;True, but you have to mention concrete instances somewhere.  &lt;code&gt;main&lt;/code&gt; seems like a perfectly good place for that.  Indeed, it seems better than hiding the concrete references in &lt;code&gt;BillingModule&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;I don&amp;#8217;t want a bunch of secret modules with &lt;code&gt;bind&lt;/code&gt; calls scattered all around my code.  I don&amp;#8217;t want to have to hunt for the particular &lt;code&gt;bind&lt;/code&gt; call for the &lt;code&gt;Zapple&lt;/code&gt; interface when I&amp;#8217;m looking at some module.  I want to know where all the instances are created.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;But Uncle Bob&lt;/em&gt;, You&amp;#8217;d know where they are because this is a &lt;em&gt;Guice&lt;/em&gt; application.&lt;/p&gt;


	&lt;p&gt;I don&amp;#8217;t want to write a &lt;em&gt;Guice&lt;/em&gt; application.  Guice is a framework, and I don&amp;#8217;t want framework code smeared all through my application.  I want to keep frameworks nicely decoupled and at arms-length from the main body of my code.  I don&amp;#8217;t want to have &lt;code&gt;@Inject&lt;/code&gt; attributes everywhere and &lt;code&gt;bind&lt;/code&gt; calls hidden under rocks.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;But Uncle Bob&lt;/em&gt;, What if I want to get an instance of &lt;code&gt;BillingService&lt;/code&gt; from deep in the bowels of my application?  With Guice I can just say &lt;code&gt;injector.getInstance(BillingService.class);&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;True, but I don&amp;#8217;t want to have &lt;code&gt;createInstance&lt;/code&gt; calls scattered all through my code.  I don&amp;#8217;t want Guice to be poured all over my app. I want my app to be clean, not soaked in Guice.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;But Uncle Bob&lt;/em&gt;, That means I have to use &lt;code&gt;new&lt;/code&gt; or factories, or pass globals around.&lt;/p&gt;


	&lt;p&gt;You think the &lt;code&gt;injector&lt;/code&gt; is not a global?  You think &lt;code&gt;BillingService.class&lt;/code&gt; is not a global?  There will always be globals to deal with.  You can&amp;#8217;t write systems without them.  You just need to manage them nicely.&lt;/p&gt;


	&lt;p&gt;And, no, I don&amp;#8217;t have to use &lt;code&gt;new&lt;/code&gt; everywhere, and I don&amp;#8217;t need factories.  I can do something as simple as:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
public class BillingApplicationNoGuice {
  public static void main(String[] args) {
    CreditCardProcessor cp = new MyCreditCardProcessor();
    TransactionLog tl = new DatabaseTransactionLog();
    BillingService.instance = new BillingService(cp, tl);

    // Deep in the bowels of my system.
    BillingService.instance.processCharge(9000, "Bob");
  }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;em&gt;But Uncle Bob&lt;/em&gt;, what if you want to create many instances of &lt;code&gt;BillingService&lt;/code&gt; rather than just that one singleton?

	&lt;p&gt;Then I&amp;#8217;d use a factory, like so:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
public class BillingApplication {
   public static void main(String[] args) {
    Injector injector = Guice.createInjector(new BillingModule());
    BillingService.factory = new BillingServiceFactory(injector);

    // Deep in the bowels of my code.
    BillingService billingService = BillingService.factory.make();
    billingService.processCharge(2034, "Bob");
  }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;em&gt;But Uncle Bob&lt;/em&gt;, I thought the whole idea was to avoid factories!

	&lt;p&gt;Hardly.  After all, Guice is just a big factory.  But you didn&amp;#8217;t let me finish.  Did you notice that I passed the Guice injector into the factory?  Here&amp;#8217;s the factory implementation.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
public class BillingServiceFactory extends AbstractModule {
  private Injector injector;

  public BillingServiceFactory(Injector injector) {
    this.injector = injector;
  }

  protected void configure() {
    bind(TransactionLog.class).to(DatabaseTransactionLog.class);
    bind(CreditCardProcessor.class).to(MyCreditCardProcessor.class);
  }

  public BillingService make() {
    return injector.getInstance(BillingService.class);
  }
}

&lt;/code&gt;&lt;/pre&gt;
I like this because now all the Guice is in one well understood place.  I don&amp;#8217;t have Guice all over my application.  Rather, I&amp;#8217;ve got factories that contain the Guice.  Guicey factories that keep the Guice from being smeared all through my application.  

	&lt;p&gt;What&amp;#8217;s more, if I wanted to replace Guice with some other DI framework, I know exactly what classes would need to change, and how to change them.  So I&amp;#8217;ve kept Guice uncoupled from my application.&lt;/p&gt;


	&lt;p&gt;Indeed, using this form allows me to defer using Guice until I think it&amp;#8217;s necessary.  I can just build the factories the good old &lt;span class="caps"&gt;GOF&lt;/span&gt; way until the need to externalize dependencies emerges.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;But Uncle Bob&lt;/em&gt;, don&amp;#8217;t you think Dependency Injection is a good thing?&lt;/p&gt;


	&lt;p&gt;Of course I do.  Dependency Injection is just a special case of Dependency Inversion.  I think Dependency Inversion is so important that I want to invert the dependencies on Guice!  I don&amp;#8217;t want lots of concrete Guice dependencies scattered through my code.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;BTW&lt;/span&gt;, did you notice that I was using Dependency Injection even when I wasn&amp;#8217;t using Guice at all?  This is nice and simple &lt;em&gt;manual&lt;/em&gt; dependency injection.  Here&amp;#8217;s that code again in case you don&amp;#8217;t want to look back:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;

public class BillingApplicationNoGuice {
  public static void main(String[] args) {
    CreditCardProcessor cp = new MyCreditCardProcessor();
    TransactionLog tl = new DatabaseTransactionLog();
    BillingService bs = new BillingService(cp, tl);
    bs.processCharge(9000, "Bob");
  }
}

&lt;/code&gt;&lt;/pre&gt;
Dependency Injection doesn&amp;#8217;t require a framework; it just requires that you invert your dependencies and then construct and pass your arguments to deeper layers.   Consider, for example, that the following test works just fine in &lt;em&gt;all&lt;/em&gt; the cases above.  It does not rely on Guice, it only relies on the fact that dependencies were inverted and can be injected into &lt;code&gt;BillingService&lt;/code&gt;

&lt;pre&gt;&lt;code&gt;

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;
  }
}

&lt;/code&gt;&lt;/pre&gt;
Also notice that I rolled my own Test Doubles (we used to call them mocks, but we&amp;#8217;re not allowed to anymore.)  It would have been tragic to use a mocking framework for such a simple set of tests.

	&lt;p&gt;Most of the time the best kind of Dependency Injection to use, is the manual kind.  Externalized dependency injection of the kind that Guice provides is appropriate for those classes that you &lt;em&gt;know&lt;/em&gt; will be extension points for your system.&lt;/p&gt;


	&lt;p&gt;But for classes that aren&amp;#8217;t obvious extension points, you will simply know the concrete type you need, and can create it at a relatively high level and inject it down as an interface to the lower levels.  If, one day, you find that you need to externalize that dependency, it&amp;#8217;ll be easy because you&amp;#8217;ve already inverted and injected it.&lt;/p&gt;</description>
      <pubDate>Sun, 17 Jan 2010 12:42:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:00f97566-88ff-41a0-a0b1-4baee8225dc0</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2010/01/17/dependency-injection-inversion</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Design Principles</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Saying &amp;quot;NO&amp;quot;.</title>
      <description>&lt;p&gt;I saw &lt;a href="http://theoatmeal.com/comics/design_hell"&gt;this cartoon&lt;/a&gt; in a tweet today. It&amp;#8217;s the story of how a boss corrupts the work of a professional.  It&amp;#8217;s a funny cartoon, and a sad story that happens all too often in our profession.  But who, exactly, was at fault?...&lt;/p&gt;


	&lt;p&gt;The difference between a laborer and a professional is that a laborer takes orders from his boss, and a professional provides input to his superiors.  Laborers are hired to take direction.  Professionals are hired to ensure that the direction chosen makes sense.&lt;/p&gt;


	&lt;p&gt;Imagine this conversation between a patient and a doctor:&lt;/p&gt;


	&lt;p&gt;Patient: &lt;em&gt;&amp;#8220;My arm hurts.&amp;#8221;&lt;/em&gt;
Doctor:  &lt;em&gt;&amp;#8220;What would you like me to do about it?&amp;#8221;&lt;/em&gt;
Patient: &lt;em&gt;&amp;#8220;Make my arm stop hurting.&amp;#8221;&lt;/em&gt;
Doctor:  &lt;em&gt;&amp;#8220;Do you want me to cut it off?, I can do that.&amp;#8221;&lt;/em&gt;
Patient: &lt;em&gt;&amp;#8220;No, I just want it to stop hurting.&amp;#8221;&lt;/em&gt;
Doctor:  &lt;em&gt;&amp;#8220;I could cut all the nerves to your arm.  That&amp;#8217;ll stop it.&amp;#8221;&lt;/em&gt;
Patient: &lt;em&gt;&amp;#8220;Isn&amp;#8217;t there something less drastic you could do?&amp;#8221;&lt;/em&gt;
Doctor:  &lt;em&gt;&amp;#8220;Ooops, sorry, time for my break.&amp;#8221;&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Clearly we don&amp;#8217;t expect doctors to behave this way.  Even though the patient is the boss, the patient expects the doctor to have the answers and help set the direction.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s another version of the conversation:&lt;/p&gt;


	&lt;p&gt;Patient:  &lt;em&gt;&amp;#8220;I want you to cut my arm off.&amp;#8221;&lt;/em&gt;
Doctor:   &lt;em&gt;&amp;#8220;What&amp;#8217;s wrong with your arm?&amp;#8221;&lt;/em&gt;
Patient:  &lt;em&gt;&amp;#8220;It hurts.  I&amp;#8217;m tired of it.  Just cut it off.&amp;#8221;&lt;/em&gt;
Doctor:   &lt;em&gt;&amp;#8220;Let me see your arm.  Hmmm.  Looks like you&amp;#8217;ve got a sprain or perhaps a hairline fracture.  We should take some X-Rays.&amp;#8221;&lt;/em&gt;
Patient:  &lt;em&gt;&amp;#8220;No, just cut it off.&amp;#8221;&lt;/em&gt;
Doctor:   &lt;em&gt;&amp;#8220;Sir, I do not cut off healthy arms.&amp;#8221;&lt;/em&gt;
Patient:  &lt;em&gt;&amp;#8220;But I&amp;#8217;m paying you.  You have to do what I say!&amp;#8221;&lt;/em&gt;
Doctor:   &lt;em&gt;&amp;#8220;No, sir, I don&amp;#8217;t.  Cutting off your arm would violate my oath.&amp;#8221;&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Which of these two doctors would you rather be?  Now project these two doctors into your own profession, and which would you rather be?&lt;/p&gt;


	&lt;p&gt;Programmers are professionals.  They know more about designing and implementing software systems than their bosses do.  Indeed, they are hired for this knowledge and expertise.  And they have a solemn duty to prevent their managers from doing things that would be harmful.&lt;/p&gt;


	&lt;p&gt;All this boils down to one simple thing.  Professionals are willing to say &amp;#8220;No&amp;#8221;.   When their managers come to them with direction that makes no sense, a professional programmer will refuse the direction.&lt;/p&gt;


	&lt;p&gt;Is this risky?  Sure.  But part of being a professional is the willingness to stand on principle.  There are lines that a professional will not cross.&lt;/p&gt;


	&lt;p&gt;Of course saying &amp;#8220;No.&amp;#8221; is only one side of the coin.  Professionals are also expected to explain their positions, and come up with viable alternatives.  Professionals &lt;em&gt;negotiate&lt;/em&gt; with their superiors until both parties are satisfied with the chosen direction.&lt;/p&gt;


	&lt;p&gt;The poor web-designer schmuck in that cartoon was not behaving as a professional.  He was behaving as a laborer.  The fiasco at the end was &lt;em&gt;his&lt;/em&gt; fault.  He should have said &amp;#8220;No.&amp;#8221; and started a &lt;em&gt;negotiation&lt;/em&gt; with his customer instead of just doing everything the customer said.&lt;/p&gt;


	&lt;p&gt;The cartoonist painted the web-designer as a wise but impotent victim, and the boss as the overbearing dufus.  The reality is that the web-designer took the role of the victim voluntarily and shirked his responsibility to refuse direction that he considered harmful.&lt;/p&gt;


	&lt;p&gt;If you are a professional, you &lt;em&gt;never&lt;/em&gt; allow yourself to be put in the role of the victim.&lt;/p&gt;</description>
      <pubDate>Fri, 04 Dec 2009 08:35:55 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:1c488f0e-912e-47c9-86b9-8333cfa3e7a1</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/12/04/saying-no</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
    </item>
    <item>
      <title>What's all this nonsense about Katas?</title>
      <description>&lt;p&gt;There has been an increase in interest in Software Katas of late.  What is all this buzz about, and why might it be important?&lt;/p&gt;


	&lt;p&gt;Several years ago (Pragmatic) Dave Thomas started a special &lt;a href="http://codekata.pragprog.com/"&gt;blog&lt;/a&gt; about coding katas.  The idea was simple: Professionals practice.&lt;/p&gt;


	&lt;p&gt;This thought might not have occurred to you before; but it&amp;#8217;s self-evidently true.  Professional musicians practice.  Professional dancers practice.  Doctors practice.  Soldiers practice.  Indeed, any kind of professional craftsman or artisan must practice their adopted trade in order to execute it well when it counts.&lt;/p&gt;


	&lt;p&gt;Dave&amp;#8217;s point was that professional programmers need to practice like any other professional.  He set forth a number of simple exercises and problems that programmers could solve during their practice time.  He also suggested that practice time needs to be scheduled and protected as part of the normal routine of a software developer.&lt;/p&gt;


	&lt;p&gt;At &lt;span class="caps"&gt;XP2005&lt;/span&gt; in Shefield, UK,  I attended Laurent Bossavit&amp;#8217;s and Emmanuel Gaillot&amp;#8217;s &lt;em&gt;Coding Dojo&lt;/em&gt; session.  I &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheProgrammingDojo"&gt;blogged&lt;/a&gt; about it at the time.  I left that session with a different view of what a Kata might be. In Dave Thomas&amp;#8217; view a kata is an exercise to solve.  Each time you solve it you try a different approach.  Dave&amp;#8217;s notion is that a kata is a way to explore the solution space of a problem. But in Martial arts a kata is something different; it is a set of motions that one memorizes in minute detail.  A martial arts kata is a &lt;em&gt;precisely executed dance&lt;/em&gt;.  I left Sheffield with the idea that a coding kata could be more like a martial arts kata.&lt;/p&gt;


	&lt;p&gt;About a year ago, &lt;a href="http://www.coreyhaines.com/"&gt;Corey Haines&lt;/a&gt; (our wandering minstrel of code) stopped by and told me about some mini-conferences that had adopted the notion of coding kata.  What he described sounded more like a group dance than a bunch of people independently solving a given problem.  This got me thinking.  So at the next Software Craftsmanship meeting at &lt;a href="http://www.8thlight.com/"&gt;8th Light&lt;/a&gt; (Which, not coincidentally, takes it&amp;#8217;s name from a martial arts philosophy) I conducted &lt;a href="http://www.vimeo.com/2499161"&gt;a simple kata session in dojo style&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I, acting as the Sen Sei, had everyone file in to the room as they would to a dojo.  I had them put their &lt;a href="http://cleancodeproject.com"&gt;green bands&lt;/a&gt; on their wrists (mine was black!).  I bade them to sit, and then gestured for silence.  For the next 15 minutes I led them through the &lt;a href="http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata"&gt;Prime Factors Kata in Java&lt;/a&gt; without uttering a word (well, almost).  I would write a simple test case, then gesture for them to do the same.  Then I would make the test pass, and again gesture for them to repeat my moves.&lt;/p&gt;


	&lt;p&gt;Then, this Fall, I attended &lt;a href="http://agile2009.agilealliance.org/programmingwiththestars"&gt;Programming with the Stars&lt;/a&gt; at Agile 2009.  As I watched the contestants perform their programming sessions, I realized that they were not simply demonstrating programming prowess; indeed they were competing in how well they &lt;em&gt;performed&lt;/em&gt; their session.  That&amp;#8217;s when it struck me.  This was a &lt;em&gt;performance art!&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;It seems absurd to think of programming as a performance art.  And yet watching those people up on stage working through routines that they had clearly practiced over and over again, was &lt;em&gt;delightfully entertaining&lt;/em&gt; to me, and to the crowd.  There were cheers and applause when a performing pair did something especially well.  There was laughter when a pair executed a clever joke in code, or in behavior.  For programmers, watching other programmers perform well practiced routines was &lt;em&gt;fun!&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Now I had seen martial arts katas executed as performance art during competitions.  Indeed, it is a beautiful thing to watch a skilled and well practiced martial artist peform a kata.  And that started me thinking.  Why would a martial artist practice these forms so intensely that they could be performed as an art?&lt;/p&gt;


	&lt;p&gt;The goal of martial arts is not to perform on stage.  The goal of martial arts is self defense!  And yet, when a martial artist is at the peak of his skill, his practice takes on the quality of a performance art.  When you watch a skilled martial artist perform, you &lt;em&gt;know&lt;/em&gt; you don&amp;#8217;t want to fight him.  The performance is a demonstration, and a realization, of mastery.&lt;/p&gt;


	&lt;p&gt;And yet the performance is not the goal.  No martial artist practices his art so that they can perform on stage.  A martial artist practices to achieve personal perfection in the art of self defense.  The fact that the practice can be performed is a (pleasant) side effect.&lt;/p&gt;


	&lt;p&gt;Could it be that these coding kata that we&amp;#8217;ve been dabbling with for the last few years could be &lt;em&gt;performed&lt;/em&gt;?  Is there a benefit to practicing them so much that performance is an option?  Is there really any reason for a programmer to create and then memorize a routine down to the level of individual keystrokes?  Is there profit to be gained from practicing that routine so thoroughly that you can do it at high speed with virtually no errors?  This August I decided to find out.&lt;/p&gt;


	&lt;p&gt;I started with the Prime Factors Kata in Java, and set it to music inspired by &lt;a href="http://www.youtube.com/watch?v=SV6ScA9rc1E"&gt;this video of dancing kites&lt;/a&gt;.  The piece is about 4 minutes long, and I figured I&amp;#8217;d need about twice that, so I found two different version of the music and played them back to back.  But working in Java is ponderous, and I could not complete the kata before the two pieces had finished.  So I switched to Ruby.  Using Ruby and Rspec I was able to finish the Kata with plenty of time to spare.&lt;/p&gt;


	&lt;p&gt;Thereupon began an evolution.  Since I had time, I added more features to the kata.  As I improved in my practice I found I had even more time, so I added even more features.  I refined and polished.  I refactored my refactorings.  I trimmed keystrokes, and learned many new keyboard shortcuts in the process. I completely abandoned the mouse; and then later reacquired it for flourishes and highlights (but never for actual coding).&lt;/p&gt;


	&lt;p&gt;Week after week, I set aside 30 minutes or so every day to practice, and practice, and practice&amp;#8212;just the way I used to practice my Jiu Jitsu Katas.  I would practice on airplanes while flying to clients.  I would practice in bed with my laptop in my lap.  I would practice late at night in hotel rooms after a long day consulting for clients.  I would practice early in the morning before shower and breakfast.  And the practice started to pay off.&lt;/p&gt;


	&lt;p&gt;Ten weeks later I finally decided I was ready to create a screencast.  I reduced my screen resolution to 1024X768.  I configured &lt;a href="http://www.ambrosiasw.com/utilities/snapzprox"&gt;SnapZ ProX&lt;/a&gt; to record the whole screen at 80% size.  And I began to record.&lt;/p&gt;


	&lt;p&gt;Performing a coding kata in time to music is a &lt;em&gt;very difficult thing to do&lt;/em&gt;.  Maintaining the timeline is &lt;em&gt;critical&lt;/em&gt;.  There are very few errors that you can effectively recover from.  If you miss a stroke, the whole sequence melts down.  And melt down it did.  Over and over and over again.  I spent weeks trying to record a reasonably good session.  I must have done hundreds of takes.  It was &lt;em&gt;very&lt;/em&gt; frustrating.&lt;/p&gt;


	&lt;p&gt;But day by day I got better and better at it.  Finally, after weeks of trying, I got what I consider to be a recording that, though not perfect, is good enough to present.  You can watch that recording &lt;a href="http://katas.softwarecraftsmanship.org/?p=71"&gt;here&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Has this paid off in the regular programming I do?  I think it has.  My mouse usage is much less than it used to be.  I know a much larger number of keyboard shortcuts than I used to, and I can use them almost instinctively.  My typing and accuracy have improved quite a bit, and I now type more punctuation and number keys without looking.  So, yes, I think the effort has paid off; though I&amp;#8217;m not at all sure the payoff compensates for the effort.&lt;/p&gt;


	&lt;p&gt;But something else compensates for the effort.  Making this recording was &lt;em&gt;fun&lt;/em&gt;&amp;#8212;it was a &lt;em&gt;lot of fun&lt;/em&gt;.  And that&amp;#8217;s probably the real answer to the question posed in the title of this blog.&lt;/p&gt;</description>
      <pubDate>Sat, 21 Nov 2009 04:32:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:b1c40077-fac6-4dd9-bc7f-0f988f020569</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/11/21/whats-all-this-nonsense-about-katas</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
    </item>
    <item>
      <title>Archeological Dig</title>
      <description>&lt;p&gt;I was going through some old files today, and I stumbled upon some acetate slides from 1995.  They were entitled: &amp;#8220;Managing OO Projects&amp;#8221;.  Wow!  What a difference fifteen years makes!   (Or does it?) ...&lt;/p&gt;


	&lt;p&gt;In 1995-99 I was frequently asked to speak to managers about what a transition to OO (usually from C to C++) would do for (or to) them.  I would spend a half day to a day going over the issues, costs, and benefits.&lt;/p&gt;


	&lt;p&gt;One part of that talk (usually about 90 min) was a discussion about software process.  It was the process part of the talk that those acetate slides that I found described.&lt;/p&gt;


	&lt;p&gt;1995 was during the ascendency of Waterfall.  Waterfall thinking was king. &lt;span class="caps"&gt;RUP&lt;/span&gt; had not yet been conceived as an acronym.  And though Booch was beating the drum for incrementalism, most people (even many within Rational) were thinking in terms of six to eighteen month waterfalls.&lt;/p&gt;


	&lt;p&gt;So, &lt;a href="http://butunclebob.com/files/unclebob/Managing%20OO%20Projects.pdf"&gt;here&lt;/a&gt; are the slides that I uncovered deep within an old filing cabinet.  I scanned them in.  They were produced on a Macintosh using the old &amp;#8220;More&amp;#8221; program.  (Where is that program now?  It was &lt;em&gt;so&lt;/em&gt; good.)&lt;/p&gt;


Go ahead and read them now.  Then come back here and continue&amp;#8230;
&lt;hr&gt;
What struck me about those slides was the consistency of the message with today.  It was all about iterative development.  Small iterations (though I never deigned to define the length in the slides, I frequently told people 2 weeks), measured results, etc. etc.  Any Agile evangelist could use those slides today.  He or she would have to dance quickly around a few statements, but overall the message has not shifted very much.

	&lt;p&gt;What&amp;#8217;s even more interesting is the coupling between the process, and OO.  The slides talk a lot about dependency management and dependency structure.  There are hints of the &lt;span class="caps"&gt;SOLID&lt;/span&gt; principles contained in those slides.  (Indeed several of the principles had already been identified by that time.)  This coupling between process and software structure was a harbinger of the current craftsmanship/clean-code movement.&lt;/p&gt;


	&lt;p&gt;Of course the one glaring omission from these slides is &lt;span class="caps"&gt;TDD&lt;/span&gt;.  That makes me think that &lt;span class="caps"&gt;TDD&lt;/span&gt; was the true catalyst of change, and the bridge that conveyed our industry from then to now.&lt;/p&gt;


	&lt;p&gt;Anyway, I guess the more things change, the more they stay the same.&lt;/p&gt;


	&lt;p&gt;Comments please!&lt;/p&gt;</description>
      <pubDate>Wed, 11 Nov 2009 10:39:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:2719dd93-f02d-4cbb-9850-265f68fbfb65</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/11/11/archeological-dig</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
      <category>Agile Methods</category>
      <category>Design Principles</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Excuse me sir, What Planet is this?</title>
      <description>&lt;p&gt;Update 12 hours later.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m not very proud of this blog (or as one commenter correctly called it &amp;#8220;blart&amp;#8221;).  It is derisive, sneering, and petulant.  It is unprofessional.  I guess I was having a bad morning.  I slipped.  I didn&amp;#8217;t check with my green band.&lt;/p&gt;


	&lt;p&gt;So I apologize to the audience at large, and to Cashto.  You should expect better from me.&lt;/p&gt;


	&lt;p&gt;I thought about pulling the blog down; but I think I&amp;#8217;ll leave it up here as an example of how &lt;i&gt;not&lt;/i&gt; to write a blog.&lt;/p&gt;


	&lt;p&gt;Some folks on twitter have been asking me to respond to this &lt;a href="http://blogs.msdn.com/cashto/archive/2009/03/31/it-s-ok-not-to-write-unit-tests.aspx"&gt;blough&lt;/a&gt; (don&amp;#8217;t bother to read it right now, I&amp;#8217;ll give you the capsule summary below.  Read it later if you must).  It&amp;#8217;s a typical screed complete with all the usual complaints, pejoratives, and illogic.  Generally I don&amp;#8217;t respond to blarts like this because I don&amp;#8217;t imagine that any readers take them very seriously.  But it appears that this blelch has made the twitter rounds and that I&amp;#8217;m going to have to say &lt;em&gt;something&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Here are the writer&amp;#8217;s main points:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;He likens unit tests to training wheels and says you can&amp;#8217;t use them to win the &lt;em&gt;Tour de France&lt;/em&gt;. 
	&lt;ul&gt;
	&lt;li&gt;I think winning the &lt;em&gt;Tour de France&lt;/em&gt; has much more to do with self-discipline than he imagines it does.  I mean it&amp;#8217;s not really just as simple as: &amp;#8220;Get on a bike and ride like hell!&amp;#8221;&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;He says testing is popular amongst college students
	&lt;ul&gt;
	&lt;li&gt;I&amp;#8217;d like to see his data!&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;He goes on to say: (cue John Cleese): &amp;#8220;(ahem) unit tests lose their effectiveness around level four of the &lt;em&gt;Dreyfus model of skill acquisition&amp;#8221;.&lt;/em&gt;  
	&lt;ul&gt;
	&lt;li&gt;(blank stunned stare).  Is this a joke?  All false erudition aside, &lt;span class="caps"&gt;WTF&lt;/span&gt; is he talking about?&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;He says that unit tests &lt;em&gt;don&amp;#8217;t&lt;/em&gt; give us confidence in refactoring because they &lt;strong&gt;over-specify&lt;/strong&gt; behavior and are too &lt;strong&gt;fine-grained&lt;/strong&gt;.  
	&lt;ul&gt;
	&lt;li&gt;He apparently prefers hyphenations to green bars.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;He says they mostly follow the &amp;#8220;happy path&amp;#8221; and therefore don&amp;#8217;t find bugs.  
	&lt;ul&gt;
	&lt;li&gt;Maybe when &lt;em&gt;he&lt;/em&gt; writes them!  This is a &lt;em&gt;big&lt;/em&gt; clue that the author can&amp;#8217;t spell &lt;span class="caps"&gt;TDD&lt;/span&gt;.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;He complains about Jester 
	&lt;ul&gt;
	&lt;li&gt;without getting the joke!&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;He says unit tests &amp;#8220;encourage some pretty questionable practices.&amp;#8221;  He flings a few design principles around and says that unit testing doesn&amp;#8217;t help with them. 
	&lt;ul&gt;
	&lt;li&gt;as the author, editor, and/or advocate of many of those principles; I have a slightly different view.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;He says that &amp;#8220;many are starting to discover that functional programming teaches far better design principles than unit testing ever will&amp;#8221;  
	&lt;ul&gt;
	&lt;li&gt;Oh no!  Not the old &amp;#8220;My language teaches design.&amp;#8221; claim.  We&amp;#8217;ve heard it all before.  They said it about C++, Java, &lt;span class="caps"&gt;COM&lt;/span&gt; (?!), etc&amp;#8230;  The lesson of the &amp;#8216;90s?  &lt;em&gt;Languages don&amp;#8217;t teach design&lt;/em&gt;.  You can make a mess in &lt;em&gt;any&lt;/em&gt; language.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;He says: &amp;#8220;tests can have negative &lt;span class="caps"&gt;ROI&lt;/span&gt;. Not only do they cost a lot to write, they&amp;#8217;re fragile, they&amp;#8217;re always broken, they get in the way of your refactoring, they&amp;#8217;re always having you chase down bogus failures, and the only way to get anything done is to ignore them.&amp;#8221;  
	&lt;ul&gt;
	&lt;li&gt;In one of my favorite episodes of Dr. Who, Tom Baker exits the Tardis, walks up to someone on the street and says: &amp;#8220;Excuse me sir, what planet is this?&amp;#8221;&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;He says: &amp;#8220;What I&amp;#8217;m saying is that it&amp;#8217;s okay if you don&amp;#8217;t write unit tests for everything. You probably have already suspected this for a long time, but now you know. I don&amp;#8217;t want you to feel guilty about it any more.&amp;#8221; 
	&lt;ul&gt;
	&lt;li&gt;Translation: &amp;#8220;&lt;i&gt;I&lt;/i&gt; don&amp;#8217;t want to feel guilty about it anymore so I&amp;#8217;m going to try to convince you&amp;#8230;&amp;#8221;  I sincerely doubt this author has &lt;em&gt;your&lt;/em&gt; best interests at heart.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;He says: &amp;#8220;Debugging is easy, at least in comparison to writing all those tedious tests.&amp;#8221; 
	&lt;ul&gt;
	&lt;li&gt;Refer back to the Dr. Who quote.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;br&gt;
&lt;br&gt;
To quote Barack Obama: &amp;#8220;Enough!&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Has this guy ever done &lt;span class="caps"&gt;TDD&lt;/span&gt;?  I rather doubt it.  Or if he did, he was so inept at it that his tests were &amp;#8220;fragile&amp;#8221;, &amp;#8220;always broken&amp;#8221;, and &amp;#8220;in the way of refactoring&amp;#8221;.  I think he should give it another try and this time spend a bit more time on test design.&lt;/p&gt;


	&lt;p&gt;Perhaps he&amp;#8217;s one of those guys who thought that unit tests were best written &lt;em&gt;after&lt;/em&gt; the code.  Certainly his list of complains makes a lot of sense in that light.  Hint:  If you want to fail at unit testing, write them last.&lt;/p&gt;


	&lt;p&gt;The bottom line is that the guy probably had a bad experience writing unit tests.  He&amp;#8217;s tired of writing them and wants to write fewer of them.  He&amp;#8217;d rather debug.  He thinks he can refactor without tests (which is definitively false).  He thinks he can go faster by writing fewer tests.  Fine, that&amp;#8217;s his choice. And he&amp;#8217;s found a rationalization to support his desires.  Great.&lt;/p&gt;


	&lt;p&gt;I predict that his results will not compare well with those who adopt the discipline of &lt;span class="caps"&gt;TDD&lt;/span&gt;.  I predict that after a few years he&amp;#8217;ll either change his mind, or go into management.&lt;/p&gt;


	&lt;p&gt;Oh, and to the author:  Gesundheit!&lt;/p&gt;</description>
      <pubDate>Thu, 05 Nov 2009 10:35:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:2a532aa7-e2ff-49b1-bfdf-38f1aa9fead9</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/11/05/its-ok-not-to-write-unit-tests-not</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Agile Methods</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Manual Mocking: Resisting the Invasion of Dots and Parentheses</title>
      <description>&lt;p&gt;The twittersphere has been all abuzz today because of something I tweeted early this morning (follow @unclebobmartin).  In my tweet I said that I hand-roll most of my own mock objects in Java, rather than using a mocking framework like &lt;a href="mockito.org"&gt;mockito&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The replies were numerous and vociferous.  Dave Astels poignantly stated that hand-rolling mocks is so 2001!&lt;/p&gt;


	&lt;p&gt;So why do I roll my own mocks?&lt;/p&gt;


Consider the following two tests:
&lt;pre&gt;
public class SelectorTest {
  private List&amp;lt;Object&amp;gt; list;

  @Before
  public void setup() {
    list = new ArrayList&amp;lt;Object&amp;gt;();
    list.add(new Object());
  }

  @Test
  public void falseMatcherShouldSelectNoElements_mockist() {
    Matcher&amp;lt;Object&amp;gt; falseMatcher = mock(Matcher.class);
    Selector&amp;lt;Object&amp;gt; selector = new Selector&amp;lt;Object&amp;gt;(falseMatcher);
    when(falseMatcher.match(anyObject())).thenReturn(false);
    List&amp;lt;Object&amp;gt; selection = selector.select(list);
    assertThat(selection.size(), equalTo(0));
  }

  @Test
  public void falseMatcherShouldSelectNoElements_classic() {
    Matcher&amp;lt;Object&amp;gt; falseMatcher = new FalseMatcher();
    Selector&amp;lt;Object&amp;gt; selector = new Selector&amp;lt;Object&amp;gt;(falseMatcher);
    List&amp;lt;Object&amp;gt; selection = selector.select(list);
    assertThat(selection.size(), equalTo(0));}

  private static class FalseMatcher implements Matcher&amp;lt;Object&amp;gt; {
    public boolean match(Object element) {
      return false;
    }
  }
}
&lt;/pre&gt;

	&lt;p&gt;The first test shows the really cool power of &lt;a href="mockito.org"&gt;mockito&lt;/a&gt; (which is my current favorite in the menagerie of java mocking frameworks).  Just in case you can&amp;#8217;t parse the syntax, let me describe it for you:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;falseMatcher is assigned the return value of the &amp;#8220;mock&amp;#8221; function.  This is a very cool function that takes the argument class and builds a new stubbed object that derives from it.  In mockito, the argument can be a class or an interface.  Cool!&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Now don&amp;#8217;t get all panicy about the strange parenthetic syntax of the &amp;#8216;when&amp;#8217; statement.  The &amp;#8216;when&amp;#8217; statement simply tells the mock what to do when a method is called on it.  In this case it instructs the falseMatcher to return false when the &amp;#8216;match&amp;#8217; function is called with any object at all.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;The second test needs no explanation.&lt;/p&gt;


	&lt;p&gt;...&lt;/p&gt;


	&lt;p&gt;And that&amp;#8217;s kind of the point.  Why would I include a bizzare, dot-ridden, parentheses-laden syntax into my tests, when I can just as easily hand-roll the stub in pure and simple java?  How hard was it to hand-roll that stub?  Frankly, it took a lot less time and effort to hand-roll it than it took to write the (when(myobj.mymethod(anyx())).)()).))); statement.&lt;/p&gt;


	&lt;p&gt;OK, I&amp;#8217;m poking a little fun here.  But it&amp;#8217;s true.  My &lt;span class="caps"&gt;IDE&lt;/span&gt; (InteliJ) generated the stub for me.  I simply started with:&lt;/p&gt;


&lt;pre&gt;
Matcher&amp;lt;Object&amp;gt; falseMatcher = new Matcher&amp;lt;Object&amp;gt;() {};
&lt;/pre&gt;

	&lt;p&gt;InteliJ complained that some methods weren&amp;#8217;t implemented and offered to implement them for me.  I told it to go ahead.  It wrote the &amp;#8216;match&amp;#8217; method exactly as you see it.  Then I chose &amp;#8220;Convert Anonymous to Inner&amp;#8230;&amp;#8221; from the refactoring menu and named the new class FalseMatcher.  Voila!  No muss, no fuss, no parenthetic maze of dots.&lt;/p&gt;


Now look, I&amp;#8217;m not saying you shouldn&amp;#8217;t use mockito, or any of these other mocking tools.  I use them myself when I must.  Here, for example, is a test I wrote in FitNesse.  I was forced to use a mocking framework because I did not have the source code of the classes I was mocking.
&lt;pre&gt;
  @Before
  public void setUp() {
    manager = mock(GSSManager.class);
    properties = new Properties();
  }

  @Test
  public void credentialsShouldBeNonNullIfServiceNamePresent() throws Exception {
    properties.setProperty("NegotiateAuthenticator.serviceName", "service");
    properties.setProperty("NegotiateAuthenticator.serviceNameType", "1.1");
    properties.setProperty("NegotiateAuthenticator.mechanism", "1.2");
    GSSName gssName = mock(GSSName.class);
    GSSCredential gssCredential = mock(GSSCredential.class);
    when(manager.createName(anyString(), (Oid) anyObject(), (Oid) anyObject())).thenReturn(gssName);
    when(manager.createCredential((GSSName) anyObject(), anyInt(), (Oid) anyObject(), anyInt())).thenReturn(gssCredential);
    NegotiateAuthenticator authenticator = new NegotiateAuthenticator(manager, properties);
    Oid serviceNameType = authenticator.getServiceNameType();
    Oid mechanism = authenticator.getMechanism();
    verify(manager).createName("service", serviceNameType, mechanism);
    assertEquals("1.1", serviceNameType.toString());
    assertEquals("1.2", mechanism.toString());
    verify(manager).createCredential(gssName, GSSCredential.INDEFINITE_LIFETIME, mechanism, GSSCredential.ACCEPT_ONLY);
    assertEquals(gssCredential, authenticator.getServerCredentials());
  }
&lt;/pre&gt;

	&lt;p&gt;If I&amp;#8217;d had the source code of the &lt;span class="caps"&gt;GSS&lt;/span&gt; classes, I could have created some very simple stubs and spies that would have allowed me to make these tests a &lt;em&gt;lot&lt;/em&gt; cleaner than they currently appear.  Indeed, I might have been able to test the true &lt;em&gt;behavior&lt;/em&gt; of the classes rather than simply testing that I was calling them appropriately&amp;#8230;&lt;/p&gt;


	&lt;h2&gt;&lt;em&gt;Mockism&lt;/em&gt;&lt;/h2&gt;


	&lt;p&gt;That last bit is pretty important.  Some time ago Martin Fowler wrote a &lt;a href="http://martinfowler.com/articles/mocksArentStubs.html#SoShouldIBeAClassicistOrAMockist"&gt;blog&lt;/a&gt; about the &lt;em&gt;Mockist&lt;/em&gt; and &lt;em&gt;Classical&lt;/em&gt; style of &lt;span class="caps"&gt;TDD&lt;/span&gt;.  In short, &lt;em&gt;Mockists&lt;/em&gt; don&amp;#8217;t test the behavior of the system so much as they test that their classes &amp;#8220;dance&amp;#8221; well with other classes.  That is, they mock/stub out all the other classes that the class under test uses, and then make sure that all the right functions are called in all the right orders with all the right arguments. etc.  There is value to doing this in many cases.  However you can get pretty badly carried away with the approach.&lt;/p&gt;


	&lt;p&gt;The classical approach is to test for desired behavior, and trust that if the test passes, then the class being tested must be dancing well with its partners.&lt;/p&gt;


	&lt;p&gt;Personally, I don&amp;#8217;t belong to either camp.  I sometimes test the choreography, and I sometimes test the behavior.  I test the choreography when I am trying to isolate one part of the system from another.  I test for the behavior when such isolation is not important to me.&lt;/p&gt;


	&lt;p&gt;The point of all this is that I have observed that a heavy dependence on mocking frameworks tends to tempt you towards testing the dance when you &lt;em&gt;should&lt;/em&gt; be testing behavior.  Tools can drive the way we think.  So remember, &lt;em&gt;you&lt;/em&gt; dominate the tool; don&amp;#8217;t let the tool dominate you!&lt;/p&gt;


	&lt;h2&gt;But aren&amp;#8217;t hand-rolled mocks fragile?&lt;/h2&gt;


	&lt;p&gt;Yes, they can be.  If you are mocking a class or interface that it very volatile (i.e. you are adding new methods, or modifying method signatures a lot) then you&amp;#8217;ll have to go back and maintain all your hand-rolled mocks every time you make such a change.  On the other hand, if you use a mocking framework, the framework will take care of that for you unless one of the methods you are specifically testing is modified.&lt;/p&gt;


	&lt;p&gt;But here&amp;#8217;s the thing.  Interfaces should not usually be volatile.  They should not continue to grow and grow, and the methods should not change much.  OK, I realize that&amp;#8217;s wishful thinking.  But, &lt;em&gt;yes&lt;/em&gt;, I wish for the kind of a design in which interfaces are the &lt;em&gt;least&lt;/em&gt; volatile source files that you have.  That&amp;#8217;s kind of the point of interfaces after all&amp;#8230;  You create interfaces so that you can separate volatile implementations from non-volatile clients.  (Or at least that&amp;#8217;s one reason.)&lt;/p&gt;


	&lt;p&gt;So if you are tempted to use a mocking framework because you don&amp;#8217;t want to maintain your volatile interfaces, perhaps you should be asking yourself the more pertinent question about why your interfaces are so volatile.&lt;/p&gt;


	&lt;p&gt;Still, if you&amp;#8217;ve got volatile interfaces, and there&amp;#8217;s just no way around it, then a mocking framework may be the right choice for you.&lt;/p&gt;


	&lt;h2&gt;So here&amp;#8217;s the bottom line.&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;It&amp;#8217;s easy to roll your own stubs and mocks. Your &lt;span class="caps"&gt;IDE&lt;/span&gt; will help you and they&amp;#8217;ll be easier and more natural to read than the dots and parentheses that the mocking frameworks impose upon you.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Mocking frameworks drive you towards testing choreography rather than behavior.  This can be useful, but it&amp;#8217;s not always appropriate.  And besides, even when you are testing choreography, the hand-rolled stubs and mocks are probably easier to write and read.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;There are special cases where mocking tools are &lt;em&gt;invaluable&lt;/em&gt;, specifically when you have to test choreography with objects that you have no source for or when your design has left you with a plethora of volatile interfaces.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Am I telling you to avoid using mocking frameworks?  No, not at all.  I&amp;#8217;m just telling you that &lt;em&gt;you&lt;/em&gt; should drive tools, tools should not drive you.&lt;/p&gt;


	&lt;p&gt;If you have a situation where a mocking tool is the right choice, by all means use it.   But don&amp;#8217;t use it because you think it&amp;#8217;s &amp;#8220;agile&amp;#8221;, or because you think it&amp;#8217;s &amp;#8220;right&amp;#8221; or because you somehow think you are supposed to.  And remember, hand-rolling often results in simpler tests without the litter of dots and parentheses!&lt;/p&gt;</description>
      <pubDate>Wed, 28 Oct 2009 18:12:16 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:55f13a22-2823-4ae4-bd47-d32a1759e267</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/10/28/manual-mocking-resisting-the-invasion-of-dots-and-parentheses</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Agile Methods</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>We must ship now and deal with consequences</title>
      <description>&lt;p&gt;Martin Fowler has written a good &lt;a href="http://martinfowler.com/bliki/TechnicalDebtQuadrant.html"&gt;blog&lt;/a&gt; about technical debt.  He suggests that there are two axes of debt: &lt;em&gt;deliberate&lt;/em&gt; and &lt;em&gt;prudent&lt;/em&gt;.  This creates four quadrants: &lt;em&gt;deliberate-prudent&lt;/em&gt;, &lt;em&gt;deliberate-imprudent&lt;/em&gt;, &lt;em&gt;inadvertent-prudent&lt;/em&gt;, and &lt;em&gt;inadvertent-imprudent&lt;/em&gt;.  I agree with just about everything in his blog except for one particular caption&amp;#8230;&lt;/p&gt;


	&lt;h2&gt;Inadvertent-Imprudent Debt.&lt;/h2&gt;


	&lt;p&gt;There is more of this debt than any other kind.  It is all too common that software developers create a mess and don&amp;#8217;t know they are doing it.  They have not developed a nose that identifies code smells.  They don&amp;#8217;t know design principles, or design patterns.  They think that the reek of rotten code is normal, and don&amp;#8217;t even identify it as smelling bad.  They think that their slow pace through the thick morass of tangled code is the norm, and have no idea they could move faster.  These people destroy projects and bring whole companies to their knees.  Their name is &lt;em&gt;Doom&lt;/em&gt;.&lt;/p&gt;


	&lt;h2&gt;Deliberate-Imprudent Debt.&lt;/h2&gt;


	&lt;p&gt;There is a meme in our industry (call it the DI meme) that tells young software developers that rushing to the finish line at all costs is the right thing to do.  This is far worse than the ignorance of the first group because these folks &lt;em&gt;willfully&lt;/em&gt; create debt without counting the cost.  Worse, this meme is contagious.  People who are infected with it tend to infect others, causing an epidemic of deliberately imprudent debtors (sound familiar?) The end result, as we are now all know, is economic catastrophe, inflation (of estimates) and crushing interest (maintenance) payments.  They have become death, the destroyer of worlds.&lt;/p&gt;


	&lt;h2&gt;Inadvertent-Prudent Debt.&lt;/h2&gt;


	&lt;p&gt;This is something of an oxymoron.  Ironically, it is also the best of all possible states.  The fact is that no matter how careful we are, there is always a better solution that we will stumble upon later.  How many times have you finished a system only to realize that if you wrote it again, you&amp;#8217;d do it very differently, and much better?&lt;/p&gt;


	&lt;p&gt;The result is that we are always creating a debt, because our hindsight will always show us a better option after it is too late.  So even the best outcome still leaves us owing.  (Mother Earth will eventually collect that debt!)&lt;/p&gt;


	&lt;h2&gt;Deliberate-Prudent Debt.&lt;/h2&gt;


	&lt;p&gt;This is the quadrant that I have the biggest problem with.  And it is this quadrant in which Martin uses the caption I don&amp;#8217;t like.  The Caption is: &lt;em&gt;&amp;#8220;We must ship now and deal with consequences.&amp;#8221;&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Does this happen?  Yes.  &lt;em&gt;Should&lt;/em&gt; it happen?  Rarely, yes.  But it damned well better not happen very often, and it damned well better not happen out of some misplaced urge to get done without counting the cost.&lt;/p&gt;


	&lt;p&gt;The problem I have with this quadrant (DP) is that people who are really in quadrant DI &lt;em&gt;think&lt;/em&gt; they are in DP, and use words such as those that appear in the caption as an excuse to rack up a huge imprudent debt.&lt;/p&gt;


	&lt;p&gt;The real issue is the definition of the word: &lt;em&gt;Imprudent&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;So let me ask you a question.  How prudent is debt?  There is a very simple formula for determining whether debt is prudent or imprudent.  You can use this formula in real life, in business, and in programming.  The formula is:  Does the debt increase your net worth, and can you make the payments?&lt;/p&gt;


	&lt;p&gt;People often focus on the first criterion, without properly considering the second.  Buying a house is almost certain to increase your net worth despite the debt (though lately&amp;#8230;).  On the other hand, if you cannot make the payments, you won&amp;#8217;t keep that house for long.  The reason for our current economic woes has a lot to do with people trying to increase their net worth despite the fact that they couldn&amp;#8217;t afford the payments.  (indeed, they were encouraged by a meme very similar to the DI meme!)&lt;/p&gt;


	&lt;h2&gt;Bad code is &lt;em&gt;always&lt;/em&gt; imprudent.&lt;/h2&gt;


	&lt;p&gt;Writing bad code &lt;em&gt;never&lt;/em&gt; increases your net worth; and the interest rate is really high.  People who write bad code are like those twenty-somethings who max out all their credit cards.  Every transaction &lt;em&gt;decreases&lt;/em&gt; net worth, and has horrendous consequences for cash flow.  In the end, the vast bulk of your effort goes to paying the interest (the inevitable slow down of the team as they push the messes around).  Paying down the principle becomes infeasible. (Just the way credit card companies like it.)&lt;/p&gt;


	&lt;h2&gt;Some Suboptimal Design Decision are Prudent Debt.&lt;/h2&gt;


	&lt;p&gt;But most are not.  Every once in awhile there is a suboptimal design decision that will increase the net worth of the project by getting that project into customer&amp;#8217;s hand&amp;#8217;s early.&lt;/p&gt;


	&lt;p&gt;This is not the same as delivering software that is under-featured.  It is often prudent to increase the net worth of a project by giving customers early access to a system without a full and rich feature set.  This is not debt.  This is more like a savings account that &lt;em&gt;earns&lt;/em&gt; interest.&lt;/p&gt;


	&lt;p&gt;Indeed, this is one reason that most technical debt is imprudent.  If you are truly concerned about getting to market early, it is almost always better to do it with &lt;em&gt;fewer features&lt;/em&gt;, than with suboptimal design.  Missing features are a promise that can be kept.  Paying back suboptimal designs creates interest payments that often submerge any attempts at payback and can slow the team to the breaking point.&lt;/p&gt;


	&lt;p&gt;But there &lt;em&gt;are&lt;/em&gt; some cases where a sub-optimal design can increase your net worth by allowing you to deliver early. However, the interest rate needs to be very low, and the principle payments need to be affordable, and big enough to pay back the debt in short order.&lt;/p&gt;


	&lt;p&gt;What does a low interest rate mean?  It means that the sub-optimal design does not infiltrate every part of your system.  It means that you can put the sub-optimal design off in a corner where it doesn&amp;#8217;t impact your daily development life.&lt;/p&gt;


	&lt;p&gt;For example, I recently implemented a feature in FitNesse using &lt;span class="caps"&gt;HTML&lt;/span&gt; Frames.  This is sub-optimal.  On the other hand, the feature is constrained to one small part of the system, and it simply doesn&amp;#8217;t impact any other part of the system.  It does not impede my progress.  There is no mess for me to move around.  The interest rate is almost zero!  (nice deal if you can get it!)&lt;/p&gt;


	&lt;p&gt;Implementing that feature with ajax is a much larger project. I would have had to invest a great deal of time and effort, and would have had to restructure massive amounts of the internal code.  So the choice was a good one.&lt;/p&gt;


	&lt;p&gt;Better yet, the customer experience has pretty much been a big yawn.  I thought people would really like the feature and would drive me to expand upon it.  Instead, the customer base has virtually ignored it.&lt;/p&gt;


	&lt;p&gt;So my solution will be to pay back this debt by eliminating the feature.  It was a cheap experiment, that resulted in my &lt;em&gt;not&lt;/em&gt; having to spend a lot of time and effort on a new architecture!  Net worth indeed!&lt;/p&gt;


	&lt;p&gt;But it might have gone the other way.  My customers may have said: &amp;#8220;Wow, Great! We want more!&amp;#8221;  At that point it would have been &lt;em&gt;terrible&lt;/em&gt; to expand on the &lt;span class="caps"&gt;HTML&lt;/span&gt; Frames!  That decision would have been in the DI quadrant.  Deliberate imprudence!  Rather, my strategy would have been to replace the suboptimal Frames design of the feature with an isolated ajax implementation, and then to gradually migrate the ajax solution throughout the project.  That would have been annoying, but loan payments always are.&lt;/p&gt;


	&lt;h2&gt;Summary&lt;/h2&gt;


	&lt;p&gt;So, don&amp;#8217;t let the caption in the DP quadrant be an excuse.  Don&amp;#8217;t fall for the DI meme that says &amp;#8220;We just gotta bite the bullet&amp;#8221;.  Tread &lt;em&gt;very&lt;/em&gt; carefully when you enter the DP quadrant.  Look around at all your options, because it&amp;#8217;s easy to &lt;em&gt;think&lt;/em&gt; you are in the DP quadrant when you are really in the DI quadrant.&lt;/p&gt;


	&lt;p&gt;Remember: &lt;em&gt;Murphy shall send you strong delusion, that you should believe you are in DP; so that you will be damned in DI.&lt;/em&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 15 Oct 2009 06:17:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:169be751-1a4f-45b8-8429-9eb3820be4a3</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/10/15/we-must-ship-now-and-deal-with-consequences</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
      <category>Agile Methods</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>TDD Derangement Syndrome</title>
      <description>&lt;p&gt;My recent blog about &lt;span class="caps"&gt;TDD&lt;/span&gt;, Design Patterns, Concurrency, and Sudoku seemed to draw the ire of a few vocal &lt;span class="caps"&gt;TDD&lt;/span&gt; detractors.  Some of these people were rude, insulting, derisive, dismissive, and immature.  Well, Halloween is not too far away.&lt;/p&gt;


	&lt;p&gt;In spite of their self-righteous snickering they did ask a few reasonable questions.  To be fair I thought it would be appropriate for me to answer them.&lt;/p&gt;


	&lt;h2&gt;Is there any research on &lt;span class="caps"&gt;TDD&lt;/span&gt;?&lt;/h2&gt;


	&lt;p&gt;It turns out that there is a fair bit.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;One simple google search led me to &lt;a href="http://haacked.com/archive/2008/01/22/research-supports-the-effectiveness-of-tdd.aspx"&gt;this blog&lt;/a&gt; by Phil Haack in which he reviewed a &lt;span class="caps"&gt;TDD&lt;/span&gt; research paper.  Quoting from the paper:&lt;/li&gt;
	&lt;/ul&gt;


	&lt;blockquote&gt;
		&lt;p&gt;We found that test-first students on average wrote more tests and, in turn, students who wrote more tests tended to be more productive. We also observed that the minimum quality increased linearly with the number of programmer tests, independent of the development strategy employed.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;ul&gt;
	&lt;li&gt;The same google search led me to &lt;a href="http://weblogs.asp.net/mhawley/archive/2004/04/15/114005.aspx"&gt;this blog&lt;/a&gt; by Matt Hawley, in which he reviewed several other research papers.  Part of his summary:&lt;/li&gt;
	&lt;/ul&gt;


	&lt;blockquote&gt;
		&lt;p&gt;* 87.5% of developers reported better requirements understanding.
    * 95.8% of developers reported reduced debugging efforts.
    * 78% of developers reported &lt;span class="caps"&gt;TDD&lt;/span&gt; improved overall productivity.
    * 50% of developers found that it decreased overall development time.
    * 92% of developers felt that &lt;span class="caps"&gt;TDD&lt;/span&gt; yielded high-quality code.
    * 79% of developers believed &lt;span class="caps"&gt;TDD&lt;/span&gt; promoted simpler design.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Actually, I recognize some of Matt&amp;#8217;s results as coming from a &lt;a href="http://www.google.com/url?sa=t&amp;#38;source=web&amp;#38;ct=res&amp;#38;cd=1&amp;#38;url=http%3A%2F%2Fcollaboration.csc.ncsu.edu%2Flaurie%2FPapers%2FTDDpaperv8.pdf&amp;#38;ei=WoTMSvSXMYSqtgfDnMjrAQ&amp;#38;usg=AFQjCNHk6TJnNC32UGD8cN65EWGjoQkTBA&amp;#38;sig2=pbzOxiSB7_HAOoBTyDqetQ"&gt;rather famous 2003 study&lt;/a&gt; (also in the list of google results) by Laurie Wiliams and Boby George. This study describes a controlled experiment that they conducted in three different companies.  Though Matt&amp;#8217;s summary above is based (in part) on that study, there is more to say.&lt;/p&gt;


	&lt;p&gt;In the George-William study teams that practiced &lt;span class="caps"&gt;TDD&lt;/span&gt; took 16% &lt;em&gt;longer&lt;/em&gt; to &lt;em&gt;claim that they were done&lt;/em&gt; than the teams that did not practice &lt;span class="caps"&gt;TDD&lt;/span&gt;. Apparently tests are more accurate than claims since the non-TDD teams failed to pass one third of the researcher&amp;#8217;s hidden acceptance tests, whereas the &lt;span class="caps"&gt;TDD&lt;/span&gt; teams passed about 6 out of 7.  To paraphrase Kent Beck: &amp;#8220;If it doesn&amp;#8217;t have to work, I can get it done a &lt;em&gt;lot&lt;/em&gt; faster!&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Another point of interest in this study is that the &lt;span class="caps"&gt;TDD&lt;/span&gt; teams produced a suite of automated tests with &lt;em&gt;very&lt;/em&gt; high test coverage (close to 100% in most cases) whereas most of the non-TDD teams did not produce such a suite; even though they had been instructed to.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Jim Shore wrote a review of &lt;a href="http://jamesshore.com/Blog/AoA-Correction-Test-Driven-Development.html"&gt;yet another research summary&lt;/a&gt; which I found in the same google search.  This one combines 7 different studies (including George-Williams).  Here the results range from dramatically improved quality and productivity to no observed effect.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Finally, there is &lt;a href="http://www.google.com/url?sa=t&amp;#38;source=web&amp;#38;ct=res&amp;#38;cd=4&amp;#38;url=http%3A%2F%2Fresearch.microsoft.com%2Fen-us%2Fprojects%2Fesm%2Fnagappan_tdd.pdf&amp;#38;ei=y4rMSryKDeWltgf6rOXgAQ&amp;#38;usg=AFQjCNGO5ql_sCI2dG5oR6mN8EFBa2OZNA&amp;#38;sig2=U8nr4HFFE6Ezog93OIhRTw"&gt;this&lt;/a&gt; 2008 case Study of &lt;span class="caps"&gt;TDD&lt;/span&gt; at &lt;span class="caps"&gt;IBM&lt;/span&gt; and Microsoft which shows that TDDers enjoy a defect density reduction ranging from 30% to 90% (as measured by defect tracking tools) and a productivity cost of between 15% and 35% (the subjective opinion of the managers).  I refer you back to Kent Beck&amp;#8217;s comment above.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I&amp;#8217;m sure there is more research out there.  After all this was just one google search.  I think it&amp;#8217;s odd that the &lt;span class="caps"&gt;TDD&lt;/span&gt; detractors didn&amp;#8217;t find anything when they did &lt;em&gt;their&lt;/em&gt; google searches.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Oh yeah, and then there was that &lt;a href="http://www2.computer.org/portal/web/csdl/magazines/software#4"&gt;whole issue of &lt;span class="caps"&gt;IEEE&lt;/span&gt; Software&lt;/a&gt; that was dedicated to papers and research on &lt;span class="caps"&gt;TDD&lt;/span&gt;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;What projects have been written with &lt;span class="caps"&gt;TDD&lt;/span&gt;, hmmm?&lt;/h2&gt;


	&lt;p&gt;Quite a few, actually.  The following is a list of projects that have an automated suite of unit tests with very high coverage.  Those that I know for a fact use &lt;span class="caps"&gt;TDD&lt;/span&gt;, I have noted as such.  The others, I can only surmise.  If you know of any others, please post a comment here.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;JUnit.  This one is kind of obvious.  JUnit was written by Kent Beck and Erich Gamma using &lt;span class="caps"&gt;TDD&lt;/span&gt; throughout.  If you measure software success by sheer distribution, this particular program is &lt;em&gt;wildly&lt;/em&gt; successful.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Fit.  Written by Ward Cunningham.  The progenitor of most current acceptance testing frameworks.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;FitNesse.  This testing framework has tens of thousands of users.  It is 70,000 lines of java code, with 90%+ code coverage.  &lt;span class="caps"&gt;TDD&lt;/span&gt; throughout.  Very small bug-list.  Again, if you measure by distribution, another raving success.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Cucumber, &lt;/li&gt;
		&lt;li&gt;Rspec.  These two are Testing frameworks in Ruby.  Of course you&amp;#8217;d expect a testing framework to be written with &lt;span class="caps"&gt;TDD&lt;/span&gt;, wouldn&amp;#8217;t you? I know these were. &lt;span class="caps"&gt;TDD&lt;/span&gt; throughout.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Limelight.  A gui framework in JRUby.  &lt;span class="caps"&gt;TDD&lt;/span&gt; throughout.&lt;/li&gt;
		&lt;li&gt;jfreechart. &lt;/li&gt;
		&lt;li&gt;Spring&lt;/li&gt;
		&lt;li&gt;JRuby&lt;/li&gt;
		&lt;li&gt;Smallsql&lt;/li&gt;
		&lt;li&gt;Ant&lt;/li&gt;
		&lt;li&gt;MarsProject&lt;/li&gt;
		&lt;li&gt;Log4J&lt;/li&gt;
		&lt;li&gt;Jmock&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Are there others?  I&amp;#8217;m sure there are.  This was just a quick web search.  
Again, if you know of more, please add a comment.&lt;/p&gt;</description>
      <pubDate>Wed, 07 Oct 2009 08:32:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:31f3a32e-467c-4c54-9ec8-3b63fe961ff1</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/10/07/tdd-derangement-syndrome</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
      <category>Agile Methods</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Echoes from the Stone Age</title>
      <description>&lt;p&gt;The echoes from Joel Spolsky&amp;#8217;s &lt;a href="http://www.joelonsoftware.com/items/2009/09/23.html"&gt;Duct Tape blog&lt;/a&gt; continue to bounce off the blogosphere and twitterverse.  &lt;a href="http://www.tbray.org/ongoing/When/200x/2009/09/25/On-Duct-Tape"&gt;Tim Bray&lt;/a&gt; and &lt;a href="http://gigamonkeys.com/blog/2009/10/05/coders-unit-testing.html"&gt;Peter Seibel&lt;/a&gt; have both written responses to Joel, me, and each other.&lt;/p&gt;


	&lt;p&gt;Here are some stray thoughts&amp;#8230;&lt;/p&gt;


	&lt;h2&gt;&lt;span class="caps"&gt;TDD&lt;/span&gt;&lt;/h2&gt;


	&lt;p&gt;Anyone who continues to think that &lt;span class="caps"&gt;TDD&lt;/span&gt; slows you down is living in the stone age.  Sorry, that&amp;#8217;s just the truth.  &lt;span class="caps"&gt;TDD&lt;/span&gt; does not slow you down, it speeds you up.&lt;/p&gt;


	&lt;p&gt;Look, &lt;span class="caps"&gt;TDD&lt;/span&gt; is not my religion, it is one of my &lt;em&gt;disciplines&lt;/em&gt;.  It&amp;#8217;s like &lt;em&gt;dual entry bookkeeping&lt;/em&gt; for accountants, or &lt;em&gt;sterile procedure&lt;/em&gt; for surgeons.  Professionals adopt such disciplines because they understand the theory behind them, and have directly experienced the benefits of using them.&lt;/p&gt;


	&lt;p&gt;I have experienced the tremendous benefit that &lt;span class="caps"&gt;TDD&lt;/span&gt; has had in my work, and I have observed it in others.  I have seen and experienced the way that &lt;span class="caps"&gt;TDD&lt;/span&gt; helps programmers conceive their designs.  I have seen and experienced the way it documents their decisions.  I have seen and experienced the decouplings imposed by the tests, and I have seen and experienced the fearlessness with which TDDers can change and clean their code.&lt;/p&gt;


	&lt;p&gt;To be fair, I don&amp;#8217;t think &lt;span class="caps"&gt;TDD&lt;/span&gt; is &lt;em&gt;always&lt;/em&gt; appropriate.  There are situations when I break the discipline and write code before tests.  I&amp;#8217;ll write about these situations in another blog.  However, these situations are few and far between.  In general, for me and many others, &lt;span class="caps"&gt;TDD&lt;/span&gt; is a way to go fast, well, and sure.&lt;/p&gt;


	&lt;p&gt;The upshot of all this is simple.  &lt;span class="caps"&gt;TDD&lt;/span&gt; is a professional discipline.  &lt;span class="caps"&gt;TDD&lt;/span&gt; works.  &lt;span class="caps"&gt;TDD&lt;/span&gt; makes you faster.  &lt;span class="caps"&gt;TDD&lt;/span&gt; is not going away.  And anyone who has not &lt;em&gt;really&lt;/em&gt; tried it, and yet claims that it would slow them down, is simply being willfully ignorant.  I don&amp;#8217;t care if your name is Don Knuth, Jamie Zawinski, Peter Seibel, or Peter Pan.  Give it a &lt;em&gt;real&lt;/em&gt; try, and &lt;em&gt;then&lt;/em&gt; you have the right to comment.&lt;/p&gt;


	&lt;p&gt;Let me put this another way.  And now I&amp;#8217;m talking directly to those who make the claim that &lt;span class="caps"&gt;TDD&lt;/span&gt; would slow them down.  Are you really such a good programmer that you don&amp;#8217;t need to thoroughly check your work?  Can you conceive of a better way to check your work than to express your intent in terms of an executable test?  And can you think of a better way to ensure that you can write that test other than to write it first?&lt;/p&gt;


	&lt;p&gt;If you can, then I want to hear all about it.  but I don&amp;#8217;t want to hear that you write a few unit tests after the fact.  I don&amp;#8217;t want to hear that you manually check your code.  I don&amp;#8217;t want to hear that you &lt;em&gt;do design&lt;/em&gt; and therefore don&amp;#8217;t need to write tests.  Those are all stone-age concepts.  I know.  I&amp;#8217;ve been there.&lt;/p&gt;


	&lt;p&gt;So there. &amp;lt;grin&amp;gt;&lt;/p&gt;


	&lt;h2&gt;The Design Pattern Religion&lt;/h2&gt;


	&lt;p&gt;Tim Bray said:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;My experience suggests that there are few surer ways to doom a big software project than via the Design Patterns religion.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;He&amp;#8217;s right of course.  The Design Patterns &lt;em&gt;religion&lt;/em&gt; is a foul bird that ravages teams and cuts down young projects in their prime.  But let&amp;#8217;s be clear about what that religion is.  The Design Patterns religion is the ardent belief that the use of design patterns is &lt;em&gt;good&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s a clue.  Design Patterns aren&amp;#8217;t good.  They also aren&amp;#8217;t bad.  They just are.  Given a particular software design situation, there may be a pattern that fits and is beneficial.  There may also be patterns that would be detrimental.  It&amp;#8217;s quite possible that none of the currently documented patterns are appropriate and that you should close the book and just solve the problem.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s another clue.  You don&amp;#8217;t &lt;em&gt;use&lt;/em&gt; patterns.  You don&amp;#8217;t &lt;em&gt;apply&lt;/em&gt; patterns.  Patterns just are.  If a particular pattern is appropriate to solve a given problem, then it will be &lt;em&gt;obvious&lt;/em&gt;.  Indeed it is often &lt;em&gt;so&lt;/em&gt; obvious that you don&amp;#8217;t realize that the pattern is in place until you are done.  You look &lt;em&gt;back&lt;/em&gt; at your code and realize: &amp;#8220;Oh, that&amp;#8217;s a Decorator!&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;So am I saying that Design Patterns are useless?&lt;/p&gt;


	&lt;p&gt;NO!  I want you to read the patterns books.  I want you to know those patterns inside and out.  If I point at you and say &amp;#8220;Visitor&amp;#8221; I want you at the board drawing all the different variants of the pattern without hesitation.  I want you to get all the names and roles right.  I want you to &lt;em&gt;know&lt;/em&gt; patterns.&lt;/p&gt;


	&lt;p&gt;But I don&amp;#8217;t want you to &lt;em&gt;use&lt;/em&gt; patterns.  I don&amp;#8217;t want you to &lt;em&gt;believe&lt;/em&gt; in patterns.  I don&amp;#8217;t want you to make patterns into a religion.  Rather I want you to be able to recognize them when they appear, and to &lt;em&gt;regularize&lt;/em&gt; them in your code so that others can recognize them too.&lt;/p&gt;


	&lt;p&gt;Design Patterns have a &lt;em&gt;huge&lt;/em&gt; benefit.  They have &lt;em&gt;names&lt;/em&gt;.  If you are reading code, and you see the word &amp;#8220;Composite&amp;#8221;, and if the author took care to regularize the code to the accepted names and roles of the &amp;#8220;Composite&amp;#8221; pattern, then you will &lt;em&gt;know&lt;/em&gt; what that part of the code is doing instantly.  And &lt;em&gt;that&lt;/em&gt; is powerful!&lt;/p&gt;


	&lt;h2&gt;Minimizing Concurrency.&lt;/h2&gt;


	&lt;p&gt;In my first &lt;a href="http://blog.objectmentor.com/articles/2009/09/24/the-duct-tape-programmer"&gt;Duct Tape blog&lt;/a&gt; I made the statement:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;I found myself annoyed at Joel&amp;rsquo;s notion that most programmers aren&amp;rsquo;t smart enough to use templates, design patterns, multi-threading, &lt;span class="caps"&gt;COM&lt;/span&gt;, etc. I don&amp;rsquo;t think that&amp;rsquo;s the case. I think that any programmer that&amp;rsquo;s not smart enough to use tools like that is probably not smart enough to be a programmer period.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Tim responds with:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;...multi-threading is part of the problem, not part of the solution; that essentially no application programmer understands threads well enough to avoid deadlocks and races and horrible non-repeatable bugs. And that &lt;span class="caps"&gt;COM&lt;/span&gt; was one of the most colossal piles of crap my profession ever foisted on itself.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Is concurrency really part of the problem?  Yes!  Concurrency is a &lt;em&gt;really big&lt;/em&gt; part of the problem.  Indeed, the first rule of concurrency is: &lt;em&gt;&lt;span class="caps"&gt;DON&lt;/span&gt;&amp;#8217;T&lt;/em&gt;.  The second rule is: &lt;em&gt;&lt;span class="caps"&gt;REALLY&lt;/span&gt;, DON&amp;#8217;T&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;The problem is that some times you have no choice.  And in those situations, where you absolutely must use concurrency, &lt;em&gt;you should know it inside and out!&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;I completely and utterly reject the notion that &lt;em&gt;ignorance&lt;/em&gt; is the best defense.  I reject that &lt;em&gt;lack of skill&lt;/em&gt; can &lt;em&gt;ever&lt;/em&gt; be an advantage.  So I want you to &lt;em&gt;know&lt;/em&gt; concurrency.  I want to shout &amp;#8220;Dining Philosophers&amp;#8221; and have you run to the board without hesitation and show me all the different solutions.  If I holler &amp;#8220;Deadlock&amp;#8221;, I want you to quickly identify the causes and solutions.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s a clue.  If you want to avoid using something, &lt;em&gt;know&lt;/em&gt; that something &lt;em&gt;cold&lt;/em&gt;.&lt;/p&gt;


	&lt;h2&gt;Sudoku&lt;/h2&gt;


	&lt;p&gt;At the end of his blog, Peter jumps on the pile of bodies already crushing Ron Jeffries regarding the Sudoku problem from July of 2006.&lt;/p&gt;


	&lt;p&gt;I find the pile-up disturbing.  Ron had the courage to fail in public.  Indeed he announced up front that he might &amp;#8220;crash and burn&amp;#8221;.  And yet he got lambasted for it by people who hid behind someone else&amp;#8217;s work.  The responses to Ron&amp;#8217;s tutorial blogs were completely unfair because the authors of those blogs had everything worked out for them by Dr. Peter Norvig before they published their screeds.  They were comparing apples to oranges because their responses were about the &lt;em&gt;solution&lt;/em&gt; whereas Ron&amp;#8217;s blogs were about the &lt;em&gt;process&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Which one of us has not gone down a rat-hole when hunting for a solution to a complex problem?  Let &lt;em&gt;that&lt;/em&gt; person write the first blog.  Everyone else ought to be a bit more humble.&lt;/p&gt;


	&lt;p&gt;Do the people on the pile think that Ron is unable to solve the Sudoku problem?  (Some have said as much.)  Then they don&amp;#8217;t know Ron very well.  Ron could code them all under the table with one hand tied behind his back.&lt;/p&gt;


	&lt;p&gt;Personal issues aside, I find the discussion fascinating in it&amp;#8217;s own right.  Ron had attempted to solve the Sudoku problem by gaining insight into that problem through the process of coding intermediate solutions.  This is a common enough &lt;span class="caps"&gt;TDD&lt;/span&gt; approach.  Indeed, the &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata"&gt;Bowling Game&lt;/a&gt; and the &lt;a href="http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata"&gt;Prime Factors Kata&lt;/a&gt; are both examples where this approach can work reasonably well.&lt;/p&gt;


	&lt;p&gt;This approach follows the advice of no less than Grady Booch who (quoting Heinlein) said:  &amp;#8220;&lt;em&gt;when faced with a problem you do not understand, do any part of it you do understand, then look at it again.&lt;/em&gt;&amp;#8220;&lt;/p&gt;


	&lt;p&gt;Ron was attempting to use &lt;span class="caps"&gt;TDD&lt;/span&gt; to &lt;em&gt;probe&lt;/em&gt; into the problem to see if he could gain any insight.  This technique often bears fruit.  Sometimes it does not.&lt;/p&gt;


	&lt;p&gt;Here is a classic example.  Imagine you were going to write a sort algorithm test first:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Test 1: Sort an empty array.
Solution: Return the input array.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Test 2: Sort an array with one element.
Solution: Return the input array.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Test 3: Sort an array with two elements.
Solution: Compare the two elements and swap if out of order.  Return the result.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Test 4: Sort an array with three elements.
Solution: Compare the first two and swap if out of order.  Compare the second two and swap if out of order.  Compare the first two again and swap if out of order.  Return the result.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Test 5: Sort an array with four elements.
Solution: Put the compare and swap operations into a nested loop.  Return the result.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;The end result is a bubble sort.  The algorithm virtually self assembles.  If you had never heard of a bubble sort before, this simple set of tests would have driven you to implement it naturally.&lt;/p&gt;


	&lt;p&gt;Problems like Bowling, Prime Factors, and Bubble Sort hold out the interesting promise that &lt;span class="caps"&gt;TDD&lt;/span&gt; may be a way to &lt;em&gt;derive&lt;/em&gt; algorithmms from first principles!&lt;/p&gt;


	&lt;p&gt;On the other hand, what set of tests would drive you to implement a QuickSort?  There are none that I know of.  QuickSort and Sudoku may require a serious amount of introspection and concentrated thought before the solution is apparent.  They may belong to a class of algorithms that do not self-assemble like Bowling, Prime Factors, and Bubble Sort.&lt;/p&gt;


	&lt;p&gt;This &lt;a href="http://www.infoq.com/news/2007/05/tdd-sudoku"&gt;blog&lt;/a&gt; by Kurt Christensen provides all the links to the various Sudoku articles, and sums it up this way.&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;span class="caps"&gt;TDD&lt;/span&gt; may not be the best tool for inventing new algorithms, it may very well be the best tool for applying those algorithms to the problem at hand.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Actually I think &lt;span class="caps"&gt;TDD&lt;/span&gt; is a good way to find out if an algorithm will self-assemble or not.  It usually doesn&amp;#8217;t take a lot of time to figure out which it&amp;#8217;s going to be.&lt;/p&gt;</description>
      <pubDate>Tue, 06 Oct 2009 11:07:29 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:1624b718-36a6-4521-aa4e-14d5b9623dc0</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/10/06/echoes-from-the-stone-age</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>A Mess is not a Technical Debt.</title>
      <description>&lt;p&gt;The term &lt;a href="http://martinfowler.com/bliki/TechnicalDebt.html"&gt;Technical Debt&lt;/a&gt; was created by Ward Cunningham to describe the engineering trade-off&amp;#8217;s that software developers and business stakeholders must often make in order to meet schedules and customer expectations.  In short, you may need to use suboptimal designs in the short term, because the schedule does not allow longer term designs to be used.  As a simple example, your initial website design may need to be frames based because you don&amp;#8217;t have time to build an Ajax framework.&lt;/p&gt;


	&lt;p&gt;Clearly this causes a debt.  If the customer is looking for a web 2.0 system, then frames just aren&amp;#8217;t going to cut it for long.  So time is going to have to be carved out of a future schedule to refit the system with an Ajax solution.&lt;/p&gt;


	&lt;p&gt;In short, the business has decided that it can afford to delay release 2 in order to accelerate release 1.  Is this wise?&lt;/p&gt;


	&lt;p&gt;Businesses make this kind of trade-off all the time; and there&amp;#8217;s nothing inherently unwise about it.  If the early release of 1.0 drives the business that pays for the development of 2.0 then the business has won.  So &lt;em&gt;this kind&lt;/em&gt; of reasoned technical debt may indeed be appropriate.&lt;/p&gt;


	&lt;p&gt;Unfortunately there is another situation that is sometimes called &amp;#8220;technical debt&amp;#8221; but that is neither reasoned nor wise.  A mess.&lt;/p&gt;


	&lt;p&gt;Technical debt may be necessary, but it had also better be &lt;em&gt;clean&lt;/em&gt;!  If you are going to implement a frames solution instead of an &lt;span class="caps"&gt;AJAX&lt;/span&gt; solution, then make sure that the workmanship of the frames solution is top-notch.  Make sure the design is well balanced, and the code is clean.  If you make a mess while implementing that frames solution, you&amp;#8217;ll never be able to replace it with an &lt;span class="caps"&gt;AJAX&lt;/span&gt; framework.  The mess will impede your progress forever.&lt;/p&gt;


	&lt;p&gt;A mess is not a technical debt.  A mess is just a mess.  Technical debt decisions are made based on real project constraints.  They are risky, but they can be beneficial.  The decision to make a mess is never rational, is always based on laziness and unprofessionalism, and has no chance of paying of in the future.  A mess is &lt;em&gt;always&lt;/em&gt; a loss.&lt;/p&gt;


	&lt;p&gt;When you buy a house and take on a big mortgage debt, you tighten up all your spending and accounting.  You clean up your books and your budgets.  You behave with &lt;em&gt;increased&lt;/em&gt; discipline.  The same is true of technical debt.  The more technical debt you take on, the tighter your disciplines need to be.  You should do &lt;em&gt;more&lt;/em&gt; testing, and &lt;em&gt;more&lt;/em&gt; pairing and &lt;em&gt;more&lt;/em&gt; refactoring.  Technical debt is not a license to make a mess.  Technical debt creates the need for even greater cleanliness.&lt;/p&gt;


	&lt;p&gt;When you decide to take on a technical debt, you had better make sure that your code stays squeaky clean.  Keeping the system clean is the only way you will pay down that debt.&lt;/p&gt;</description>
      <pubDate>Tue, 22 Sep 2009 08:15:19 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0d502aec-a625-4ce1-9ad9-6e67aa589b44</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/09/22/a-mess-is-not-a-technical-debt</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>The CSM Integrity Deficit</title>
      <description>&lt;p&gt;Scott Ambler wrote a &lt;a href="https://www.ibm.com/developerworks/mydeveloperworks/blogs/ambler/entry/integrity_debt"&gt;blog&lt;/a&gt;, and an &lt;a href="http://www.ambysoft.com/certification/scam.html"&gt;editorial&lt;/a&gt; about the dirty dealings and desperate deception of the Scrum Alliance and their slimy certification scam.  He rightly points out that the &lt;em&gt;certification&lt;/em&gt; means little more than the applicant&amp;#8217;s check didn&amp;#8217;t bounce.&lt;/p&gt;


	&lt;p&gt;He goes on to imply that the entire agile community is guilty of keeping silent while this huge chicanery was foisted upon an innocent industry.  He calls this conspiratorial silence: &lt;em&gt;&amp;#8220;integrity debt&amp;#8221;&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Oh bollux!  What an incredible load of Dingoes Kidneys!&lt;/p&gt;


	&lt;p&gt;Look.  I&amp;#8217;m not a big fan of &lt;span class="caps"&gt;CSM&lt;/span&gt;.  I think it&amp;#8217;s a gimmick. I am not a &lt;span class="caps"&gt;CSM&lt;/span&gt; myself, and have no intention of joining their ranks.  When I meet someone who proclaims themselves to be a &lt;span class="caps"&gt;CSM&lt;/span&gt;, I&amp;#8217;m not particularly impressed.  I know what that certification means, and I take it with a grain of salt.  To me, the title of &lt;span class="caps"&gt;CSM&lt;/span&gt; is worth little more than a shrug.&lt;/p&gt;


	&lt;p&gt;We at Object Mentor do a lot of training in things like Test Driven Development, Agile Methods. Object Oriented Principles, Java, C#, etc. etc.  At the end of every course we often sign and pass out certificates to the students.  Those certificates proclaim that the student attended the course.  I see no difference between that certificate (which is a certification after all) and the &lt;span class="caps"&gt;CSM&lt;/span&gt; certificate.  I suppose the students who take our &lt;span class="caps"&gt;TDD&lt;/span&gt; course could claim to be &lt;em&gt;Object Mentor Certified TDDers&lt;/em&gt;; and they&amp;#8217;d be right.&lt;/p&gt;


	&lt;p&gt;Have we created an &amp;#8220;Integrity Debt&amp;#8221; by handing out those certificates?  Of course not.  Everybody knows exactly what they mean.  Nobody misrepresents their intent.  They are an honest statement of fact.  And the same is true of the &lt;span class="caps"&gt;CSM&lt;/span&gt; certificate.&lt;/p&gt;


	&lt;p&gt;Is it troubling that some HR people are starting to put &lt;span class="caps"&gt;CSM&lt;/span&gt; requirements on Job postings?  Not at all!  It is perfectly within the rights of any company to decide that they want to hire people who have been appropriately trained.  Are there some HR people who overestimate the value of &lt;span class="caps"&gt;CSM&lt;/span&gt;?  Probably, but that&amp;#8217;s their own fault.&lt;/p&gt;


	&lt;p&gt;In my humble opinion there is no significant integrity issue here.  Oh it wouldn&amp;#8217;t surprise me to learn that there might have been some back-door deals in the early days of &lt;span class="caps"&gt;CSM&lt;/span&gt;.  Perhaps some people were given &lt;span class="caps"&gt;CST&lt;/span&gt; status, or &lt;span class="caps"&gt;CSM&lt;/span&gt; status without careful controls.  If that happened, I chalk it up to birthing pains which the Scrum Alliance is striving to correct.  I don&amp;#8217;t think anybody was out to scam anybody else.  I don&amp;#8217;t think &lt;span class="caps"&gt;CSM&lt;/span&gt; is a far flung conspiracy to ruin the software industry, and I don&amp;#8217;t think the US government flew those jets into the twin towers.&lt;/p&gt;


	&lt;p&gt;Bottom line.  There is no &lt;em&gt;&amp;#8220;Integrity Debt&amp;#8221;&lt;/em&gt; here. What there &lt;em&gt;is&lt;/em&gt; is a group of honest and caring folks who are trying to figure out the best ways to get Agile concepts adopted in an industry that &lt;em&gt;sorely&lt;/em&gt; needs them.&lt;/p&gt;


	&lt;p&gt;In that regard I think that the agile movement has enjoyed a significant &lt;em&gt;boost&lt;/em&gt; because of the interest generated by the &lt;span class="caps"&gt;CSM&lt;/span&gt; program.  There are more companies doing Agile today because of &lt;span class="caps"&gt;CSM&lt;/span&gt;.  So if anybody owes a debt here, it may be the Agile community owing a debt to the &lt;span class="caps"&gt;CSM&lt;/span&gt; program.&lt;/p&gt;


	&lt;p&gt;Maybe, instead of accusing and castigating and pointing the finger of judgement and doom we ought give a salute to Ken Schwaber, and say: &amp;#8220;Thanks Ken.&amp;#8221;&lt;/p&gt;</description>
      <pubDate>Fri, 18 Sep 2009 08:44:43 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:2ae0ff36-9f77-4c49-b236-0d4853d9176c</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/09/18/the-csm-integrity-deficit</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Agile Methods</category>
    </item>
    <item>
      <title>One Thing: Extract till you Drop.</title>
      <description>&lt;p&gt;For years authors and consultants (like me) have been telling us that functions should do &lt;em&gt;one thing&lt;/em&gt;.  They should do it well.  They should do it only.&lt;/p&gt;


	&lt;p&gt;The question is: What the hell does &amp;#8220;one thing&amp;#8221; mean?&lt;/p&gt;


	&lt;p&gt;After all, one man&amp;#8217;s &amp;#8220;one thing&amp;#8221; might be someone else&amp;#8217;s &amp;#8220;two things&amp;#8221;.&lt;/p&gt;


Consider this class:
&lt;pre&gt;
  class SymbolReplacer {
    protected String stringToReplace;
    protected List&amp;lt;String&amp;gt; alreadyReplaced = new ArrayList&amp;lt;String&amp;gt;();

    SymbolReplacer(String s) {
      this.stringToReplace = s;
    }

    String replace() {
      Pattern symbolPattern = Pattern.compile("\\$([a-zA-Z]\\w*)");
      Matcher symbolMatcher = symbolPattern.matcher(stringToReplace);
      while (symbolMatcher.find()) {
        String symbolName = symbolMatcher.group(1);
        if (getSymbol(symbolName) != null &amp;#38;&amp;#38; !alreadyReplaced.contains(symbolName)) {
          alreadyReplaced.add(symbolName);
          stringToReplace = stringToReplace.replace("$" + symbolName, translate(symbolName));
        }
      }
      return stringToReplace;
    }

    protected String translate(String symbolName) {
      return getSymbol(symbolName);
    }
  }
&lt;/pre&gt;

	&lt;p&gt;It&amp;#8217;s not too hard to understand.  The &lt;span style="font-family:courier;"&gt;replace()&lt;/span&gt; function searches through a string looking for &lt;em&gt;$NAME&lt;/em&gt; and replaces each instance with the appropriate translation of &lt;em&gt;&lt;span class="caps"&gt;NAME&lt;/span&gt;&lt;/em&gt;.  It also makes sure that it doesn&amp;#8217;t replace a name more than once.  Simple.&lt;/p&gt;


	&lt;p&gt;Of course the words &amp;#8220;It also&amp;#8230;&amp;#8221; pretty much proves that this function does more than one thing.  So we can probably split the function up into two functions as follows:&lt;/p&gt;


&lt;pre&gt;
    String replace() {
      Pattern symbolPattern = Pattern.compile("\\$([a-zA-Z]\\w*)");
      Matcher symbolMatcher = symbolPattern.matcher(stringToReplace);
      while (symbolMatcher.find()) {
        String symbolName = symbolMatcher.group(1);
        replaceAllInstances(symbolName);
      }
      return stringToReplace;
    }

    private void replaceAllInstances(String symbolName) {
      if (getSymbol(symbolName) != null &amp;#38;&amp;#38; !alreadyReplaced.contains(symbolName)) {
        alreadyReplaced.add(symbolName);
        stringToReplace = stringToReplace.replace("$" + symbolName, translate(symbolName));
      }
    }
&lt;/pre&gt;

	&lt;p&gt;OK, so now the &lt;span style="font-family:courier;"&gt;replace()&lt;/span&gt; function simply finds all the symbols that need replacing, and the &lt;span style="font-family:courier;"&gt;replaceAllInstances()&lt;/span&gt; function replaces them if they haven&amp;#8217;t already been replaced.  So do these function do one thing each?&lt;/p&gt;


	&lt;p&gt;Well, the &lt;span style="font-family:courier;"&gt;replace()&lt;/span&gt; compiles the pattern and build the &lt;span style="font-family:courier;"&gt;Matcher()&lt;/span&gt;  Maybe those actions should be moved into the constructor?&lt;/p&gt;


&lt;pre&gt;
  class SymbolReplacer {
    protected String stringToReplace;
    protected List&amp;lt;String&amp;gt; alreadyReplaced = new ArrayList&amp;lt;String&amp;gt;();
    private Matcher symbolMatcher;
    private final Pattern symbolPattern = Pattern.compile("\\$([a-zA-Z]\\w*)");

    SymbolReplacer(String s) {
      this.stringToReplace = s;
      symbolMatcher = symbolPattern.matcher(s);
    }

    String replace() {
      while (symbolMatcher.find()) {
        String symbolName = symbolMatcher.group(1);
        replaceAllInstances(symbolName);
      }
      return stringToReplace;
    }

    private void replaceAllInstances(String symbolName) {
      if (getSymbol(symbolName) != null &amp;#38;&amp;#38; !alreadyReplaced.contains(symbolName)) {
        alreadyReplaced.add(symbolName);
        stringToReplace = stringToReplace.replace("$" + symbolName, translate(symbolName));
      }
    }

    protected String translate(String symbolName) {
      return getSymbol(symbolName);
    }
  }
&lt;/pre&gt;

	&lt;p&gt;OK, so &lt;em&gt;now&lt;/em&gt; certainly the &lt;span style="font-family:courier;"&gt;replace()&lt;/span&gt; function is doing &lt;em&gt;one thing&lt;/em&gt;?  Ah, but I see at least two.  It loops, extracts the &lt;span style="font-family:courier;"&gt;symbolName&lt;/span&gt; and then does the replace.  OK, so how about this?&lt;/p&gt;


&lt;pre&gt;
    String replace() {
      for (String symbolName = nextSymbol(); symbolName != null; symbolName = nextSymbol())
        replaceAllInstances(symbolName);

      return stringToReplace;
    }

    private String nextSymbol() {
      return symbolMatcher.find() ? symbolMatcher.group(1) : null;
    }
&lt;/pre&gt;

	&lt;p&gt;I had to restructure things a little bit.  The loop is a bit ugly.  I wish I could have said &lt;span style="font-family:courier;"&gt;for (String symbolName : symbolMatcher)&lt;/span&gt; but I guess &lt;span style="font-family:courier;"&gt;Matchers&lt;/span&gt; don&amp;#8217;t work that way.&lt;/p&gt;


	&lt;p&gt;I kind of like the &lt;span style="font-family:courier;"&gt;nextSymbol()&lt;/span&gt; function.  It gets the &lt;span style="font-family:courier;"&gt;Matcher&lt;/span&gt; nicely out of the way.&lt;/p&gt;


	&lt;p&gt;So now the &lt;span style="font-family:courier;"&gt;replace()&lt;/span&gt; and &lt;span style="font-family:courier;"&gt;nextSymbol()&lt;/span&gt; functions are &lt;em&gt;certainly&lt;/em&gt; doing one thing.  Aren&amp;#8217;t they?&lt;/p&gt;


	&lt;p&gt;Well, I suppose I could separate the loop from the return in &lt;span style="font-family:courier;"&gt;replace()&lt;/span&gt;.&lt;/p&gt;


&lt;pre&gt;
    String replace() {
      replaceAllSymbols();
      return stringToReplace;
    }

    private void replaceAllSymbols() {
      for (String symbolName = nextSymbol(); symbolName != null; symbolName = nextSymbol())
        replaceAllInstances(symbolName);
    }
&lt;/pre&gt;

	&lt;p&gt;I don&amp;#8217;t see how I could make these functions smaller.  They &lt;em&gt;must&lt;/em&gt; be doing &lt;em&gt;one thing&lt;/em&gt;.  There&amp;#8217;s no way to extract any other functions from them!&lt;/p&gt;


	&lt;p&gt;Uh&amp;#8230;  Wait.  Is &lt;em&gt;that&lt;/em&gt; the definition of &lt;em&gt;one thing&lt;/em&gt;?  Is a function doing &lt;em&gt;one thing&lt;/em&gt; if, and only if, you simply cannot extract any other functions from it?  What else &lt;em&gt;could&lt;/em&gt; &amp;#8220;one thing&amp;#8221; mean?  After all, If I can extract one function out of another, the original function must have been doing more than one thing.&lt;/p&gt;


	&lt;p&gt;So does that mean that for all these years the authors and consultants (like me) have been telling us to extract until you can&amp;#8217;t extract anymore?&lt;/p&gt;


Let&amp;#8217;s try that with the rest of this class and see what it looks like&amp;#8230;
&lt;pre&gt;
  class SymbolReplacer {
    protected String stringToReplace;
    protected List&amp;lt;String&amp;gt; alreadyReplaced = new ArrayList&amp;lt;String&amp;gt;();
    private Matcher symbolMatcher;
    private final Pattern symbolPattern = Pattern.compile("\\$([a-zA-Z]\\w*)");

    SymbolReplacer(String s) {
      this.stringToReplace = s;
      symbolMatcher = symbolPattern.matcher(s);
    }

    String replace() {
      replaceAllSymbols();
      return stringToReplace;
    }

    private void replaceAllSymbols() {
      for (String symbolName = nextSymbol(); symbolName != null; symbolName = nextSymbol())
        replaceAllInstances(symbolName);
    }

    private String nextSymbol() {
      return symbolMatcher.find() ? symbolMatcher.group(1) : null;
    }

    private void replaceAllInstances(String symbolName) {
      if (shouldReplaceSymbol(symbolName))
        replaceSymbol(symbolName);
    }

    private boolean shouldReplaceSymbol(String symbolName) {
      return getSymbol(symbolName) != null &amp;#38;&amp;#38; !alreadyReplaced.contains(symbolName);
    }

    private void replaceSymbol(String symbolName) {
      alreadyReplaced.add(symbolName);
      stringToReplace = stringToReplace.replace(
        symbolExpression(symbolName), 
        translate(symbolName));
    }

    private String symbolExpression(String symbolName) {
      return "$" + symbolName;
    }

    protected String translate(String symbolName) {
      return getSymbol(symbolName);
    }
  }
&lt;/pre&gt;

	&lt;p&gt;Well, I think it&amp;#8217;s pretty clear that each of these functions is doing &lt;em&gt;one thing&lt;/em&gt;.  I&amp;#8217;m not sure how I&amp;#8217;d extract anything further from any of them.&lt;/p&gt;


	&lt;p&gt;Perhaps you think this is taking things too far.  I used to think so too.  But after programming for over 40+ years, I&amp;#8217;m beginning to come to the conclusion that this level of extraction is not taking things too far at all.  In fact, to me, it looks just about right.&lt;/p&gt;


	&lt;p&gt;So, my advice: Extract till you just can&amp;#8217;t extract any more.  Extract till you drop.&lt;/p&gt;


	&lt;p&gt;After all, with modern tools it takes &lt;em&gt;very&lt;/em&gt; little time.  It makes each function almost trivial.  The code reads very nicely.  It forces you to put little snippets of code into nicely named functions.  And, well gosh, extracting till you drop is kind of fun!&lt;/p&gt;</description>
      <pubDate>Fri, 11 Sep 2009 13:33:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:fa921995-cdc4-4867-8541-9bfa9a2834e4</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/09/11/one-thing-extract-till-you-drop</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
      <category>Design Principles</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Jarvis March in Clojure</title>
      <description>&lt;p&gt;OK, all you Clojure gurus, I need your help.  I need to speed this algorithm up.&lt;/p&gt;


	&lt;p&gt;Just for fun I thought I&amp;#8217;d write the Jarvis March algorithm in Clojure.  This algorithm is for finding the convex hull of a collection of points.  The basic idea is really simple.  Imagine that all the points in the collection are represented by nails in a board.  Find the left-most nail and tie a string to it.  Then wind the string around the nails.  The string will only touch nails that are part of the convex hull.&lt;/p&gt;


	&lt;p&gt;The details are not really that much more difficult.  You start at the left-most point and calculate the angle from vertical required to touch every other point.  The point with the minimum angle is the next point.  You keep going around looking finding points with the minimum angle that is greater than the previous angle. When you get back to the starting point you are done.&lt;/p&gt;


	&lt;p&gt;Calculating angles can be time consuming, so I use a psuedo-angle algorithm.  It doesn&amp;#8217;t calculate the actual angle, rather it is a function that increases with the true angle, and goes from [0, 4).&lt;/p&gt;


The code is pretty simple.  
&lt;pre&gt;
(ns convexHull.convex-hull
  (:use clojure.contrib.math))

(defn quadrant-one-pseudo-angle [dx dy]
  (/ dx (+ dy dx)))

(defn pseudo-angle [[dx dy]]
  (cond
    (and (= dx 0) (= dy 0))
    0

    (and (&amp;gt;= dx 0) (&amp;gt; dy 0))
    (quadrant-one-pseudo-angle dx dy)

    (and (&amp;gt; dx 0) (&amp;lt;= dy 0))
    (+ 1 (quadrant-one-pseudo-angle (abs dy) dx))

    (and (&amp;lt;= dx 0) (&amp;lt; dy 0))
    (+ 2 (quadrant-one-pseudo-angle (abs dx) (abs dy)))

    (and (&amp;lt; dx 0) (&amp;gt;= dy 0))
    (+ 3 (quadrant-one-pseudo-angle dy (abs dx)))

    :else nil))

(defn point-min [[x1 y1 :as p1] [x2 y2 :as p2]]
  (cond
    (&amp;lt; x1 x2)
    p1

    (= x1 x2)
    (if (&amp;lt; y1 y2) p1 p2)

    :else
    p2))

(defn find-min-point [points]
  (reduce point-min points))

(defn delta-point [[x1 y1] [x2 y2]]
  [(- x1 x2) (- y1 y2)])

(defn angle-and-point [point base]
  [(pseudo-angle (delta-point point base)) point])

(defn min-angle-and-point [ap1 ap2]
  (if (&amp;lt; (first ap1) (first ap2)) ap1 ap2))

(defn find-point-with-least-angle-from [base angle points]
  (reduce min-angle-and-point
    (remove
      #(&amp;lt; (first %) angle)
      (map #(angle-and-point % base)
        (remove
          (fn [p] (= base p))
          points)))))

(defn hull [points]
  (println "Start")
  (let [starting-point (find-min-point points)]
    (println starting-point)
    (loop [hull-list [starting-point] angle 0 last-point starting-point]
      (let [[angle next-point] (find-point-with-least-angle-from last-point angle points)]
        (if (= next-point (first hull-list))
          hull-list
          (recur (conj hull-list next-point) angle next-point))))))
&lt;/pre&gt;

I execute it with this:
&lt;pre&gt;
(ns convexHull.time-hull
  (:use convexHull.convex-hull))

(def r (java.util.Random.))
(defn rands [] (repeatedly #(.nextGaussian r)))
(defn points [] (take 400000 (partition 2 (rands))))
(let [hull-points (time (hull (points)))]
  (printf "Points: %d\n" (count hull-points))
  (doseq [x hull-points] (println x)))
&lt;/pre&gt;

	&lt;p&gt;This takes &lt;em&gt;way&lt;/em&gt; too long to run.  The equivalent java program will do a million points in half a second.  This one is taking 25 seconds to do a half-million points.  It won&amp;#8217;t even &lt;em&gt;do&lt;/em&gt; a million points.  It slows way way down and then runs out of memory.  (There must be some kind of disk caching going on or something.)&lt;/p&gt;


	&lt;p&gt;Anyway, I&amp;#8217;d be interested in seeing how a real Clojure programmer would speed this program up.&lt;/p&gt;</description>
      <pubDate>Tue, 11 Aug 2009 21:10:21 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:fd5cfe9d-1538-4efa-9664-44c3c855f848</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/08/11/jarvis-march-in-clojure</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Using Clojure for Scripting</title>
      <description>&lt;p&gt;Clojure makes a nice language for writing scripts that explore things on the filesystem.  For example, here is a cute little program that explores the FitNesse source tree counting the lines of production java code and comparing it to the lines of unit test code.&lt;/p&gt;


&lt;pre&gt;

(use 'clojure.contrib.duck-streams)

(def file-counts
  (map
    #(list (.toString %) (count (read-lines %)))
    (remove #(.isDirectory %)
      (file-seq (file-str "~/projects/FitNesseGit/src/fitnesse")))))

(defn count-lines-that-end-with [file-counts suffix]
  (reduce +
    (map second
      (filter #(.endsWith (first %) suffix) file-counts))))

(def java-count (count-lines-that-end-with file-counts ".java"))
(def test-count (count-lines-that-end-with file-counts "Test.java"))

(printf "Java lines: %d\n" java-count)
(printf "Test lines: %d\n" test-count)
(printf "Test pct: %.1f\n" (double (* 100 (/ test-count java-count))))
&lt;/pre&gt;</description>
      <pubDate>Sat, 08 Aug 2009 14:14:07 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ada5a2eb-c1fa-4853-905f-7cdcd02d8d60</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/08/08/using-clojure-for-scripting</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Java calling Clojure.</title>
      <description>&lt;p&gt;While I think Clojure is an interesting language, in order for it to be of real practical use, I must be able to use it in conjunction with other systems I am working on.  Specifically, I&amp;#8217;d like to write some FitNesse tools in Clojure;  but for that to work, I&amp;#8217;ll need to call into my Clojure code from Java.&lt;/p&gt;


	&lt;p&gt;Today, my son Justin and I managed to do just that by following the instruction in Stuart Halloway&amp;#8217;s &lt;a href="http://www.pragprog.com/titles/shcloj/programming-clojure"&gt;book&lt;/a&gt;, the Clojure api &lt;a href="http://clojure.org/api#toc388"&gt;website&lt;/a&gt;, and Mark Volkmann&amp;#8217;s very useful &lt;a href="http://java.ociweb.com/mark/clojure/article.html"&gt;site&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Be advised, that it takes a bit of fiddling to get this to work.  You will have to jockey around with your classpaths and output directories.  But it&amp;#8217;s not actually that hard to do, and the results can be very rewarding.&lt;/p&gt;


	&lt;p&gt;We implemented the Bowling game (again), but this time we wrote the unit tests in Java, and had them call into Clojure.  From the point of view of the Java tests, it looked just like we were calling into java code.  The tests had no idea that this was Clojure.&lt;/p&gt;


Here are the tests:
&lt;pre&gt;
package bowling;

import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;

public class BowlingTest {
  private Game g;

  @Before
  public void setup() {
    g = new Game();
  }

  @Test
  public void roll() throws Exception {
    g.roll(0);
  }

  @Test
  public void gutterGame() throws Exception {
    rollMany(20, 0);
    assertEquals(0, g.score());
  }

  private void rollMany(int n, int pins) {
    for (int i=0; i&amp;lt; n; i++) {
      g.roll(pins);
    }
  }

  @Test
  public void allOnes() throws Exception {
    rollMany(20, 1);
    assertEquals(20, g.score());    
  }

  @Test
  public void oneSpare() throws Exception {
    g.roll(5);
    g.roll(5);
    g.roll(3);
    rollMany(17, 0);
    assertEquals(16, g.score());
  }

  @Test
  public void oneStrike() throws Exception {
    g.roll(10);
    g.roll(5);
    rollMany(17,0);
    assertEquals(20, g.score());
  }

  @Test
  public void perfectGame() throws Exception {
    rollMany(12, 10);
    assertEquals(300, g.score());
  }

  @Test
  public void allSpares() throws Exception {
    rollMany(21, 5);
    assertEquals(150, g.score());
  }
}
&lt;/pre&gt;

The clojure code to make them pass looks like this:
&lt;pre&gt;
(ns bowling.Game
  (:gen-class
    :state state
    :init init
    :methods [
    [roll [int] void]
    [score [] int]
    ]))

(defn -init [] [[] (atom [])])

(defn -roll [this pins]
  (reset! (.state this) (conj @(.state this) pins)))

(declare score-frames)

(defn -score [this]
  (reduce + (take 10 (score-frames [] (conj @(.state this) 0)))))

(defn score-frames [scores [first second third :as rolls]]
  (cond
    (or (empty? rolls) (nil? second) (nil? third)) scores
    (= 10 first) (recur (conj scores (+ 10 second third)) (next rolls))
    (= 10 (+ first second)) (recur (conj scores (+ 10 third)) (nnext rolls))
    :else
    (recur (conj scores (+ first second)) (nnext rolls))))
&lt;/pre&gt;

	&lt;p&gt;The magic is all up in that (ns bowling.game&amp;#8230; block.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;The name of the java class is Game in the bowling package, or just bowling.Game.&lt;/li&gt;
		&lt;li&gt;Clojure will create a special member function named &lt;em&gt;state&lt;/em&gt; that you can use to squirrel away the state variables of the class.&lt;/li&gt;
		&lt;li&gt;A function named &lt;em&gt;-init&lt;/em&gt; will be called when your class is constructed.  You must write this function to return a vector containing 1) a vector of all the arguments to pass to the base class constructor (in my case none), and the initial state of the newly created instance, (in my case an empty vector stuffed into an atom)  &lt;/li&gt;
		&lt;li&gt;The class will have two new methods, &lt;em&gt;roll&lt;/em&gt;, which takes an int and returns void, and &lt;em&gt;score&lt;/em&gt; which takes nothing and returns an int.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;When a method is called on the instance, Clojure automatically invokes a function of the same name, but prefixed by a -, so -roll and -score are the implementations of the &lt;em&gt;roll&lt;/em&gt; and &lt;em&gt;score&lt;/em&gt; methods.  Note that each of these functions take a &lt;em&gt;this&lt;/em&gt; argument.  You can get the state out of &lt;em&gt;this&lt;/em&gt; by saying (.state this).&lt;/p&gt;


	&lt;p&gt;From a source code point of view, that&amp;#8217;s about all there is to it.  But how do you compile this into a java .class file?&lt;/p&gt;


Here&amp;#8217;s what we did.  We created a new file named compile.clj that looks like this:
&lt;pre&gt;
(set! *compile-path* "../../classes")
(compile 'bowling.Game)
&lt;/pre&gt;
We can run this file from our &lt;span class="caps"&gt;IDE&lt;/span&gt; (IntelliJ using the LAClojure plugin) and it will compile quite nicely.  But there are a few things you have to make sure you do.

	&lt;ul&gt;
	&lt;li&gt;Find out where your &lt;span class="caps"&gt;IDE&lt;/span&gt; puts the .class files, and set the &lt;em&gt;&lt;strong&gt;compile-path&lt;/strong&gt;&lt;/em&gt; variable to that directory.&lt;/li&gt;
		&lt;li&gt;Also make sure that directory is in your classpath.&lt;/li&gt;
		&lt;li&gt;Make sure that directory exists!&lt;/li&gt;
		&lt;li&gt;Also make sure that your source file directory (the directory that contains the packages) is in your classpath. (I know&amp;#8230; but that&amp;#8217;s apparently what it takes.)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;You will get errors.  And the errors aren&amp;#8217;t particularly informative.  The key to understanding them is to look at the backtrace of the exceptions they throw.  Notice, for example, if the function &amp;#8220;WriteClassFile&amp;#8221; (or something like that) is buried in the backtrace.  If so, you are probably having trouble writing your class file.&lt;/p&gt;


	&lt;p&gt;In the end, we wrote up an ant script that compiled our clojure and our java together.  (You have to compile them in the right order!  If java calls Clojure, those .class files have to exist before the java will compile!)&lt;/p&gt;


	&lt;p&gt;The ant script we used was created for us by IntelliJ, and then we modified it to get it to work.  I include it here with the caveat that we made it work, but we didn&amp;#8217;t make it &amp;#8220;right&amp;#8221;.   You can ignore most of the stuff at the beginning.  The interesting part is the &lt;em&gt;Clojure&lt;/em&gt; target, and the &lt;em&gt;clean&lt;/em&gt; target.&lt;/p&gt;


&lt;pre&gt;
&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;project name="bowlingforjunit" default="all"&amp;gt;

  &amp;lt;property file="bowlingforjunit.properties"/&amp;gt;
  &amp;lt;!-- Uncomment the following property if no tests compilation is needed --&amp;gt;
  &amp;lt;!-- 
  &amp;lt;property name="skip.tests" value="true"/&amp;gt;
   --&amp;gt;

  &amp;lt;!-- Compiler options --&amp;gt;

  &amp;lt;property name="compiler.debug" value="on"/&amp;gt;
  &amp;lt;property name="compiler.generate.no.warnings" value="off"/&amp;gt;
  &amp;lt;property name="compiler.args" value=""/&amp;gt;
  &amp;lt;property name="compiler.max.memory" value="128m"/&amp;gt;
  &amp;lt;patternset id="ignored.files"&amp;gt;
    &amp;lt;exclude name="**/CVS/**"/&amp;gt;
    &amp;lt;exclude name="**/SCCS/**"/&amp;gt;
    &amp;lt;exclude name="**/RCS/**"/&amp;gt;
    &amp;lt;exclude name="**/rcs/**"/&amp;gt;
    &amp;lt;exclude name="**/.DS_Store/**"/&amp;gt;
    &amp;lt;exclude name="**/.svn/**"/&amp;gt;
    &amp;lt;exclude name="**/.pyc/**"/&amp;gt;
    &amp;lt;exclude name="**/.pyo/**"/&amp;gt;
    &amp;lt;exclude name="**/*.pyc/**"/&amp;gt;
    &amp;lt;exclude name="**/*.pyo/**"/&amp;gt;
    &amp;lt;exclude name="**/.git/**"/&amp;gt;
    &amp;lt;exclude name="**/.sbas/**"/&amp;gt;
    &amp;lt;exclude name="**/.IJI.*/**"/&amp;gt;
    &amp;lt;exclude name="**/vssver.scc/**"/&amp;gt;
    &amp;lt;exclude name="**/vssver2.scc/**"/&amp;gt;
  &amp;lt;/patternset&amp;gt;
  &amp;lt;patternset id="library.patterns"&amp;gt;
    &amp;lt;include name="*.zip"/&amp;gt;
    &amp;lt;include name="*.war"/&amp;gt;
    &amp;lt;include name="*.egg"/&amp;gt;
    &amp;lt;include name="*.ear"/&amp;gt;
    &amp;lt;include name="*.swc"/&amp;gt;
    &amp;lt;include name="*.jar"/&amp;gt;
  &amp;lt;/patternset&amp;gt;
  &amp;lt;patternset id="compiler.resources"&amp;gt;
    &amp;lt;include name="**/?*.properties"/&amp;gt;
    &amp;lt;include name="**/?*.xml"/&amp;gt;
    &amp;lt;include name="**/?*.gif"/&amp;gt;
    &amp;lt;include name="**/?*.png"/&amp;gt;
    &amp;lt;include name="**/?*.jpeg"/&amp;gt;
    &amp;lt;include name="**/?*.jpg"/&amp;gt;
    &amp;lt;include name="**/?*.html"/&amp;gt;
    &amp;lt;include name="**/?*.dtd"/&amp;gt;
    &amp;lt;include name="**/?*.tld"/&amp;gt;
    &amp;lt;include name="**/?*.ftl"/&amp;gt;
  &amp;lt;/patternset&amp;gt;

  &amp;lt;!-- JDK definitions --&amp;gt;

  &amp;lt;property name="jdk.bin.1.6" value="${jdk.home.1.6}/bin"/&amp;gt;
  &amp;lt;path id="jdk.classpath.1.6"&amp;gt;
    &amp;lt;fileset dir="${jdk.home.1.6}"&amp;gt;
      &amp;lt;include name="lib/deploy.jar"/&amp;gt;
      &amp;lt;include name="lib/dt.jar"/&amp;gt;
      &amp;lt;include name="lib/javaws.jar"/&amp;gt;
      &amp;lt;include name="lib/jce.jar"/&amp;gt;
      &amp;lt;include name="lib/management-agent.jar"/&amp;gt;
      &amp;lt;include name="lib/plugin.jar"/&amp;gt;
      &amp;lt;include name="lib/sa-jdi.jar"/&amp;gt;
      &amp;lt;include name="../Classes/charsets.jar"/&amp;gt;
      &amp;lt;include name="../Classes/classes.jar"/&amp;gt;
      &amp;lt;include name="../Classes/dt.jar"/&amp;gt;
      &amp;lt;include name="../Classes/jce.jar"/&amp;gt;
      &amp;lt;include name="../Classes/jconsole.jar"/&amp;gt;
      &amp;lt;include name="../Classes/jsse.jar"/&amp;gt;
      &amp;lt;include name="../Classes/laf.jar"/&amp;gt;
      &amp;lt;include name="../Classes/management-agent.jar"/&amp;gt;
      &amp;lt;include name="../Classes/ui.jar"/&amp;gt;
      &amp;lt;include name="lib/ext/apple_provider.jar"/&amp;gt;
      &amp;lt;include name="lib/ext/dnsns.jar"/&amp;gt;
      &amp;lt;include name="lib/ext/localedata.jar"/&amp;gt;
      &amp;lt;include name="lib/ext/sunjce_provider.jar"/&amp;gt;
      &amp;lt;include name="lib/ext/sunpkcs11.jar"/&amp;gt;
    &amp;lt;/fileset&amp;gt;
  &amp;lt;/path&amp;gt;

  &amp;lt;property name="project.jdk.home" value="${jdk.home.1.6}"/&amp;gt;
  &amp;lt;property name="project.jdk.bin" value="${jdk.bin.1.6}"/&amp;gt;
  &amp;lt;property name="project.jdk.classpath" value="jdk.classpath.1.6"/&amp;gt;

  &amp;lt;!-- Project Libraries --&amp;gt;

  &amp;lt;!-- Global Libraries --&amp;gt;

  &amp;lt;path id="library.clojure.classpath"&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/ant-launcher.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/ant.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/clojure-contrib.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/clojure.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/commons-codec-1.3.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/commons-fileupload-1.2.1.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/commons-io-1.4.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/compojure.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/hsqldb.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/jetty-6.1.14.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/jetty-util-6.1.14.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/jline-0.9.94.jar"/&amp;gt;
    &amp;lt;pathelement location="/Users/unclebob/projects/clojure-build/lib/servlet-api-2.5-6.1.14.jar"/&amp;gt;
  &amp;lt;/path&amp;gt;

  &amp;lt;!-- Modules --&amp;gt;

  &amp;lt;!-- Module BowlingForJunit --&amp;gt;

  &amp;lt;dirname property="module.bowlingforjunit.basedir" file="${ant.file}"/&amp;gt;

  &amp;lt;property name="module.jdk.home.bowlingforjunit" value="${project.jdk.home}"/&amp;gt;
  &amp;lt;property name="module.jdk.bin.bowlingforjunit" value="${project.jdk.bin}"/&amp;gt;
  &amp;lt;property name="module.jdk.classpath.bowlingforjunit" value="${project.jdk.classpath}"/&amp;gt;

  &amp;lt;property name="compiler.args.bowlingforjunit" value="${compiler.args}"/&amp;gt;

  &amp;lt;property name="bowlingforjunit.output.dir" value="${module.bowlingforjunit.basedir}/classes"/&amp;gt;
  &amp;lt;property name="bowlingforjunit.testoutput.dir" value="${module.bowlingforjunit.basedir}/classes"/&amp;gt;

  &amp;lt;path id="bowlingforjunit.module.bootclasspath"&amp;gt;
    &amp;lt;!-- Paths to be included in compilation bootclasspath --&amp;gt;
  &amp;lt;/path&amp;gt;

  &amp;lt;path id="bowlingforjunit.module.classpath"&amp;gt;
    &amp;lt;path refid="${module.jdk.classpath.bowlingforjunit}"/&amp;gt;
    &amp;lt;pathelement location="/Library/junit4.6/junit-4.6.jar"/&amp;gt;
    &amp;lt;path refid="library.clojure.classpath"/&amp;gt;
    &amp;lt;pathelement location="${basedir}/classes"/&amp;gt;
  &amp;lt;/path&amp;gt;

  &amp;lt;path id="bowlingforjunit.runtime.module.classpath"&amp;gt;
    &amp;lt;pathelement location="${bowlingforjunit.output.dir}"/&amp;gt;
    &amp;lt;pathelement location="/Library/junit4.6/junit-4.6.jar"/&amp;gt;
    &amp;lt;path refid="library.clojure.classpath"/&amp;gt;
    &amp;lt;pathelement location="${basedir}/classes"/&amp;gt;
  &amp;lt;/path&amp;gt;

  &amp;lt;patternset id="excluded.from.module.bowlingforjunit"&amp;gt;
    &amp;lt;patternset refid="ignored.files"/&amp;gt;
  &amp;lt;/patternset&amp;gt;

  &amp;lt;patternset id="excluded.from.compilation.bowlingforjunit"&amp;gt;
    &amp;lt;patternset refid="excluded.from.module.bowlingforjunit"/&amp;gt;
  &amp;lt;/patternset&amp;gt;

  &amp;lt;path id="bowlingforjunit.module.sourcepath"&amp;gt;
    &amp;lt;dirset dir="${module.bowlingforjunit.basedir}"&amp;gt;
      &amp;lt;include name="src"/&amp;gt;
    &amp;lt;/dirset&amp;gt;
  &amp;lt;/path&amp;gt;

  &amp;lt;target name="compile" depends="clojure, compile.java" description="Compile module BowlingForJunit"/&amp;gt;

  &amp;lt;target name="compile.java" description="Compile module BowlingForJunit; production classes"&amp;gt;
    &amp;lt;mkdir dir="${bowlingforjunit.output.dir}"/&amp;gt;
    &amp;lt;javac destdir="${bowlingforjunit.output.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" 
           memorymaximumsize="${compiler.max.memory}" fork="true" executable="${module.jdk.bin.bowlingforjunit}/javac"&amp;gt;
      &amp;lt;compilerarg line="${compiler.args.bowlingforjunit}"/&amp;gt;
      &amp;lt;bootclasspath refid="bowlingforjunit.module.bootclasspath"/&amp;gt;
      &amp;lt;classpath refid="bowlingforjunit.module.classpath"/&amp;gt;
      &amp;lt;src refid="bowlingforjunit.module.sourcepath"/&amp;gt;
      &amp;lt;patternset refid="excluded.from.compilation.bowlingforjunit"/&amp;gt;
    &amp;lt;/javac&amp;gt;

    &amp;lt;copy todir="${bowlingforjunit.output.dir}"&amp;gt;
      &amp;lt;fileset dir="${module.bowlingforjunit.basedir}/src"&amp;gt;
        &amp;lt;patternset refid="compiler.resources"/&amp;gt;
        &amp;lt;type type="file"/&amp;gt;
      &amp;lt;/fileset&amp;gt;
    &amp;lt;/copy&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;target name="clojure"&amp;gt;
    &amp;lt;java classname="clojure.lang.Compile"&amp;gt;
      &amp;lt;classpath&amp;gt;
        &amp;lt;path location="/Users/unclebob/projects/clojure/BowlingForJunit/classes"/&amp;gt;
        &amp;lt;path location="/Users/unclebob/projects/clojure/BowlingForJunit/src"/&amp;gt;        
        &amp;lt;path location="/Users/unclebob/projects/clojure/BowlingForJunit/src/bowling"/&amp;gt;
        &amp;lt;path location="/Users/unclebob/projects/clojure-build/lib/clojure.jar"/&amp;gt;
        &amp;lt;path location="/Users/unclebob/projects/clojure-build/lib/clojure-contrib.jar"/&amp;gt;  
      &amp;lt;/classpath&amp;gt;
      &amp;lt;sysproperty key="clojure.compile.path" value="/Users/unclebob/projects/clojure/BowlingForJunit/classes"/&amp;gt;
      &amp;lt;sysproperty key="java.awt.headless" value="true"/&amp;gt;
      &amp;lt;arg value="bowling.Game"/&amp;gt;
    &amp;lt;/java&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;target name="clean" description="cleanup module"&amp;gt;
    &amp;lt;delete dir="${bowlingforjunit.output.dir}"/&amp;gt;
    &amp;lt;delete dir="${bowlingforjunit.testoutput.dir}"/&amp;gt;
    &amp;lt;mkdir  dir="${bowlingforjunit.output.dir}"/&amp;gt;
  &amp;lt;/target&amp;gt;

  &amp;lt;target name="all" depends="clean, compile" description="build all"/&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;</description>
      <pubDate>Fri, 07 Aug 2009 17:00:43 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:6d45354f-02f4-4519-aebc-dad2102743cf</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/08/07/java-calling-clojure</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>As the tests get more specific, the code gets more generic.</title>
      <description>&lt;p&gt;I tweeted this not too long ago.  The basic idea is that as you add tests, the tests get more and more specific.  This makes sense since tests are, after all, specifications.  The more specifications you have, the more specific the whole body of specifications becomes.&lt;/p&gt;


	&lt;p&gt;As a general rule, good design dictates that the more specific your requirements become, the more general your code needs to be.  This is saying roughly the same thing as Greenspun&amp;#8217;s Tenth Rule of Programming: &amp;#8220;Any sufficiently complicated [...] program contains an ad hoc informally-specified bug-ridden slow implementation of half of Common Lisp.&amp;#8221;  Or rather, as more and more constraints pile upon a program, the designers look for ways to push those constraints out of the program itself and into the data.&lt;/p&gt;


	&lt;p&gt;In return for my tweet people asked for examples.&lt;/p&gt;


	&lt;p&gt;One of the better examples (though perhaps a bit trivial) is the &lt;a href="http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata"&gt;Prime Factors Kata&lt;/a&gt;.   This lovely little experiment grows and grows as you add test cases, and then suddenly collapses into an elegant three line algorithm.&lt;/p&gt;


	&lt;p&gt;The tests continue to become ever more specific.  The production code starts out &lt;em&gt;just as&lt;/em&gt; specific as the tests.  But with the second or third test the programmer must make a decision.  He can write the production code to mirror the tests (i.e. writing it as an if/else statement that detects which test is running and supplying the expected answer) or he can come up with some kind of more general algorithm that satisfies the tests without looking anything like them.&lt;/p&gt;


	&lt;p&gt;The algorithm grows and warps and twists; and then, just when it looks like it&amp;#8217;s destined to become a wretched mess; it simply evaporates into a lovely little three line nested loop.&lt;/p&gt;


	&lt;p&gt;We see the principle at work in other ways as well.  Often the programmers have a whole list of tests that they know must pass.  As they write them one by one, they write the production code that satisfies them.  Then, as in the &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata"&gt;Bowling Game Kata&lt;/a&gt; the tests start to pass unexpectedly.  You were done with the code, and you weren&amp;#8217;t aware of it.  You continue writing tests, expecting one to fail, but they all pass.  The test code grows, but the production code remains the same.&lt;/p&gt;


	&lt;p&gt;Sometimes this happens in a less surprising way.  Sometimes you &lt;em&gt;know&lt;/em&gt; that you have implemented an algorithm that will pass all remaining tests, but you write those tests anyway because they are part of the specification&lt;/p&gt;


	&lt;p&gt;The point is that test code and production code do not grow at the same rate.  Indeed, as the application increases in complexity, the test code grows at a rate that is faster than the production code.  Sometimes the production code actually shrinks as the test code grows because the programmers moved a load of functionality out of the code and into the data.&lt;/p&gt;


	&lt;p&gt;Consider FitNesse.  A year ago there were 45,000 lines of code, of which 15,000 were tests, so 33% of the total were tests.&lt;/p&gt;


	&lt;p&gt;Now Fitnesse is 58,000 lines of code of which 26,000 are tests.  We added 13,000 lines of code overall, but 8,000 (61%), are tests! The tests have grown to over 44% of the total.&lt;/p&gt;</description>
      <pubDate>Thu, 06 Aug 2009 14:23:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:69954d56-0bc3-481c-86db-474de0f760e4</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/08/06/as-the-tests-get-more-specific-the-code-gets-more-generic</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Don't be lazy about lazy sequences.</title>
      <description>&lt;p&gt;Coding with infinite sequences is very powerful, but also very bizarre.  If you aren&amp;#8217;t careful you can get algorithms that work fine, but are O(N&lt;sup&gt;2) instead of O(N).&lt;/p&gt;


	&lt;p&gt;Consider the (partial-sums) function that I used in my previous &lt;a href="http://blog.objectmentor.com/articles/2009/08/05/generating-pi-in-clojure"&gt;blog&lt;/a&gt; on generating pi.&lt;/p&gt;


&lt;pre&gt;
(defn partial-sums [s]
  (lazy-seq
    (cons (first s) (add-streams (next s) (partial-sums s)))))
&lt;/pre&gt;  

	&lt;p&gt;This function takes in a list of (a b c&amp;#8230;) and returns a list of partial sums (a a+b a+b+c&amp;#8230;).  Trying to figure out how this function works is a bit mind-bending; at least for me; but here&amp;#8217;s how I visualize it.&lt;/p&gt;


It adds (next s) to (partial-sums s).  
&lt;pre&gt;
                   (next s)
                      |
                      V
              s: (a   b    c     d ...)
(partial-sum s):     (a   a+b  a+b+c ...)
&lt;/pre&gt;

	&lt;p&gt;Notice how the vertical columns are the sums that we want.  Notice also that each result is the sum of the previous result and the next element of s.  So verbally and visually this all makes sense.  But &lt;em&gt;algorithmically&lt;/em&gt; it can still be challenging to understand.  I mean, how do those values get calculated really?&lt;/p&gt;


	&lt;p&gt;Oh&amp;#8230;  And I should note&amp;#8230;  The function above doesn&amp;#8217;t work this way at all.  It&amp;#8217;s actually horrifically inefficient.  But I&amp;#8217;ll get to that, and to the solution.  First things first.&lt;/p&gt;


	&lt;p&gt;What allows this function to run is &lt;em&gt;lazy-evaluation&lt;/em&gt;.  All that really means is that an element of a list does not really exist until you ask for it.  At that point the program calculates what the element of the list should be and then returns it to you as if it was there all along.&lt;/p&gt;


	&lt;p&gt;In Clojure, when you build a sequence inside the (lazy-seq) form, it simply defers the execution of the procedures that generate the values of the sequence until those values are requested.  Look again at the function above.  When you call it, it simply returns immediately without doing anything.  The (lazy-seq) form simply short-circuits the execution of the function, deferring it for later.&lt;/p&gt;


	&lt;p&gt;So when (partial-sums) returns it gives you a sequence, but there&amp;#8217;s nothing in it!  However, as soon as you ask for the first element, the body of the (partial-sums) function will execute &lt;em&gt;just enough&lt;/em&gt; to give you the value of the first element.  No other elements are calculated.  When you ask for the next value, (partial-sums) will execute again, just enough to give you &lt;em&gt;that&lt;/em&gt; value.  And so on.&lt;/p&gt;


	&lt;p&gt;Knowing that, let&amp;#8217;s trace the execution.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;We call (partial-sums s) which returns a list (let&amp;#8217;s call it ps)&lt;/li&gt;
		&lt;li&gt;To get the first element of ps, (partial-sums) is lazily-invoked and simply returns &lt;span style="font-family:Courier New"&gt;(first s)&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;For the second element it returns the first element of the sequence produced by &lt;span style="font-family:Courier New"&gt;(add-streams (next s) (partial-sums s))&lt;/span&gt; &lt;br/&gt;which will be: &lt;span style="font-family:Courier New"&gt;(+ (first (next s)) (first s))&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;For the third element it returns the second element of the added streams, but the element is composed of yet another stream addition invoked by the recursive (partial-sums)  So it looks like this: &lt;br/&gt;&lt;span style="font-family:Courier New"&gt;(+ (first (next (next s)) (+ (first (next s)) (first s))&lt;/span&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&amp;#8220;Uh&amp;#8230;  Wait.&amp;#8221; I hear you say.   &amp;#8220;You mean that in order to calculate the third element, you have to add three elements?  Didn&amp;#8217;t we say that we could add the next element of s to the previous element of the partial sums?  Why do we have to do three additions?  Why does it seem to be doing this:&amp;#8221;&lt;/p&gt;


&lt;pre&gt;
(a b c)
  (a b c)
    (a b c)
&lt;/pre&gt;
Notice that the vertical columns &lt;em&gt;are&lt;/em&gt; the sums we are looking for; but calculating them requires a lot more work than just adding the next value to the previous sum!. 

	&lt;p&gt;&amp;#8220;But wait,&amp;#8221; you say again. &amp;#8220;I know something about Clojure.  Clojure &lt;em&gt;memoizes&lt;/em&gt; the list values.  Once you ask for a list element the first time, it never has to recalculate it again!  So when we get the third element of the result it &lt;em&gt;shouldn&amp;#8217;t&lt;/em&gt; have to recalculate the second.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Partly right.  Once you lazily evaluate a list element, that element never has to be evaluated again.  It&amp;#8217;s in the list, and will simply be returned from the list.  But let me ask you this:  In the function above, where is the list that being asked &lt;em&gt;again&lt;/em&gt;?  Look closely.  There is no partial-sums result that is being asked for a value more than once.  Indeed, every time we need a value we create a new (partial-sums) list.  So we aren&amp;#8217;t taking advantage of the previous values because we&amp;#8217;re always creating a new list.&lt;/p&gt;


If you&amp;#8217;d like to prove this to yourself, you can run this fun little program.  
&lt;pre&gt;
(defn p [a b] (println a '+ b) (+ a b))

(defn add_streams [a b] (map p a b))

(defn partial-sums [s]
    (lazy-seq
      (cons (first s)
        (add_streams (next s) (partial-sums s)))))

(def w (iterate inc 1))
(println (take 5 (partial-sums w)))
&lt;/pre&gt;

Notice how I print every addition in the (p) function.  If you run this you&amp;#8217;ll get the following result:
&lt;pre&gt;
(2 + 1
1 2 + 1
3 + 3
3 2 + 1
3 + 3
4 + 6
6 2 + 1
3 + 3
4 + 6
5 + 10
10 15)
&lt;/pre&gt;

	&lt;p&gt;The jumble of numbers is evidence that the lazy evaluation is working.  As the println marches through the 5 partial sums, it causes each to be evaluated, causing each sum to be printed.  Notice how many sums are taken!  Ten additions for 5 partial sums.  It&amp;#8217;ll be 15 for 6, and 21 for 7.  Indeed, the number of additions required to calculate ps[n] is equal to ps[n-1].  A little thought will convince you that this is O(n&lt;/sup&gt;2).&lt;/p&gt;


	&lt;p&gt;To reduce this back to O(n), we need to stop creating a new list of partial-sums at each recursion, and use a single copy of the partial-sums result.  We can do this by saving the partial sums result in a var, and then using that in the add-streams call.&lt;/p&gt;


&lt;pre&gt;
(defn partial-sums [s]
    (def result (lazy-seq
      (cons (first s)
        (add_streams (next s) result)))) result)
&lt;/pre&gt;

	&lt;p&gt;This may bend your brain just a little bit more.  We are using the result &lt;em&gt;before&lt;/em&gt; we are done calculating it!  But that&amp;#8217;s ok, since we never use more than has &lt;em&gt;already been&lt;/em&gt; calculated&amp;#8230;&lt;/p&gt;


	&lt;p&gt;Running the program with this change yields the following output.&lt;/p&gt;


&lt;pre&gt;
(2 + 1
1 3 + 3
3 4 + 6
6 5 + 10
10 15)
&lt;/pre&gt;

	&lt;p&gt;&lt;em&gt;That&amp;#8217;s&lt;/em&gt; the O(n) behavior we wanted!  Each sum is calculated by adding the next element to the previous sum!  Hooray!&lt;/p&gt;


	&lt;p&gt;There&amp;#8217;s a lesson here.  You don&amp;#8217;t get the benefit of lazy sequences unless you &lt;em&gt;use&lt;/em&gt; the lazy sequences.  Creating a brand new one each time may generate the right answer, but it&amp;#8217;s lazy, and can burn a lot of execution cycles.&lt;/p&gt;


	&lt;p&gt;One problem I have with this solution is the creation of the global var &amp;#8216;result&amp;#8217;.  I&amp;#8217;m sure there&amp;#8217;s a way to create a local result; but I haven&amp;#8217;t found it yet.  (I tried using various let forms, but I haven&amp;#8217;t stumbled upon one that works yet.)&lt;/p&gt;</description>
      <pubDate>Thu, 06 Aug 2009 11:54:41 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:9010a7e4-16d5-4f2f-b4dc-743fe6da8ef3</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/08/06/dont-be-lazy-about-lazy-sequences</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Generating PI in Clojure</title>
      <description>&lt;p&gt;The &lt;span class="caps"&gt;SICP&lt;/span&gt; book shows a cute algorithm for computing PI using infinite sequences (lazy evaluation).  I have adapted it for Clojure and modified it to use Java&amp;#8217;s BigDecimal class, so that I can generate arbitrary precision.&lt;/p&gt;


	&lt;p&gt;First we define a function that generates an &amp;#8220;infinite&amp;#8221; list of terms of the form 1/1 + 1/3 &amp;#8211; 1/5 + 1/7 &amp;#8211; ...  This is a well known series that very slowly converges on Pi.  Notice that I&amp;#8217;m using the &amp;#8216;M&amp;#8217; suffix to denote BigDecimal, and I&amp;#8217;m restricting the precision to 300 places.  Notice also that I&amp;#8217;m using lazy-seq.  This function delays the execution of the &amp;#8216;cons&amp;#8217; term until that part of the list is actually used.  This allows the list to appear to be infinite.&lt;/p&gt;


&lt;pre&gt;
(defn pi-summands [n]
  (lazy-seq
    (cons (with-precision 300 (/ 1M n))
      (map - (pi-summands (+ n 2))))))

&lt;/pre&gt;

	&lt;p&gt;Next we have two utility functions.  The first multiplies the terms of a list by a scale factor.  The other adds two lists together producing a list of sums.  If the input lists are &amp;#8216;infinite&amp;#8217;, the output lists will also be &amp;#8216;infinite&amp;#8217;.&lt;/p&gt;


&lt;pre&gt;
(defn scale-stream [stream factor]
  (map (fn [x] (* x factor)) stream))

(defn add-streams [p q]
  (map +  p q))
&lt;/pre&gt;

	&lt;p&gt;partial-sums  takes a list of terms produces a list of the sums of those terms.  Given [a b c] it produces [a a+b a+b+c].  And, again, the lists can be infinite.&lt;/p&gt;


&lt;pre&gt;
(defn partial-sums [s]
  (lazy-seq
    (cons (first s) (add-streams (next s) (partial-sums s)))))
&lt;/pre&gt;

	&lt;p&gt;pi-stream mutiplies the partial-sums of the pi-summands by 4.  Turning the summing sequence into 4/1 + 4/3 &amp;#8211; 4/5&amp;#8230;&lt;/p&gt;


&lt;pre&gt;
(def pi-stream
  (scale-stream (partial-sums (pi-summands 1)) 4))
&lt;/pre&gt;

	&lt;p&gt;A simple squaring function.&lt;/p&gt;


&lt;pre&gt;
(defn square [s] (* s s))
&lt;/pre&gt;

	&lt;p&gt;Euler&amp;#8217;s transform is a fancy way to average three terms of a +/- sequence.  It can dramatically increase the precision of an otherwise slowly converging sequence.  The euler-transform function produces a sequence of results from the pi-stream.  Again, note the constraint I place on BigDecimal precision.&lt;/p&gt;


&lt;pre&gt;
(defn euler-transform [s]
  (let [s0 (nth s 0)
        s1 (nth s 1)
        s2 (nth s 2)]
    (lazy-seq
      (cons (with-precision 300 (- s2 (/ (square (- s2 s1))
        (+ s0 (* -2 s1) s2))))
        (euler-transform (next s))))))
&lt;/pre&gt;

	&lt;p&gt;It turns out that you can use Euler&amp;#8217;s transform on it&amp;#8217;s own results to further increase precision.  The make-tableau function arranges the reapplication of a transform so that it can be repeatedly applied to itself.&lt;/p&gt;


&lt;pre&gt;
(defn make-tableau [transform s]
  (lazy-seq
    (cons s (make-tableau transform (transform s)))))
&lt;/pre&gt;

And now we grab the first element of each repetition.
&lt;pre&gt;
(defn accelerated-sequence [transform s]
  (map first (make-tableau transform s)))
&lt;/pre&gt;

	&lt;p&gt;A little utility to print the elements of a list.&lt;/p&gt;


&lt;pre&gt;
(defn print-list [s] (doseq [n s] (println n)))
&lt;/pre&gt;

And now finally we print the first 150 iterations of the accelerated euler-transformation of the pi sequence.
&lt;pre&gt;
(print-list (take 150
  (accelerated-sequence euler-transform pi-stream)))
&lt;/pre&gt;

	&lt;p&gt;The 150th result (the first two lines of which are accurate)
3.14159265358979323846264338327950288419716939
93751058209749445923078164062862089986280348253
25256352154500957038098311477352066337027814620
46050836612955894790973622135628850706785335611
34661971615744147647325427374216175843967838084
09640502874355811103562027043480098593797655792
36344321165429010895M&lt;/p&gt;</description>
      <pubDate>Wed, 05 Aug 2009 08:07:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:d7776e53-674c-4c34-8138-8a6d7d042053</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/08/05/generating-pi-in-clojure</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Scenario Tables for FitNesse</title>
      <description>&lt;p&gt;Scenario Tables are a very powerful new feature of &lt;em&gt;FitNesse&lt;/em&gt;, allowing a whole new level of abstraction in the specification of tests.  Scenario tables can be used on any page that uses the &lt;em&gt;Slim&lt;/em&gt; test system.&lt;/p&gt;


	&lt;p&gt;One of the tests among the many acceptance tests for FitNesse itself ensures that certain operations require authentication.  For example, if you declare a page to be read-locked, then you should not be able to read that page unless you have logged in.&lt;/p&gt;


	&lt;p&gt;Here is an example of an old-style FitNesse test that ensures that you can not save a page that is write-locked unless you log in.&lt;/p&gt;


	&lt;p&gt;&lt;img src=http://butunclebob.com/files/images/AuthenticationScenarios/initialAuthenticationTest.gif width=100%&gt;&lt;/p&gt;


	&lt;p&gt;Notice the detailed, step by step, &lt;em&gt;programmerish&lt;/em&gt; nature of the test.  
1. It creates a user with a password.  
2. It creates a page that is write-locked.
3. It requests the page without any authentication and expects a 401.
4. It requests the page with bad authentication and expects a 401.
5. It requests the page with good authentication and expects a 303.&lt;/p&gt;


	&lt;p&gt;This test is not too hard to understand, and any good QA/BA ought to be able to grasp what it is doing.  But it is certainly circuitous and indirect.  Worse, this algorithm is repeated on a new page for each of fifteen other secure operations, creating a suite of very similar pages.  In other words, lots of &lt;em&gt;duplication&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;In sweeping through the acceptance tests of FitNesse, I decided to use scenarios to simplify them.  My first attempt at this was to adopt a Given/When/Then (BDD) approach.  The same kind of approach that you might use with Cucumber of JBehave.&lt;/p&gt;


	&lt;p&gt;&lt;img src=http://butunclebob.com/files/images/AuthenticationScenarios/intermediateAuthenticationTest.gif width=70%&gt;&lt;/p&gt;


	&lt;p&gt;This test is much shorter, easier to read, and gets right to the point.  It&amp;#8217;s also much less &lt;em&gt;programmerish&lt;/em&gt; since it doesn&amp;#8217;t mention 401s or 303s.  I was able to accomplish this by creating a set of scenarios that look something like the ones below.  (They aren&amp;#8217;t the exact ones, but you get the idea.)&lt;/p&gt;


	&lt;p&gt;&lt;img src=http://butunclebob.com/files/images/AuthenticationScenarios/intermediateScenarios.gif width=100%&gt;&lt;/p&gt;


	&lt;p&gt;All the &lt;em&gt;programmerish&lt;/em&gt; stuff is hidden in the scenarios!  That&amp;#8217;s nice.  If you look closely at the scenarios and substitute them into the test, you can see that the whole test simply turns into something very much like the original test.&lt;/p&gt;


	&lt;p&gt;Though this is better, we still have a lot of similar pages. The duplication has not been removed.&lt;/p&gt;


	&lt;p&gt;So then I added a third level of indirection.  This one solves all the problems.&lt;/p&gt;


	&lt;p&gt;&lt;img src=http://butunclebob.com/files/images/AuthenticationScenarios/finalAuthenticationTest.gif width=60%&gt;&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s hard to imagine a simpler test than this.  Instead of a suite of sixteen different tests, I have one single test.  The scenario is simply executed once of reach row of the &amp;#8220;Operation is authenticated&amp;#8221; table.&lt;/p&gt;


	&lt;p&gt;Here are the scenarios that allowed me to do this.&lt;/p&gt;


	&lt;p&gt;&lt;img src=http://butunclebob.com/files/images/AuthenticationScenarios/finalScenarios.gif width=100%&gt;&lt;/p&gt;


	&lt;p&gt;Once again, if you simply replace the scenarios in each row of the table, you&amp;#8217;ll wind up with sixteen tests that look a lot like the original test.  But now they are very direct, absurdly simple to read, and are virtually free of &lt;em&gt;programmerish&lt;/em&gt; gobblety-gook.&lt;/p&gt;


	&lt;p&gt;Critics may rightly point out that you can get the same results by simply writing a &lt;em&gt;ColumnFixture&lt;/em&gt; that interprets the final table.  True, but then you put the burden of test-abstraction on the programmers.  What is interesting about the scenario approach is that I was able to reduce the &lt;em&gt;programmerish&lt;/em&gt; and highly duplicated tests into a single simple test table &lt;em&gt;without writing any new fixtures&lt;/em&gt;!&lt;/p&gt;


	&lt;p&gt;In other words, programmers can supply a set of APIs, in the form of fixtures, and then competent test engineers can shape the tests appropriately with scenario tables that eventually call the low level fixture APIs while keeping the tests readable and free of duplication.&lt;/p&gt;</description>
      <pubDate>Tue, 04 Aug 2009 15:00:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:1c68a78e-b297-4c81-b6d4-2321e492d902</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/08/04/scenario-tables-for-fitnesse</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>More Clojure from Uncle Bob JSPS</title>
      <description>&lt;p&gt;Thanks to all who posted their solutions to the Bowling Game.  Just to be contrary, I decided to implement yet another kind of solution.  This one clearly shows my OO roots.&lt;/p&gt;


h2. Here are the tests.
&lt;pre&gt;
(ns bowling-game)
(use 'clojure.contrib.test-is)
(use 'bowling-game)

(defn roll-list [game list]
  (vec (concat game list)))

(defn roll-many [game n pins]
  (roll-list game (repeat n pins)))

(deftest can-create-game
  (is (not (nil? (new-game)))))

(deftest gutter-game-should-score-0
  (is (= 0 (score (-&amp;gt; (new-game) (roll-many 20 0))))))

(deftest all-ones-should-score-20
  (is (= 20 (score (-&amp;gt; (new-game) (roll-many 20 1))))))

(deftest one-spare
  (is (= 16 (score (-&amp;gt; (new-game) (roll-list [5 5 3]) (roll-many 17 0))))))

(deftest one_strike
  (is (= 24 (score (-&amp;gt; (new-game) (roll-list [10 3 4]) (roll-many 16 0))))))

(deftest perfect-game
  (is (= 300 (score (-&amp;gt; (new-game) (roll-many 12 10))))))

(run-tests 'bowling-game)
&lt;/pre&gt;
&lt;hr/&gt;

	&lt;h2&gt;And here is the code.&lt;/h2&gt;


&lt;pre&gt;
(ns bowling-game)
(defn new-game [] [])

(defn frame-type [[first second]]
  (cond
    (= 10 first) :strike
    (= 10 (+ first second)) :spare
    :else :no-mark))

(defmulti frame-size frame-type)
(defmethod frame-size :strike [_] 1)
(defmethod frame-size :spare [_] 2)
(defmethod frame-size :no-mark [_] 2)

(defmulti frame-score frame-type)
(defmethod frame-score :strike [[_ first second]] (+ 10 (+ first second)))
(defmethod frame-score :spare [[_ _ next]] (+ 10 next))
(defmethod frame-score :no-mark [[first second]] (+ first second))

(defn score [game]
  (loop [frame 1 rolls game score 0]
    (if (&amp;gt; frame 10)
      score
      (recur (inc frame) (subvec rolls (frame-size rolls)) (+ score (frame-score rolls))))))
&lt;/pre&gt;</description>
      <pubDate>Fri, 31 Jul 2009 08:12:44 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:562954b1-4789-4bbb-b864-ff3298fedea7</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/07/31/more-clojure-from-uncle-bob-jsps</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Uncle Bob, JSPS: Learning Clojure</title>
      <description>&lt;p&gt;(JSPS: Just Some Poor Schmuck)&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m trying to learn &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt;, and I&amp;#8217;m finding the effort challenging.  Perhaps you can help me.&lt;/p&gt;


	&lt;p&gt;Programming in Clojure (A derivative of Lisp) requires a certain &amp;#8220;inside-out&amp;#8221; thinking.  I&amp;#8217;m finding the combination of the shift in thought process and &lt;span class="caps"&gt;TDD&lt;/span&gt; quite difficult to resolve.  So I thought I&amp;#8217;d ask for your help.&lt;/p&gt;


	&lt;p&gt;Below is the &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata"&gt;Bowling Game&lt;/a&gt; written in Clojure complete with unit tests.  I&amp;#8217;m not at all pleased with the result.  The tests, especially, look bizzare and backwards to me.&lt;/p&gt;


	&lt;p&gt;Please post your own solutions to this so that we can all compare and contrast them.&lt;/p&gt;


	&lt;h2&gt;Tests&lt;/h2&gt;


&lt;pre&gt;
(ns bowling-game)
(use 'clojure.contrib.test-is)
(use 'bowling-game)

(defn roll-list [game list]
  (if (empty? list)
    game
    (roll-list (roll game (first list)) (rest list))
    ))

(defn roll-many [game n pins]
  (loop [i n g game]
    (if (zero? i)
      g
      (recur (dec i) (roll g pins)))))

(defn gutter-game [game] (roll-many game 20 0))

(deftest can-create-game
  (is (not (nil? (new-game)))))

(deftest gutter-game-should-score-0
  (is (= 0 (score (gutter-game (new-game))))))

(deftest all-ones-should-score-20
  (is (= 20 (score (roll-many (new-game) 20 1)))))

(deftest one-spare
  (is (= 16 (score
    (roll-many
      (roll-list (new-game) [5 5 3])
      17 0)))))

(deftest one_strike
  (is (= 24 (score
    (roll-many
      (roll-list (new-game) [10 3 4])
      16 0)))))

(deftest perfect-game
  (is (= 300 (score (roll-many (new-game) 12 10)))))

(run-tests 'bowling-game)
&lt;/pre&gt;

	&lt;h2&gt;Code&lt;/h2&gt;


&lt;pre&gt;
(ns bowling-game)
(defn new-game [] [])

(defn next-two-balls [rolls]
  (+ (rolls 0) (rolls 1)))

(defn score-strike [rolls]
  [1 (+ 10 (+ (rolls 1) (rolls 2)))])

(defn score-spare [rolls]
  [2 (+ 10 (rolls 2))])

(defn score-no-mark [rolls]
  [2 (next-two-balls rolls)])

(defn score-next-frame [rolls]
  (if (= 10 (first rolls))
    (score-strike rolls)
    (if (= 10 (next-two-balls rolls))
      (score-spare rolls)
      (score-no-mark rolls))))

(defn score [game]
  (loop [frame 1 rolls game score 0]
    (if (&amp;gt; frame 10)
      score
      (let [frame-score (score-next-frame rolls)]
        (recur (inc frame) (subvec rolls (frame-score 0)) (+ score (frame-score 1)))))))

(defn roll [game pins]
  (conj game pins))
&lt;/pre&gt;</description>
      <pubDate>Sun, 19 Jul 2009 21:10:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:23b5c784-3251-492b-ac4f-77492c3b576f</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/07/19/uncle-bob-jsps-learning-clojure</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>The Rush</title>
      <description>&lt;p&gt;There&amp;#8217;s nothing like the feeling of achievement when you get a complex software system working.  It&amp;#8217;s the feeling of the hunter making a hard fought kill.  By the sheer power of your intellect you have imposed your will upon inanimate nature, and forced it to do your bidding.  You feel the &lt;em&gt;rush&lt;/em&gt; of power, the satisfaction of victory.  You are the master!&lt;/p&gt;


	&lt;p&gt;That&amp;#8217;s the good news.&lt;/p&gt;


	&lt;p&gt;The bad news is that you&amp;#8217;ve made a mess of things along the way.&lt;/p&gt;


	&lt;p&gt;This is inevitable.  It takes a great deal of focus and endurance to get a system working just right.  While you are consumed by that focus, you have little room for niceties like small functions, nice names, decoupling, and cleanliness.&lt;/p&gt;


	&lt;p&gt;My apprentice and I just finished achieving a major milestone in FitNesse.  It used to be that each new release of FitNesse was contained in a zip file that had all the files and directories laid out just perfectly.  This is great for a brand new installation, but doesn&amp;#8217;t work so well when you are upgrading.  What we managed to get working last night was the ability for FitNesse to self-install from it&amp;#8217;s jar file.  Now, whether you are installing for the first time, or just upgrading, FitNesse will install itself into your environment appropriately.&lt;/p&gt;


	&lt;p&gt;If you&amp;#8217;ve ever written a self-install like this, you know there are lots of niggling little details to attend to.  While the problem is conceptually simple, the realization is a maze of complexity.&lt;/p&gt;


	&lt;p&gt;Last night, with dinner waiting on the table and getting cold, we got the last little problem licked, and saw the whole self-installation work as we wanted.  We congratulated each other with a high-five, and then went upstairs to eat a well-deserved meal.  Later that evening I went down to the office and checked in the code.&lt;/p&gt;


	&lt;p&gt;This morning I woke up, and while in the shower, I realized that we had a lot of work left to do.  We need to go back over all that code and clean it up.  I&amp;#8217;m sure we left a swath of detritus while on the hunt.&lt;/p&gt;


	&lt;p&gt;The rush of victory should never be confused with the cold and crystalline concept of &lt;em&gt;done&lt;/em&gt;.  Once you get your systems to work, you still have to go back and clean up the wreckage left behind by the victorious battle.  You are not &lt;em&gt;done&lt;/em&gt; until the victorious code has been cleaned, polished, and oiled.&lt;/p&gt;</description>
      <pubDate>Fri, 26 Jun 2009 08:40:13 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ff86f7eb-465c-43d7-8584-e9f35b3dc900</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/06/26/the-rush</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Clean Code and Battle Scarred Architecture</title>
      <description>&lt;p&gt;If you go &lt;a href="http://internal.objectmentor.com:9090/job/fitnesse/crap/"&gt;here&lt;/a&gt; you&amp;#8217;ll see that I struggle to keep the &lt;a href="http://www.crap4j.org/"&gt;&lt;span class="caps"&gt;CRAP&lt;/span&gt;&lt;/a&gt; out of FitNesse.  Despite the whimsical name of this metric (which I take a perverse delight in), I find it to be remarkably useful.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;CRAP&lt;/span&gt; is a metric that is applied to each function in the system.  The formula for &lt;span class="caps"&gt;CRAP&lt;/span&gt; is:
&lt;acronym title="f"&gt;CRAP&lt;/acronym&gt; = comp(f)&lt;sup&gt;2.&lt;/sup&gt; X (1 &amp;#8211; cov(f)/100)&lt;sup&gt;3.&lt;/sup&gt; + comp(f)&lt;/p&gt;


	&lt;p&gt;Where comp(f) = the cyclomatic complexity of the function f.
and cov(f) = the unit test coverage of function f.&lt;/p&gt;


	&lt;p&gt;So a function&amp;#8217;s &lt;span class="caps"&gt;CRAP&lt;/span&gt; will be small iff the cyclomatic complexity is low and the test coverage is high.  &lt;span class="caps"&gt;CRAP&lt;/span&gt; will be &lt;em&gt;huge&lt;/em&gt; if cyclomatic complexity is high, and there is no coverage.&lt;/p&gt;


	&lt;p&gt;What does this have to do with architecture?  Read on&amp;#8230;&lt;/p&gt;


	&lt;p&gt;I work very hard to keep the ratio of crappy methods near .1%.  Of the 5643 methods in FitNesse, only 6 are crappy, and five of those I have no control over.&lt;/p&gt;


	&lt;p&gt;If you study the graph you can see how quickly I react to even the slightest uptick in crap.  I don&amp;#8217;t tolerate it because it means that either I&amp;#8217;ve got a horrifically complex method that needs to be refactored, or (and this is far more likely) I&amp;#8217;ve got a method that isn&amp;#8217;t sufficiently tested.&lt;/p&gt;


	&lt;p&gt;Why am I so fastidious about this?  Why am I so concerned about keeping the crap out of FitNesse?  The reason is pretty simple.  It&amp;#8217;s the &lt;em&gt;least&lt;/em&gt; I can do.&lt;/p&gt;


	&lt;p&gt;If you look inside of FitNesse, you&amp;#8217;ll find that there are lots of structures and decisions that don&amp;#8217;t seem to make a lot of sense at first reading.  There are complexities and abstractions that will leave you shaking your head.&lt;/p&gt;


	&lt;p&gt;For example.  We generate all our &lt;span class="caps"&gt;HTML&lt;/span&gt; &lt;em&gt;in code&lt;/em&gt;.  Yes, you read that correctly.  We write Java code that constructs &lt;span class="caps"&gt;HTML&lt;/span&gt;.  And yes, that means we are slinging angle brackets around.&lt;/p&gt;


	&lt;p&gt;To be fair, we&amp;#8217;ve managed to move most of the angle bracket slingers into a single module that hides the &lt;span class="caps"&gt;HTML&lt;/span&gt; construction behind an abstraction barrier.  This helps a lot, but &lt;em&gt;cripe&lt;/em&gt; who would sling angle brackets when template system are so prevalent?  I hope nobody.  But FitNesse was not conceived at a time when template systems made sense (at least to us).&lt;/p&gt;


	&lt;p&gt;Fear not, I am working through the Fitnesse code replacing the &lt;span class="caps"&gt;HTML&lt;/span&gt; generation with Velocity templates.  It&amp;#8217;ll take some time, but I&amp;#8217;ll get it done.  The point is, that just like every other software system you&amp;#8217;ve seen, FitNesse is a collection of historical compromises.  The architecture shows the scars of many decisions that have since had to be reversed or deeply modified.&lt;/p&gt;


	&lt;p&gt;What does this have to do with &lt;span class="caps"&gt;CRAP&lt;/span&gt;?  Simply this.  The battle scarred architecture is something that will never really go away.  I can stop the bleeding, and disinfect the wounds, but there will always be evidence of the battle.&lt;/p&gt;


	&lt;p&gt;That scarring makes the system hard to understand.  It complicates the job of adding features and fixing bugs.  It decreases the effectiveness of the developers who work on FitNesse.  And though I work hard to massage the scars and bandage the wounds,  the war goes on.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;But I can keep the &lt;span class="caps"&gt;CRAP&lt;/span&gt; out!&lt;/em&gt;  I &lt;em&gt;can&lt;/em&gt; keep the code so clean and simple at the micro level, that the poor folks who try to make sense out of the macro scale aren&amp;#8217;t impeded by huge deeply nested functions that aren&amp;#8217;t tested!&lt;/p&gt;


	&lt;p&gt;Think of it this way.  &lt;span class="caps"&gt;CRAP&lt;/span&gt; is disease at the cellular level.  &lt;span class="caps"&gt;CRAP&lt;/span&gt; is a rot so pervasive that it can infest every nook and cranny of the system.  My system may have scars, &lt;em&gt;but it&amp;#8217;s not diseased!&lt;/em&gt;  In fact, despite the evidence of battles long past, the FitNesse code is &lt;em&gt;very&lt;/em&gt; healthy.&lt;/p&gt;


	&lt;p&gt;And I aim to keep it that way.&lt;/p&gt;</description>
      <pubDate>Wed, 20 May 2009 17:35:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:33c6eb39-6431-415a-9e68-edea9078cdd0</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/05/20/clean-code-and-battle-scarred-architecture</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Agile Methods</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Why the sea is boiling hot</title>
      <description>&lt;p&gt;In my &lt;a href="http://blip.tv/file/2089545"&gt;keynote&lt;/a&gt; at the &lt;a href="http://en.oreilly.com/rails2009/"&gt;Rails Conference&lt;/a&gt; last Wednesday, I spoke about &lt;em&gt;What Killed Smalltalk and could it Kill Ruby Too?&lt;/em&gt;.  In this keynote, as is my wont, I spoke about the need for our industry to define itself as a profession, and for us to define ourselves as professionals.  I closed the keynote with this statement: &amp;#8220;Professionalism does not mean rigid formalism.  Professionalism does not mean adhering to beaurocrasy.  Professionalism is &lt;em&gt;honor&lt;/em&gt;.  Professionalism is being honest with yourself and disciplined in the way you work.  Professionalism is not letting fear take over.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;David Heinemeier Hansson, inventor of Rails, and affectionately referred to as @dhh has posted a &lt;a href="http://www.loudthinking.com/posts/42-we-need-both-engineers-and-artists-in-programming"&gt;blog&lt;/a&gt; in response in which he asserts that we need &lt;em&gt;artists&lt;/em&gt; as well as &lt;em&gt;professionals&lt;/em&gt;, and draws a dichotomy between the two.  The dichotomy is a false one&amp;#8230;&lt;/p&gt;


	&lt;p&gt;We are a community of artisans.  &lt;em&gt;We make things with our hands!&lt;/em&gt;  We all strive, like @dhh, to make things of great beauty and utility.  In no way, and by no means, do I wish to assail that artistry.  Indeed, my hope is to free it.  I want to convince all programmers that the desire for, and the pursuit of beauty is &lt;em&gt;the way you satisfy your customers&lt;/em&gt;.  The only way to go fast, &lt;em&gt;is to go well.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;I want developers to take pride in their work.  I also want them to take pride in &lt;em&gt;the way&lt;/em&gt; that they work.  I want them to be able to look back on the last few days, weeks, and months, and be able to say to themselves, &amp;#8220;I made something beautiful, and I made it well.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;We are a quirky lot.  Some of us wear faded jeans with yesterday&amp;#8217;s spaghetti on them.  Others wear T-shirts that have PI wrapped around them.  There are beards, tatoos, tongue-studs and hair in all shapes and colors. There are hawaiian shirts and sandals.  There are jackets and ties and sometimes even suits. Some of us speak carefully.  Some of us drop F-bombs at a whim.  Some of us are liberal, and some are conservative.  Some of us relish in being seen, and some of us are glad to be overlooked.  In short, we are a group of diverse people who are drawn together by our common passion for code.&lt;/p&gt;


	&lt;p&gt;There is nothing wrong with this diversity.  Indeed it&amp;#8217;s healthy.  The fact that we all think differently about styles, language, appearance, and values means that there are a zillion different ways that we can learn from each other.  And in that learning grows the seed of our profession.&lt;/p&gt;


	&lt;p&gt;So @dhh is right, at least about the diversity.  We should all relish the opportunity to share ideas with people who think differently than we do.  But @dhh is wrong when he draws the dichotomy between artists and engineers.  Every engineer is an artist, and every artist is an engineer.   Every engineer strives for elegance and beauty.  Every artist has the need to make their art actually work.  The two are inextricably tied.  You cannot be one without also being the other.&lt;/p&gt;


	&lt;p&gt;Now, certainly there are environments where the engineering side of things is emphasized over the artistry side.  In extreme cases the artistry is repressed into near non-existence.  Such places are soul-searing hell-holes that every programmer should strive to escape (or for the brave: change from within!)  Indeed, @dhh implies that he worked in such places and found he was &amp;#8220;faking [his] way along in this world.&amp;#8221;  I completely understand that.&lt;/p&gt;


	&lt;p&gt;But then @dhh makes his biggest mistake.  He equates the professionalism I was talking about in my keynote with those repressive environments.  He seems to think that professionalism and artistry are mutually exclusive.  That wearing a green band means you give up on beauty.  That discipline somehow saps programmer happiness.&lt;/p&gt;


	&lt;p&gt;But remember what I said when I closed my keynote: &amp;#8220;Professionalism does not mean rigid formalism.  Professionalism does not mean adhering to beaurocrasy.  Professionalism is &lt;em&gt;honor&lt;/em&gt;.  Professionalism is being honest with yourself and disciplined in the way you work.  Professionalism is not letting fear take over.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;This is not a complete definition; but it will serve for my current purposes.  Because, you see, I made a big mistake during that keynote. And it is in how we deal with our own errors that the claim of professionalism is most frequently, and most thoroughly tested.&lt;/p&gt;


	&lt;p&gt;In my keynote I used a metaphor to link hormones and languages.  I said that C++ was a testosterone language, but Java was an estrogen language.  And then I used the word &amp;#8220;insipid&amp;#8221; to describe Java.&lt;/p&gt;


	&lt;p&gt;Now clearly C++ and testosterone have very little in common.  My use of this metaphor was an oratory device &amp;#8211; a joke.  As far as the operation of that device is concerned, it was a success.  The vast majority of the audience laughed, demonstrating to me that they were a) listening and b) understanding and c) open.&lt;/p&gt;


	&lt;p&gt;There is a kind of &lt;em&gt;artistry&lt;/em&gt; in making oratory devices like this, and I take a certain amount pride in it.  Such devices need to be timed appropriately, delivered skillfully, and used to gauge the audience.  They can help to turn virtually any dry topic into a compelling speech.&lt;/p&gt;


	&lt;p&gt;On the other hand, the construction of &lt;em&gt;this&lt;/em&gt; device had a significant flaw.  I had equated women with weakness.  This was not intentional.  I do not think of women as weak.  But there it was: Estrogen === Insipid. If you were a woman in that audience, how could you come to any conclusion other than &amp;#8220;Uncle Bob thinks women are weak.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;How did I make this error?  Lack of discipline.  I did not &lt;em&gt;test&lt;/em&gt; this keynote adequately.  I should at least have run it past my wife!  I mis-engineered my art!  (Or perhaps my engineering was artless &amp;lt;grin&amp;gt;).&lt;/p&gt;


	&lt;p&gt;Within minutes of concluding my talk, the complaints appeared on twitter.   Women who had been offended and hurt by the remark were tweeting their dissatisfaction.  Some men were joining them.&lt;/p&gt;


	&lt;p&gt;There were two ways I could have responded to this.  I could have asserted that these people were just being too sensitive; that they should have realized that this was just an oratory device and that I didn&amp;#8217;t mean any harm; that they should just recognize me for who I am and not get so hung up in their own fears and values.&lt;/p&gt;


	&lt;p&gt;But I think that reaction would have been unprofessional.  Why?  Because it would have been dishonest.  The truth was that this was just a stupid mistake.  I built the device badly.  I executed the device without testing it properly.  I screwed up; and I needed to own up that.  So I immediately tweeted apologies to those concerned and ate an appropriate amount of humble pie.&lt;/p&gt;


	&lt;p&gt;The reason I told you this story (at the risk of sounding somewhat self-aggrandizing) is so that I could use it to help define professionalism.  The construction of my oratory device was unprofessional.  I should have tested it better.  I should have realized the danger of using gender comparisons and taken greater care with their use.  &lt;em&gt;I could have done better&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;We professionals aren&amp;#8217;t prefect.  We all make mistakes.  We recover from those mistakes by owning up to them &lt;em&gt;as&lt;/em&gt; mistakes.  We do not cover those mistakes by claiming that everyone else is wrong.&lt;/p&gt;


	&lt;p&gt;Confronting your mistakes and taking appropriate action is a &lt;em&gt;discipline&lt;/em&gt;. It is a &lt;em&gt;discipline&lt;/em&gt; of honor and self-honesty.  It is a demonstration that we do not let the fear of our own errors take us over.&lt;/p&gt;</description>
      <pubDate>Mon, 11 May 2009 11:09:57 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:0740eb61-d264-4e84-8d93-142a484e6943</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/05/11/why-the-sea-is-boiling-hot</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
    </item>
    <item>
      <title>The Scatology of Agile Architecture</title>
      <description>&lt;p&gt;One of the more insidious and persistent myths of agile development is that up-front architecture and design are bad; that you should never spend time up front making architectural decisions.  That instead you should evolve your architecture and design from nothing, one test-case at a time.&lt;/p&gt;


	&lt;p&gt;Pardon me, but that&amp;#8217;s Horse Shit.&lt;/p&gt;


	&lt;p&gt;This myth is not part of agile at all.  Rather it is an hyper-zealous response to the &lt;em&gt;real&lt;/em&gt; Agile proscription of &lt;em&gt;Big Design Up Front&lt;/em&gt; (BDUF).  There should be no doubt that &lt;span class="caps"&gt;BDUF&lt;/span&gt; is harmful.  It makes no sense at all for designers and architects to spend month after month spinning system designs based on a daisy-chain of untested hypotheses. To paraphrase John Gall: &lt;em&gt;Complex systems designed from scratch never work.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;However, there &lt;em&gt;are&lt;/em&gt; architectural issues that need to be resolved up front.  There &lt;em&gt;are&lt;/em&gt; design decisions that must be made early.  It &lt;em&gt;is&lt;/em&gt; possible to code yourself into a very nasty cul-de-sac that you might avoid with a little forethought.&lt;/p&gt;


	&lt;p&gt;Notice the emphasis on size here.  Size matters!  &amp;#8216;B&amp;#8217; is bad, but &amp;#8216;L&amp;#8217; is good.  Indeed, &lt;span class="caps"&gt;LDUF&lt;/span&gt; is absolutely essential.&lt;/p&gt;


	&lt;p&gt;How big are these B&amp;#8217;s and L&amp;#8217;s?  It depends on the size of the project of  course.  For most projects of moderate size I think a few days ought to be sufficient to think through the most important architectural issues and start testing them with iterations.  On the other hand, for very large projects, I seen nothing wrong with spending anywhere from a week to even a month, thinking through architectural issues.&lt;/p&gt;


	&lt;p&gt;In some circles this early spate of architectural thought is called &lt;em&gt;Iteration 0&lt;/em&gt;.  The goal is to make sure you&amp;#8217;ve got your ducks in a row before you go off half-cocked and code yourself into a nightmare.&lt;/p&gt;


	&lt;p&gt;When I work on FitNesse, I spend a lot of time thinking about how I should implement a new feature.  For most features I spend an hour or two considering alternative implementations.  For larger features I&amp;#8217;ve spent one or two days batting notions back and forth.  There have been times when I&amp;#8217;ve even drawn &lt;em&gt;&lt;span class="caps"&gt;UML&lt;/span&gt; diagrams&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;On the other hand, I don&amp;#8217;t allow those early design plans to dominate once I start TDDing.  Often enough the &lt;span class="caps"&gt;TDD&lt;/span&gt; process leads me in a direction different from those plans.  That&amp;#8217;s OK, I&amp;#8217;m glad I made those earlier plans.  Even if I don&amp;#8217;t follow them they helped me to understand and constrain the problem. They gave me the context to evaluate the new solution that &lt;span class="caps"&gt;TDD&lt;/span&gt; helped me to discover.  To paraphrase Eisenhower: Individual plans may not turn out to be helpful, but the act of planning is always indispensable.&lt;/p&gt;


	&lt;p&gt;So here&amp;#8217;s the bottom line.  If you are working in an Agile team, don&amp;#8217;t feel guilty about taking a day or two to think some issues through.  Indeed, &lt;em&gt;feel&lt;/em&gt; guilty if you &lt;em&gt;don&amp;#8217;t&lt;/em&gt; take &lt;em&gt;a little&lt;/em&gt; time to think things through.  Don&amp;#8217;t feel that &lt;span class="caps"&gt;TDD&lt;/span&gt; is the only way to design.  On the other hand, don&amp;#8217;t let yourself get too vested in your designs.  Allow &lt;span class="caps"&gt;TDD&lt;/span&gt; to change your plans if it leads you in a different direction.&lt;/p&gt;</description>
      <pubDate>Sat, 25 Apr 2009 15:23:09 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:75b7d6e4-6c5a-4bba-b373-321a2bb29d1b</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/04/25/the-scatology-of-agile-architecture</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Agile Methods</category>
    </item>
    <item>
      <title>Crap Code Inevitable?  Rumblings from ACCU.</title>
      <description>&lt;p&gt;I gave the opening Keynote at &lt;a href="http://accu.org/index.php/conferences/accu_conference_2009"&gt;&lt;span class="caps"&gt;ACCU 2009&lt;/span&gt;&lt;/a&gt; on Wednesday.  It was entitled: &lt;em&gt;The Birth of Craftsmanship&lt;/em&gt;.  Nicolai Josuttis finshed the day with the closing keynote: &lt;em&gt;Welcome Crappy Code &amp;#8211; The Death of Code Quality&lt;/em&gt;.  It was like a blow to the gut.&lt;/p&gt;


	&lt;p&gt;In my keynote I attempted to show the historical trajectory that has led to the emergence of the &lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;software craftsmanship&lt;/a&gt; movement.  My argument was that since the business practices of &lt;span class="caps"&gt;SCRUM&lt;/span&gt; have been widely adopted, and since teams who follow those practices but do not follow the technical practices of XP experience a relentless decrease in velocity, and since that decrease in velocity is &lt;em&gt;exposed&lt;/em&gt; by the transparency of scrum, then if follows that the eventual adoption of those technical XP practices is virtually assured.  My conclusion was that Craftsmanship was the &amp;#8220;next big thing&amp;#8221; (tm) that would capture the attention of our industry for the next few years, driven by the business need to increase velocity.  (See Martin Fowler&amp;#8217;s blog on &lt;a href="http://martinfowler.com/bliki/FlaccidScrum.html"&gt;Flaccid Scrum&lt;/a&gt;)  In short, we are on a trajectory towards a higher degree of professionalism and craftsmanship.&lt;/p&gt;


	&lt;p&gt;Nicolai&amp;#8217;s thesis was the exact opposite of mine.  His argument was that we are all ruled by marketing and that businesses will do whatever it takes to cut costs and increase revenue, and therefore businesses will drive software quality inexorably downward.  He stipulated that this will necessarily create a crisis as the defect rates and deadline slips increased, but that all attempts to improve quality would be short lived and followed by a larger drive to decrease quality even further.&lt;/p&gt;


	&lt;p&gt;Josuttis&amp;#8217; talk was an hour of highly depressing rhetoric couched in articulate delivery and brilliant humor.  One of the more memorable moments came when he playacted how a manger would respond to a developer&amp;#8217;s plea to let them write clean code like Uncle Bob says.  The manager replies: &amp;#8220;I don&amp;#8217;t care what Uncle Bob says, and if you don&amp;#8217;t like it you can leave and take Uncle Bob with you.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;One of the funnier moments came when Josuttis came up with his rules for crap code, one of which was &amp;#8220;Praise Copy and Paste&amp;#8221;.  Here he showed the evolution of a module from the viewpoint of clean code, and then from the viewpoint of copy-paste.  His conclusion, delivered with a lovely irony, was the the copy-paste solution was more maintainable because it was clear which code belonged to which version.&lt;/p&gt;


	&lt;p&gt;It was at this point that I thought that this whole talk was a ribald joke, an elaborate spoof.  I predicted that he was about to turn the tables on everyone and ringingly endorse the craftsmanship movement.&lt;/p&gt;


	&lt;p&gt;Alas, it was not so. In the end he said that he was serious about his claims, and that he was convinced that crap code would dominate our future.  And then he gave his closing plea which went like this:&lt;/p&gt;


	&lt;p&gt;We finally accepted that requirements change, and so we invented Agile.&lt;/p&gt;


	&lt;p&gt;We must finally accept that code will be crap and so we must ???&lt;/p&gt;


	&lt;p&gt;He left the question marks on the screen and closed the talk.&lt;/p&gt;


	&lt;p&gt;This was like a blow to the gut.  The mood of the conference changed, at least for me, from a high of enthralled geekery, to depths of hoplessness and feelings of futile striving against the inevitable. Our cause was lost.  Defeat was imminent.  There was no hope.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Bulls Bollocks!&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;To his credit, there are a few things that Josuttis got right.  There &lt;em&gt;is&lt;/em&gt; a lot of crap code out there.  And there &lt;em&gt;is&lt;/em&gt; a growing cohort of crappy coders writing that crap code.&lt;/p&gt;


	&lt;p&gt;But the solution to that is not to give up and become one of them.  The solution to that is to design our systems so that they don&amp;#8217;t require an army of maintainers slinging code.  Instead we need to design our systems such that the vast majority of changes can be implemented in DSLs that are tuned to business needs, and do not require &amp;#8220;programmers&amp;#8221; to maintain.&lt;/p&gt;


	&lt;p&gt;The thing that Josuttis got completely wrong, in my mildly arrogant opinion, is the notion that low quality code is cheaper than high quality code.  Low quality code is &lt;em&gt;not&lt;/em&gt; cheaper; it is &lt;em&gt;vastly&lt;/em&gt; more expensive, even in the short term.  Bad code slows everyone down from the minute that it is written.  It creates a continuous and copious drag on further progress. It requires armies of coders to overcome that drag; and those armies must grow exponentially to maintain constant velocity against that drag.&lt;/p&gt;


	&lt;p&gt;This strikes at the very heart of Josuttis&amp;#8217; argument.  His claim that crappy code is inevitable is based on the notion that crappy code is cheaper than clean code, and that therefore businesses will demand the crap every time.  But it has generally not been &lt;em&gt;business&lt;/em&gt; that has demanded crappy code.  Rather it has been &lt;em&gt;developers&lt;/em&gt; who mistakenly thought that the business&amp;#8217; need for speed meant that they had to produce crappy code.  Once &lt;em&gt;we&lt;/em&gt;, as &lt;em&gt;professional developers&lt;/em&gt;, realize that the only way to go fast is to create clean and well designed code, then we will see the business&amp;#8217; need for speed as a demand for high quality code.&lt;/p&gt;


	&lt;p&gt;My vision of the future is quite different from Josuttis&amp;#8217;.  I see software developers working together to create a discipline of craftsmanship, professionalism, and quality similar to the way that doctors, lawyers, architects, and many other professionals and artisans have done.  I see a future where team velocities increase while development costs decrease because of the steadily increasing skill of the teams.    I see a future where large software systems are engineered by relatively small teams of craftsmen, and are configured and customized by business people using DSLs tuned to their needs.&lt;/p&gt;


	&lt;p&gt;I see a future of &lt;em&gt;Clean Code&lt;/em&gt;, Craftsmanship, Professionalism, and an overriding imperative for Code Quality.&lt;/p&gt;</description>
      <pubDate>Thu, 23 Apr 2009 04:56:22 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:3032f508-8860-43f1-a16b-5b26b563999d</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/04/23/crap-code-inevitable-rumblings-from-accu</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Master Craftsman Teams.</title>
      <description>&lt;p&gt;In the early &amp;#8216;70s F. T. Baker, and Fred Brooks wrote about the notion of Chief Programmer teams.  The idea was that a highly skilled chief programer would be assisted by a team of helpers.  The chief would write most of the code, delegating simpler tasks to the helpers.&lt;/p&gt;


	&lt;p&gt;Though the idea was tried at &lt;span class="caps"&gt;IBM&lt;/span&gt; and shown to work well, the idea has never really caught on.  One reason may be that the economics don&amp;#8217;t appear to be all that good.  A team of four juniors making $50K supporting a senior making $100K costs $300K. That just seems like a lot of money for one well supported chief programmer writing most of the code.&lt;/p&gt;


	&lt;p&gt;But in light of the movement towards software craftsmanship, perhaps it&amp;#8217;s time to dust off this old idea and look at it from a different perspective.  Consider the following thought experiment&amp;#8230;&lt;/p&gt;


	&lt;p&gt;We are in the throes of a recession that is challenging us to think differently about things.  At the same time our universities are &lt;em&gt;raising&lt;/em&gt; tuitions and &lt;em&gt;increasing&lt;/em&gt; faculty salaries, while requiring ever less from both the faculty and the students.  Today&amp;#8217;s professors spend about 9 hours per week in the classroom.  And the quality of the CS majors graduating from these institutions is, to put it bluntly, &lt;em&gt;wretched&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Why should a young aspiring software professional spend four years and $200K+ to attend an institution that will teach them less about their chosen profession than 3 months of working on a real project with talented mentors?  Indeed, why should employers pay $50K for undertrained programmers who are sure to make horrific messes for the next three years of their career?&lt;/p&gt;


	&lt;p&gt;Consider instead a team of craftspeople.  At the center of this team is a master programmer.  This is someone who has been programming for two decades or more.  This person understand systems at a gut level, and can quickly make technical judgements without agonizing over them.  Such a person can direct a team with the kind of calm confidence that only comes with years of experience and seasoning.&lt;/p&gt;


	&lt;p&gt;Our master has three lieutenant journeymen who themselves each have three apprentices.  Our journeymen have at least five years of experience, and are capable both of taking and giving direction.  They can make short term tactical decisions, and direct their apprentices accordingly.  At the same time they take technical and architectural direction from the master.&lt;/p&gt;


	&lt;p&gt;The journeymen write a &lt;em&gt;lot&lt;/em&gt; of code &amp;#8211; almost as much as the master.  They also throw away two thirds of the code written by the apprentices, and drive them to redo it better &amp;#8211; always better.  They teach the apprentices how to refactor, and often pair with them and sit with them while reviewing their code.&lt;/p&gt;


	&lt;p&gt;The master probably writes more code than any of the team members.  This code is often architectural in nature, and helps to establish the seed about which the system will crystalize.  The master also sets technical direction and overall architecture, and makes all critical technical decisions.  However, the chief job of the master is to relentlessly drive the journeymen towards higher quality and productivity by establishing and enforcing the appropriate disciplines and practices.  From the master&amp;#8217;s point of view, it&amp;#8217;s &amp;#8220;my way or the highway.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Yes, I know this is very &lt;em&gt;anti-scrum&lt;/em&gt;.  But this is a case where I think scrum in particular, and agile in general just got it wrong.  No battle was won by gaining the consensus of the soldiers.  And if you don&amp;#8217;t think developing a system is a &lt;em&gt;battle&lt;/em&gt; against time, resources, and attitudes, then you&amp;#8217;ve never built a system.  No great team has ever succeeded without a strong coach who imposed discipline, set the vision, and had the final authority over who played and who sat on the bench.  Consensus and team rule may be useful tools &lt;em&gt;some of the time&lt;/em&gt;, but only in the context of effective leadership.&lt;/p&gt;


	&lt;p&gt;The apprentices write a significant amount of code&amp;#8212;most of which is discarded by the journeymen.  The journeymen act as committers.  When an apprentice delivers code that the journeyman finds acceptable, the journeyman will commit that code to their main line.  Otherwise he sends it back to the apprentice to do over.  By the same token the master accepts subsystems from the journeymen and, if acceptable, commits it to the master main line.&lt;/p&gt;


	&lt;p&gt;The master sees every line of code in the system. The Journeymen see every line of code written by their apprentices, and they write a significant amount themselves.  Pairing is prevalent though not universal.  Anyone on the team can pair with anyone else.  It should not be uncommon for the master to pair with the apprentices from time to time.&lt;/p&gt;


	&lt;p&gt;Apprentices begin at a young age&amp;#8212;perhaps 18 or 19.  After all, the idea is that they aren&amp;#8217;t going to a university.  Rather, the brightest would start as apprentices right out of high school, while others might opt for two years of community college first.&lt;/p&gt;


	&lt;p&gt;Apprenticeship would last 2-4 years, depending on how quickly the apprentice learns.  Apprentices earn no more than minimum wage.  After all, they are young, barely productive, and are deriving great benefit from working with experienced journeyman under the guidance of a master.&lt;/p&gt;


	&lt;p&gt;Attaining journeyman status is something for the master to decide, with advice from the journeymen.  The decision is bittersweet because it is a decision to eject the apprentice from the team so that he or she can start the &lt;em&gt;journey&lt;/em&gt;.  Usually the new journeyman would join the team of a different master.&lt;/p&gt;


	&lt;p&gt;Some apprentices simply won&amp;#8217;t attain journeyman status.  In the end, if they fail to make progress, they must be removed from the team.  No one should stay an apprentice year after year.  It is the responsibility of the journeymen and master to decide if an apprentice should be removed from the team.&lt;/p&gt;


	&lt;p&gt;The skills of new journeymen will gradually increase.  At first they should have only one apprentice.  Over the months and years their increasing leadership skills will allow them to take two or three at a time.  The most experienced Journeymen might play the role of master in smaller projects.&lt;/p&gt;


	&lt;p&gt;Attaining master status is no small feat.  It requires the consensus of other masters, and must be demonstrated through several successful accomplishments.&lt;/p&gt;


	&lt;p&gt;I expect a journeyman would make $50-100K depending on their experience.  I expect a master would make $150-$250K or more.&lt;/p&gt;


	&lt;p&gt;Now imagine a team of 13.  One master, three journeymen, and nine apprentices.  This is a powerful unit.  Its size is right at the sweet spot for hyper productive teams.  It has the right balance of experience.  And&amp;#8230; it&amp;#8217;s pretty cheap.  This team costs ~$600K per year, or about $50K per person.  Or (consulting companies take notice) about $23/person/hour.&lt;/p&gt;


	&lt;p&gt;It seems to me that such a team could do much more, much better, than a team of 12 graduates lead by a tech-lead with five years experience.  The productivity and efficiency (and efficiencies of scale!) of this approach should be obvious.  Moreover, I think that being an apprentice on a team like this would provide a much better, much faster, and &lt;em&gt;much&lt;/em&gt; cheaper education than a university degree.  Finally, I think that using teams of this kind could be a remarkably cost-effective way to get very high quality software written very quickly.&lt;/p&gt;</description>
      <pubDate>Wed, 01 Apr 2009 16:51:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f9df49b6-e79e-445b-96de-203dbf363851</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/04/01/master-craftsman-teams</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
    </item>
    <item>
      <title>Let's Hear it for the Zealots!</title>
      <description>&lt;p&gt;In his March 1st, 2009 &lt;a href="http://www.sdtimes.com/link/33300"&gt;column&lt;/a&gt; in SDTimes, Andrew Binstock takes the &amp;#8220;Zealots of Agile&amp;#8221; to task for claiming that Agile is the &lt;em&gt;one true way&lt;/em&gt;.  He made the counter-argument that non-agile projects have succeeded, and that agile projects have failed.  He implied that the attitudes of the agile zealots are blind to these facts.&lt;/p&gt;


	&lt;p&gt;What a load of dingoes kidneys!&lt;/p&gt;


	&lt;p&gt;There is a difference between a zealot, and a religious fanatic.  A religious fanatic cannot envision themselves to be wrong.  We in the agile community may indeed be zealots, but we know we can be wrong.  We know that projects succeeded before agile, and we know that agile projects have failed.  We know that there are other schools of thought that are just as valid as ours.  Indeed, most of us expect (even hope!) that agile will be superseded by something better one day.&lt;/p&gt;


	&lt;p&gt;Some of you may remember my keynote address at the 2002 XPUniverse in Chicago.  My son, Micah, and I got up in front of the group dressed in Jiu Jistsu garb, and commenced to do a martial arts demonstration.&lt;/p&gt;


	&lt;p&gt;After the demonstration I made the point that a student of Karate could have given an equally spellbinding, though quite different, show.  A student of Tae Kwon Do would amaze us with still other wonderful moves.  The morale, of course, was that there are many ways to get the job done.  There are many equally valid schools of thought.&lt;/p&gt;


	&lt;p&gt;However, the knowledge that there are other valid schools of thought does not dilute the zeal a student has for the school of thought he has chosen to study.  Do you think that a Jiu Jistsu master isn&amp;#8217;t a zealot?  You&amp;#8217;d better believe he is!  To be great, one must have zeal.  To rail against zeal is to rail against the desire for greatness.  It is &lt;em&gt;zeal&lt;/em&gt; that makes you go the extra distance to become great.  The Jiu Jitsu master may respect the Karate master, but his goal is to become great at Jiu Jitsu.&lt;/p&gt;


	&lt;p&gt;So I think it is &lt;em&gt;healthy&lt;/em&gt; that agile proponents are vociferous advocates of their school of thought.  They are like Karate students who are excited about their new skills, and want to teach those skills to others.  If their zeal to excel can infect others with similar zeal, so much the better.  We &lt;em&gt;need&lt;/em&gt; people in this industry who want to excel.&lt;/p&gt;


	&lt;p&gt;In his column Andrew derided agile zealots for claiming that Agile was the &lt;em&gt;one true path&lt;/em&gt;.  I don&amp;#8217;t know of any prominent agile advocate who has ever made that claim.  Indeed, when Kent Beck and I sat down in 1999 to plan out the XP Immersion training, we were very concerned that we might turn the XP movement into a religion.  We did not want to create the impression that XPers were the chosen people and that wisdom would die with us.  So we were, in fact, very careful to avoid any hint of the &amp;#8220;one true path&amp;#8221; argument.&lt;/p&gt;


	&lt;p&gt;As evidence of this, consider the Snowbird meeting in 2001.  That meeting was &lt;em&gt;inclusive&lt;/em&gt;, not exclusive.  We invited people from all over the spectrum to join us there.  &lt;span class="caps"&gt;DSDM&lt;/span&gt;, FDD, Scrum, Crystal, &lt;span class="caps"&gt;MDA&lt;/span&gt;, &amp;#38; &lt;span class="caps"&gt;RUP&lt;/span&gt; were all represented; and the agile manifesto (Yes, Andrew, Manifesto![1]) was the result.  That manifesto was a simple statement of values, not a claim to deific knowledge.&lt;/p&gt;


	&lt;p&gt;Am I an Agile Zealot?  Damned right I am!  Do I think Agile is the best way to get software done?  Damned right I do!  I wouldn&amp;#8217;t be doing Agile if I didn&amp;#8217;t think it was best.  Do I think Agile is better than someone else&amp;#8217;s school of thought?  Let me put it this way: I&amp;#8217;m quite happy to go head to head against someone who follows another school of thought.  I believe I&amp;#8217;d code him right into the ground!  Isn&amp;#8217;t that what any good student of his craft would think?  But I also recognize that one day I&amp;#8217;ll lose that competition, and that will be a great day for me because it will give me the opportunity to learn something new and better.&lt;/p&gt;


	&lt;p&gt;Andrew also mentioned that Kent Beck and I are so obsessed with our &amp;#8220;evangelical fervor&amp;#8221; that we: &amp;#8220;endlessly test and endlessly refine and refactor code to the point that it becomes an all-consuming diversion that does not advance the project&amp;#8221;.  &lt;span class="caps"&gt;WTF&lt;/span&gt;?  I&amp;#8217;ve been making monthly releases of FitNesse, and Kent has been cranking out releases of JunitMax; neither of us has been so busy gilding our respective lilies that we are failing to move our respective projects forward. Look around Andrew, we&amp;#8217;re shipping code over here brother.&lt;/p&gt;


	&lt;p&gt;As part of his rant against our &amp;#8220;evangelical fervor&amp;#8221; Andrew asked this rather snide question: &amp;#8220;I broke up that code into a separate class and added seven methods for what benefit, again?&amp;#8221;  This would appear to be a dig against refactoring &amp;#8211; or perhaps &lt;em&gt;excess&lt;/em&gt; refactoring.  Still the question has a simple answer.  We would only break up a module into a class with seven methods if that module was big, ugly, and complex, and by breaking it up we made it simple and easy to understand and modify.  It seems to me that leaving the module in a messy state is irresponsible and unprofessional.&lt;/p&gt;


	&lt;p&gt;Andrew complains that there is very little Agile experience with projects over six million lines of code.  I&amp;#8217;m not sure where he got that number from, perhaps he&amp;#8217;s been watching Steve Austin re-runs.  Actually, the majority of my 2008 consulting business has been with very large companies with products &lt;em&gt;well&lt;/em&gt; over six million lines of code.  Agile-in-the-Large is the name of the game in those companies!&lt;/p&gt;


	&lt;p&gt;Finally, Andrew says Michael Feathers is a &amp;#8220;moderate&amp;#8221; Agile proponent.  This is the same Michael Feathers who wrote a book defining Legacy code as code without tests &amp;#8211; hardly a moderate point of view.  Michael is a master, not a moderate.&lt;/p&gt;


	&lt;p&gt;I think Andrew has fallen into a common trap.  He sees the zeal of the agile proponents and mistakes it for religious fanaticism.  Instead of respecting that zeal as the outward manifestation of the inward desire to excel, he rails against it as being myopic and exclusive and then views all the statements of the agile proponents through that clouded viewport.  Once you have decided that someone is a religious fanatic, it is difficult to accept anything they say.&lt;/p&gt;


	&lt;p&gt;I think standing against religious fanaticism in the software community is a good thing.  I also think that those of us who are zealous must constantly watch that we are not also becoming blind to our own weaknesses and exclusive in our outlook.  But I could wish that those who fear religious fanaticism as much as I do would stop confusing it with professional zeal.&lt;/p&gt;


	&lt;p&gt;So here&amp;#8217;s the bottom line.  People who excel are, by definition, zealots.  People who aren&amp;#8217;t zealous, do not excel. So there&amp;#8217;s nothing wrong with being a zealot; indeed, zeal is a very positive emotion. The trick to being a zealot is to be mindful that the day will eventually come when some other zealot from a different school of thought will code you into the ground.  When that happens, you should thank him for showing you a better way.&lt;/p&gt;


	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; I kicked off the Snowbird meeting by challenging the group to write a &amp;#8220;manifesto&amp;#8221;.  I chose the word &amp;#8220;manifesto&amp;#8221; because some years earlier I had read &lt;em&gt;The Object Oriented Database System Manifesto&lt;/em&gt; and I thought it was a clever use of the word.&lt;/p&gt;</description>
      <pubDate>Tue, 10 Mar 2009 16:58:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:7987e28e-935e-4303-b2e4-1e010beba6b7</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/03/10/lets-hear-it-for-the-zealots</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Quality:  It's alive!  It's ALIVE!</title>
      <description>&lt;p&gt;Recently James Bach wrote a compelling post entitled &lt;a href="http://www.satisfice.com/blog/archives/224"&gt;Quality is Dead&lt;/a&gt;.  As much as I&amp;#8217;d like to agree, something interesting has just happened that tempts me to believe in a rebirth.&lt;/p&gt;


	&lt;p&gt;Just when James finally declares the death of quality, along comes the &lt;a href="http://manifesto.softwarecraftsmanship.org/main"&gt;Manifesto for Software Craftsmanship&lt;/a&gt;.  This simple document that builds upon the four values declared in the &lt;a href="http://agilemanifesto.org/"&gt;Agile Manifesto&lt;/a&gt; went live late on Friday evening.  Now, at 3PM on Saturday over 600 people have signed it!&lt;/p&gt;


	&lt;p&gt;What does this mean?  I think it means that many of us have seen what James was talking about, and are tired of it.  We don&amp;#8217;t want our users posting blogs &amp;#8211; as James did &amp;#8211; crying that they &lt;span class="caps"&gt;HATE&lt;/span&gt; us.  We want our users to be astonished by the elegance and simplicity of our creations.  We want other software developers to look under the hood and be amazed and impressed at the clarity and simplicity they see.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;We want to be proud of our work!&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;We want our quality back!&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;And so a few weeks ago some software developers gathered at the offices of &lt;a href="http://www.8thlight.com/main"&gt;8th Light&lt;/a&gt; in Libertyville, Illinois, and began the process of creating this manifesto.  There followed a very active and passionate discussion in the &lt;a href="http://groups.google.com/group/software_craftsmanship?lnk=srg"&gt;Software Craftsmanship email group&lt;/a&gt;.  The end result was this manifesto.&lt;/p&gt;


	&lt;p&gt;I encourage all of you to read and sign the manifesto, join the email group, and help bring quality back to life in the software profession.&lt;/p&gt;</description>
      <pubDate>Sat, 07 Mar 2009 15:25:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:7fda0576-ab31-4f6b-bf1c-d87078134a6b</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/03/07/quality-its-alive-its-alive</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Software Craftsmanship</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Whiners that Fail</title>
      <description>&lt;p&gt;The acronym is not accidental.&lt;/p&gt;


	&lt;p&gt;Recently, Michael Feathers posted a hugely valuable &lt;a href="http://tinyurl.com/ab3tgn"&gt;blog&lt;/a&gt; entitled: &lt;em&gt;10 Papers every Programmer should read at least twice&lt;/em&gt;.  Do you have &lt;em&gt;any&lt;/em&gt; idea how valuable this is?  Michael has read hundreds, if not thousands, of papers, and he is freely offering his opinion about which ten are the best.  A wise man would pay thousands of dollars for this information.  But some people prefer to whine.&lt;/p&gt;


	&lt;p&gt;Get a load of this gem posted by someone named David:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;... you should have actual pdfs of these papers, not links that require you to pay. If these papers were truly important, then you would be able to read them without paying &amp;#8230;  your tone is arrogant and annoying. Get over yourself.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Clearly this is a troll.  Normally I do not feed the trolls.  But this one pushed my buttons (I know, I know, that&amp;#8217;s the intent of a troll&amp;#8212;well it worked.)  But it wasn&amp;#8217;t only this response.  Here&amp;#8217;s another one by someone named Mik:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Thanks for the list, but please don&amp;rsquo;t link to &lt;span class="caps"&gt;ACM&lt;/span&gt; portal, it is a pay site. Always link to a free version if it is available. Yes, these papers are worth spending a minute or two searching for a free version, and yes they are probably worth spending real money to read as well, but if a free version exists, save us all the time and money and link to it. &lt;p/&gt; One small moment for an author, or one giant waste of time for mankind.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;&lt;strong&gt;What a bunch of whiners!&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Here is this golden nugget laid in front of them, and they complain that it&amp;#8217;s too heavy to pick up.  &lt;strong&gt;Fools!  Losers!&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m sorry for the anger, but the attitude makes me crazy.  Are we professionals who stand on our own and take responsibility for our careers?  Or are we children who expect our parents to wipe our bums?&lt;/p&gt;


	&lt;p&gt;I know I&amp;#8217;m preaching to the choir. The people who take the time to read this blog don&amp;#8217;t generally need to be told this. But on the off-chance that this might actually reach someone and change their attitude&amp;#8230;here goes.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;YOU&lt;/span&gt;, and &lt;em&gt;NO  &amp;nbsp;&amp;nbsp;  &lt;span class="caps"&gt;ONE&lt;/span&gt; &amp;nbsp;&amp;nbsp; &lt;span class="caps"&gt;ELSE&lt;/span&gt;&lt;/em&gt;, is responsible for your career.  Your employer is not responsible for it.  You should not depend on your employer to advance your career.  You should not depend on your employer to buy you books, it&amp;#8217;s great if they do, but it&amp;#8217;s not really their responsibility.  If they won&amp;#8217;t buy them, &lt;span class="caps"&gt;YOU&lt;/span&gt; buy them!  It&amp;#8217;s not your employers responsibility to teach you a new language.  It&amp;#8217;s great if they send you to a training course, but if they don&amp;#8217;t &lt;span class="caps"&gt;YOU&lt;/span&gt; teach the language to your self!&lt;/p&gt;


	&lt;p&gt;I fear greatly that our culture of entitlement has created a bunch of whining sissy programmers who think it&amp;#8217;s unfair that they have to pay for a copyrighted article.  &lt;em&gt;(Pay?  Who me?  That&amp;#8217;s my employer&amp;#8217;s job!  That&amp;#8217;s my teacher&amp;#8217;s job!  That&amp;#8217;s Michael Feathers&amp;#8217; job! I mean if they want me to be a good programmer then they&amp;#8217;d better not expect ME to pay for these articles!  They&amp;#8217;d better not expect ME to do a google search for an article! They&amp;#8217;d better come right over here to my cubicle between 9am and 10am and read the article to me while stroking my hair!)&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;The world does not owe you a living.  Your employer does not owe you a career.  And Michael Feathers&amp;#8217; does not owe you access to free articles.&lt;/p&gt;</description>
      <pubDate>Fri, 27 Feb 2009 18:55:40 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:f919918b-d789-4369-bb58-9fdbbe1fa866</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/02/27/whiners-that-fail</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Getting a SOLID start.</title>
      <description>&lt;p&gt;I am often asked: &amp;#8220;How should I get started with &lt;span class="caps"&gt;SOLID&lt;/span&gt; principles?&amp;#8221;  Given the recent interest and controversy about the issue, it&amp;#8217;s probably time I gave a written answer.&lt;/p&gt;


	&lt;h2&gt;First things first.&lt;/h2&gt;


	&lt;p&gt;You can read about the Solid principles &lt;a href="http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf"&gt;here&lt;/a&gt;.  This is a paper I wrote nearly a decade ago.  It uses a somewhat dated form of &lt;span class="caps"&gt;UML&lt;/span&gt;, and examples are in C++.  Also the concepts are &lt;em&gt;severely&lt;/em&gt; abbreviated.  This is the Cliff Notes.  Still, it should give you an initial notion of the names, definitions, and concepts.&lt;/p&gt;


	&lt;p&gt;There are quite a few papers &lt;a href="http://www.objectmentor.com/resources/publishedArticles.html"&gt;here&lt;/a&gt; that explain the principles in much more detail.  Just click on the &amp;#8220;Design Principles&amp;#8221; topic to see them all.  Though I think you&amp;#8217;ll find the other topics pretty interesting too.&lt;/p&gt;


	&lt;p&gt;Finally, the principles are definitively described in two books: &lt;em&gt;Agile Software Development: Principles, Patterns, and Practices&lt;/em&gt;, and &lt;em&gt;Agile Principles Patterns, and Practices in C#&lt;/em&gt;.  You can see descriptions of these books &lt;a href="http://www.objectmentor.com/PPP"&gt;here&lt;/a&gt;&lt;/p&gt;


	&lt;h2&gt;What do I mean by &amp;#8220;Principle&amp;#8221;&lt;/h2&gt;


	&lt;p&gt;The &lt;span class="caps"&gt;SOLID&lt;/span&gt; principles are not rules.  They are not laws.  They are not perfect truths.  The are statements on the order of &lt;em&gt;&amp;#8220;An apple a day keeps the doctor away.&amp;#8221;&lt;/em&gt;  This is a good principle, it is good advice, but it&amp;#8217;s not a pure truth, nor is it a rule.&lt;/p&gt;


	&lt;p&gt;The principles are mental cubby-holes.  They give a name to a concept so that you can talk and reason about that concept.  They provide a place to hang the &lt;em&gt;feelings&lt;/em&gt; we have about good and bad code.  They attempt to categorize those feelings into concrete advice.  In that sense, the principles are a kind of anodyne.  Given some code or design that you &lt;em&gt;feel bad&lt;/em&gt; about, you may be able to find a principle that explains that bad feeling and advises you about how to feel better.&lt;/p&gt;


	&lt;p&gt;These principles are heuristics. They are common-sense solutions to common problems.  They are common-sense disciplines that can help you stay out of trouble.  But like any heuristic, they are empirical in nature.  They have been observed to work in many cases; but there is no proof that they always work, nor any proof that they should always be followed.&lt;/p&gt;


	&lt;h2&gt;Following the rules on the paint can won&amp;#8217;t teach you how to paint.&lt;/h2&gt;


	&lt;p&gt;This is an important point.  Principles will not turn a bad programmer into a good programmer.  Principles have to be applied with judgement.  If they are applied by rote it is just as bad as if they are not applied at all.&lt;/p&gt;


	&lt;p&gt;Having said that, if you want to paint well, I suggest you learn the rules on the paint can.  You may not agree with them all.  You may not always apply the ones you &lt;em&gt;do&lt;/em&gt; agree with.  But you&amp;#8217;d better &lt;strong&gt;know&lt;/strong&gt; them.  Knowledge of the principles and patterns gives you the justification to decide when and where to apply them.  If you don&amp;#8217;t know them, your decisions are much more arbitrary.&lt;/p&gt;


	&lt;h2&gt;So how do I get started?&lt;/h2&gt;


	&lt;p&gt;&amp;#8220;There is no royal road to Geometry&amp;#8221; Euclid once said to a King who wanted the short version.  Don&amp;#8217;t expect to skim through the papers,  or thumb through the books, and come out with any real knowledge.  If you want to learn these principles well enough to be able to apply them, then you have to &lt;em&gt;study&lt;/em&gt; them.  The books are full of coded examples of principles done right and wrong.  Work through those examples, and follow the reasoning carefully.  This is not easy, but it &lt;em&gt;is&lt;/em&gt; rewarding.&lt;/p&gt;


	&lt;p&gt;Search your own code, and the code of others, for applications and violations of the principles.  Determine whether those applications and violations were justified.  Improve the designs by applying one or more principles, and see if the result is actually better.  If you&amp;#8217;d like to study a code base that was written by people who&amp;#8217;ve been immersed in these principles for years, then download the source for FitNesse from fitnesse.org.&lt;/p&gt;


	&lt;p&gt;Conduct or join a discussion group at work.  Do brown-bags, lunch-n-learns, reading-groups, etc.  People who learn in groups learn much more, and much more quickly, than people who study alone.  Never underestimate the power of the other guy&amp;#8217;s viewpoint.&lt;/p&gt;


	&lt;p&gt;By the same token, join a user group with people from different companies.  Attend monthly meetings and listen to the speakers, or participate in the discussions.  Again, you&amp;#8217;ll learn an awful lot that way.&lt;/p&gt;


	&lt;p&gt;Practice, practice, practice, practice.  Be prepared to make &lt;em&gt;lots&lt;/em&gt; of mistakes.&lt;/p&gt;


	&lt;p&gt;And, of course, apply what you&amp;#8217;ve learned on the job, and ask your peers to review your work.  Pair program with them if at all possible.  &lt;em&gt;&amp;#8220;As iron sharpens iron, so one man sharpens another.&amp;#8221;&lt;/em&gt; (Proverbs 27:17)&lt;/p&gt;</description>
      <pubDate>Thu, 12 Feb 2009 20:43:35 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:970506d9-c08d-40b0-a6ee-b347be94e70e</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/02/12/getting-a-solid-start</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Design Principles</category>
    </item>
    <item>
      <title>An Open Letter to Joel Spolsky and Jeff Atwood</title>
      <description>&lt;p&gt;Joel, Jeff,&lt;/p&gt;


	&lt;p&gt;Here is an open letter to the two of you that I hope we can use in our upcoming StackOverflow #40 podcast.  I won&amp;#8217;t post it on my blog until we&amp;#8217;ve been able to iterate it a bit.  I&amp;#8217;ve spent several hours on this trying to balance the tone.  It used to be a lot longer &amp;lt;grin&amp;gt;.&lt;/p&gt;


	&lt;p&gt;Dear Joel and Jeff&lt;/p&gt;


	&lt;p&gt;In the Stack Overflow Podcast #38 you said: &amp;#8220;Last week I was listening to a podcast on Hanselminutes, with Robert Martin talking about the &lt;span class="caps"&gt;SOLID&lt;/span&gt; principles &amp;#8230; they all sounded to me like extremely bureaucratic programming that came from the mind of somebody that has not written a lot of code, frankly.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;And again later: &amp;#8221;...it seems to me like a lot of the Object Oriented Design principles you&amp;#8217;re hearing lately from people like Robert Martin and Kent Beck and so forth have gone off the deep end into architecture for architecture&amp;#8217;s sake.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;And yet again: &amp;#8220;People that say things like this have just never written a heck of a lot of code.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;And still again: &amp;#8220;One of the &lt;span class="caps"&gt;SOLID&lt;/span&gt; principles, (a butchering of the Single Responsibility Principle) and it&amp;#8217;s just&amp;#8230; idiotic! You can&amp;#8217;t build software that way!&amp;#8221;&lt;/p&gt;


	&lt;p&gt;I hope you&amp;#8217;ve had time to perform a little due diligence since then, and that you now realize that your statements were unfair, harmful, and were pretty much crap.&lt;/p&gt;


	&lt;p&gt;I understand that you were trying to make a valid point and that the words just got away from you a bit. I quite agree that a dogmatic or religious application of the &lt;span class="caps"&gt;SOLID&lt;/span&gt; principles is neither realistic nor beneficial.  If you had read through any of the articles and/or books I&amp;#8217;ve written on these principles over the last 15 years, you&amp;#8217;d have found that I don&amp;#8217;t recommend the religious or dogmatic approach you blamed me for. In short, you jumped to a erroneous conclusion about me, and about the principles, because you weren&amp;#8217;t familiar with the material.&lt;/p&gt;


	&lt;p&gt;I understand that this was a podcast, and that you were both just jawing.  However, your podcasts are a &lt;strong&gt;product&lt;/strong&gt; that you ship to everyone in the world.  The content of that product can do great good; but it can also do great and permanent harm.  One would think that you&amp;#8217;d want to be careful with such a product.  Yet in the intensity of the moment you got a bit careless and spewed some crap instead.  That&amp;#8217;s fine, everybody makes mistakes.  But then you &lt;strong&gt;shipped&lt;/strong&gt; it!  You shipped a product that had a huge bug in it.  You should have had tests!&lt;/p&gt;


	&lt;p&gt;Could it be that when you said &amp;#8221;...quality just doesn&amp;#8217;t matter that much&amp;#8230;&amp;#8221; you were being serious.  Clearly the quality of podcast #38 didn&amp;#8217;t matter much to you, since you shipped it without verifying that your information was accurate.  As a result, you did unjust harm to me.  Were I a more litigious person, we might be having this discussion in court.&lt;/p&gt;


	&lt;p&gt;Now I&amp;#8217;m quite certain that you don&amp;#8217;t want to ship bad product.  I just think that you&amp;#8217;ve been careless with your production process.  You haven&amp;#8217;t put in place a mechanism that will stop you from shipping crap.  So I suggest that you practice Test Driven Development with your podcast.  Write down the acceptance criteria beforehand (I suggest lawsuit avoidance would be a high priority), and then review the product against those criteria afterwards.  Yes, this will take some time, and there will be a cost.  However, it will pay back handsomely because your product will be far better, and you will avoid embarrassments like this one (or worse).  And, after all, products deserve and require this kind of care.  So do your listeners.  This is just simple professionalism.  Don&amp;#8217;t ship shit.
&lt;del&gt;&amp;#8212;&lt;/del&gt;-&lt;del&gt;&amp;#8212;&lt;/del&gt;&amp;#8212;-&lt;/p&gt;


	&lt;p&gt;Some of the other points we could talk about in the podcast:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;span class="caps"&gt;TDD&lt;/span&gt; for real this time.  You guys can just throw your complaints at me and I&amp;#8217;ll address them.
 * For example, I&amp;#8217;d like to explain how one would test Joel&amp;#8217;s JPeg compression feature.&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;ISP&lt;/span&gt; and &lt;span class="caps"&gt;SRP&lt;/span&gt;, the two principles that Joel butchered.&lt;/li&gt;
		&lt;li&gt;Mike Connie&amp;#8217;s observation (in #39) about interfaces.&lt;/li&gt;
		&lt;li&gt;How, when, and why to apply Principles and Patterns.&lt;/li&gt;
		&lt;li&gt;From Stack Overflow:
 * Large Switch statements: Bad &lt;span class="caps"&gt;OOP&lt;/span&gt;?
 * &lt;span class="caps"&gt;JSON&lt;/span&gt; is used only for JavaScript? (Rant on &lt;span class="caps"&gt;XML&lt;/span&gt;)
 * &lt;span class="caps"&gt;ASP&lt;/span&gt;.Net &amp;#8211; How to effectively use design patterns without over-engineering!&lt;/li&gt;
	&lt;/ul&gt;</description>
      <pubDate>Fri, 06 Feb 2009 20:53:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:3607f47d-8998-4ffa-925f-65c600fd4bb6</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/02/06/on-open-letter-to-joel-spolsky-and-jeff-atwood</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Speed Kills</title>
      <description>&lt;p&gt;Ron Jeffries wrote a wonderful &lt;a href="http://xprogramming.com/blog/2009/02/01/quality-speed-tradeoff-youre-kidding-yourself"&gt;blog&lt;/a&gt; about how we kid ourselves that there is a tradeoff between quality and speed.  Isn&amp;#8217;t there?&lt;/p&gt;


	&lt;p&gt;That depends on what you mean by &amp;#8220;speed&amp;#8221;.  If you mean rushingtogetawholebunchofshitcodedandsortofrunning, then quality is not for you.  On the other hand, if by &amp;#8220;speed&amp;#8221; you mean delivering working software quickly and repeatably release after release after release; then maintaining high quality is your only option.&lt;/p&gt;


	&lt;p&gt;The first course is that of the adrenline junkie.  The hacker stereotype of the twinkie eating cola guzzling nerd who cackles like the Wicked Witch of the West while tunnel visioning into his screen and keyboard. The second course is that of the professional programmer, the craftsman who with calm demeanor and deliberate confidence servers his clients, and his career.&lt;/p&gt;


	&lt;p&gt;We all feel the pressure to rush.  It&amp;#8217;s like a drug, really.  It feels good to through off the disciplines and justcodeupawholebunchofshit.  We get the adrenline high, and we feel as though we are skating on the edge between success and failure, sailing so close to the wind that we&amp;#8217;re on the verge of tipping, getting the rush of speed.  When we get our code working we feel &lt;em&gt;victorious!&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;What we &lt;em&gt;should&lt;/em&gt; be feeling is &lt;em&gt;stupid&lt;/em&gt;.  Because we actually &lt;em&gt;were&lt;/em&gt; skating on the edge between success and failure.  We should not feel victorious, we should feel &lt;em&gt;shame&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;We justify this addiction to speed by telling ourselves that our bosses want us to go fast.  We tell ourselves that time-to-market requires that we sail close to the wind.  And then we put the needle in our arm and let fly another dose of speed&amp;#8212;oblivious to the consequences.&lt;/p&gt;


	&lt;p&gt;I teach a lot of programming classes in which I give the students programs to write.  I tell them that the goal is not to finish the programs, but to learn the skills of programming.  I tell them that the code they are writing will all be deleted after they leave.  I tell them to focus on the techniques and disciplines they are learning, not on finishing the programs.  And yet on Friday afternoon there are always a group of folks who are flailing away at their keyboards trying desperately to finish something that they know will be deleted as soon as they leave.&lt;/p&gt;


	&lt;p&gt;These people have surrendered to the drug of speed.  They need to conquer.  They manufactured their own deadline pressure and behaved as if their boss was breathing down their necks.&lt;/p&gt;


	&lt;p&gt;How do you &lt;em&gt;really&lt;/em&gt; get things done quickly?  You listen to your grandparents.  Remember what they told you?  &amp;#8220;Slow and steady wins the race.&amp;#8221; and &amp;#8220;Anything worth doing is worth doing well.&amp;#8221;  How does a professional craftsman get things done quickly?  He/she adopts an attitude of calm, focuses on the problem to be solved, and then step by step solves that problem without rushing, without yielding to the need for speed, without surrendering to the desire for a quick conquest.&lt;/p&gt;


	&lt;p&gt;When you feel the temptation to rush, resist it.  Leave the keyboard and walk around.  Distract yourslef with something else.  Do not give in to the call of your addiction.&lt;/p&gt;


	&lt;p&gt;If you want to be a craftsman.  If you want to be someone who builds software quickly, accurately, and repeatably.  If you want to be someone that your employer respects and values.  If you want to respect yourself.  Then remember this simple fact.  &lt;em&gt;Speed Kills&lt;/em&gt;.&lt;/p&gt;</description>
      <pubDate>Tue, 03 Feb 2009 17:03:33 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:d8352b3a-a55d-4295-8d69-ce5dac0c13db</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/02/03/speed-kills</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Multi-dimensional Seniority</title>
      <description>&lt;p&gt;I was at a meeting of the &lt;a href="http://groups.softwarecraftsmanship.org"&gt;Chicago Software Craftsmanship group&lt;/a&gt; last night.  Dave Hoover and Paul Pagel were talking about the different apprenticeship models at &lt;a href="obtiva.com"&gt;Obtiva&lt;/a&gt; and &lt;a href="8thlight.com"&gt;8thLight&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The 8thLight model uses a 90 day probation period during which an &amp;#8220;apprentice&amp;#8221; has an appointed mentor who guides the apprentice to learn enough to become a &amp;#8220;craftsman&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;The Obtiva model is less structured, but there&amp;#8217;s no probationary period.  Once an apprentice had delivered something meaningful for a client, and had been recognized by the others, he/she would become a &amp;#8220;consultant&amp;#8221;, and eventually a &amp;#8220;senior consultant&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Both speakers used the term &amp;#8220;journeyman&amp;#8221; but neither defined it.  Both speakers agreed that 90 days, or a year, or even two years was insufficient for an apprentice to become a true journeyman.&lt;/p&gt;


	&lt;p&gt;After the talk I started to ponder this question of seniority.  What makes a software developer senior?  Certainly the amount of time spent in a career is a big factor.  Someone with 15 years of experience is certainly senior.&lt;/p&gt;


	&lt;p&gt;However, there&amp;#8217;s that old joke about the guy who had 15 years of experience, the same year fifteen times in a row.   That&amp;#8217;s a real concern.  It is perfectly possible to work for 15 years and dig yourself into a rut you can&amp;#8217;t get out of.  Think of all those Cobol programmers who never learned anything else.&lt;/p&gt;


	&lt;p&gt;Both Paul and Dave talked about how they planned for their apprentices to grow with the company.  They both lamented apprentices that had left the company to do other things.&lt;/p&gt;


	&lt;p&gt;This made me think about the apprentices we&amp;#8217;ve had at Object Mentor.  (Paul was one of them.  Dave was almost another.) Over the years we&amp;#8217;ve had seven or so apprentices.  Today, we have none.  Not a single apprentice has stayed at Object Mentor.  Is this bad?&lt;/p&gt;


	&lt;p&gt;It hasn&amp;#8217;t been bad for the apprentices.  Two went on to form their own company (8thLight).  Others have made names for themselves in the community.  More than one has written a book.  Nearly all are passionate craftsmen who care about their profession, and who are making an impact.&lt;/p&gt;


	&lt;p&gt;It wasn&amp;#8217;t bad for Object Mentor either.  The apprentices moved on when it was a good time for them to move on, and we have kept good relationships with them. More than one customer has come our way because of referrals from past apprentices.&lt;/p&gt;


	&lt;p&gt;So at the end of the meeting, when everyone had milled away from the central area, I went to the whiteboard and scratched out a simple diagram.  It was an graph with Seniority on the horizontal axis, and Journey on the vertical axis.&lt;/p&gt;


	&lt;p&gt;Then I drew a nearly horizontal line starting from the origin and hugging the Seniority axis.  This is the career path of the guy who has the same year of experience 15 times in a row.  Let&amp;#8217;s call him Sam.  Then I drew another line which was a stair-step that went towards the upper right at something less then a 45 degree angle.  This is the career path of a developer who changes jobs a few times during his/her career.  Let&amp;#8217;s call her Jasmine.&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm4.static.flickr.com/3482/3213134571_2df4411867.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;I don&amp;#8217;t think there is a vertical path.  The only way to go on a journey is to spend some time at it, and that drives you horizontally.&lt;/p&gt;


	&lt;p&gt;OK, now maybe I&amp;#8217;ve just spent a dozen paragraphs explaining the obvious.  To-wit: A journeyman is a journeyman because he/she&amp;#8217;s gone on a journey.  Does that journey &lt;em&gt;have&lt;/em&gt; to involve changing employers?  I think it probably does.  You see, there&amp;#8217;s a problem.&lt;/p&gt;


	&lt;p&gt;The student/teacher relationship is persistent.  At least in my experience it is.  The only way for a teacher and student to ever consider themselves to be peers is for the relationship to break and then reform later in a new context.&lt;/p&gt;


	&lt;p&gt;Sam, has remained an apprentice, even though he&amp;#8217;s got lots of experience.  Why?  Because he still works with his original mentors who consider him to be their student.  Jasmine, on the other hand, has seen the world, experienced many different situations in many different places.  She could become a master.&lt;/p&gt;


	&lt;p&gt;OK, ok.  I&amp;#8217;m belaboring the point.  So let me conclude.  If you are considering an apprenticeship program it seems to me that the most important aspect of that program is that the relationship is &lt;em&gt;temporary&lt;/em&gt;, and results in a journey.  In other words, don&amp;#8217;t expect to hold on to your apprentices for very long.&lt;/p&gt;</description>
      <pubDate>Tue, 20 Jan 2009 23:10:38 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:acdf3fec-4d45-4652-95f9-ba8d5b999fb7</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2009/01/20/multi-dimensional-seniority</link>
      <category>Uncle Bob's Blatherings</category>
    </item>
    <item>
      <title>Fudge anyone?</title>
      <description>&lt;p&gt;Back in September, when I was just staring the &lt;a href="http://fitnesse.org/FitNesse.TestSystems"&gt;Slim&lt;/a&gt; project, I made a crucial architectural decision.  I made it dead wrong.  And then life turned to fudge&amp;#8230;&lt;/p&gt;


	&lt;p&gt;The issue was simple.  Slim tables are, well, tables just like Fit tables are.  How should I parse these tables?  Fit parses &lt;span class="caps"&gt;HTML&lt;/span&gt;.  FitNesse parses wiki text &lt;em&gt;into&lt;/em&gt; HTML and delivers it to Fit.  Where should Slim fit in all of this?&lt;/p&gt;


	&lt;p&gt;Keep in mind that Fit &lt;em&gt;must&lt;/em&gt; parse &lt;span class="caps"&gt;HTML&lt;/span&gt; since it lives on the far side of the FitNesse/SUT boundary.  Fit doesn&amp;#8217;t have access to wiki text.  Slim tables, on the other hand, live on the &lt;em&gt;near&lt;/em&gt; side of the FitNesse/SUT boundary, and so have full access to wiki text, and the built in parsers that parse that text.&lt;/p&gt;


	&lt;p&gt;So it seemed to me that I had two options.&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Follow the example of Fit and parse wiki text into &lt;span class="caps"&gt;HTML&lt;/span&gt;, and then have the Slim Tables parse the &lt;span class="caps"&gt;HTML&lt;/span&gt; in order to process the tables.  &lt;/li&gt;
		&lt;li&gt;Take advantage of the built in wiki text parser inside of FitNesse and bypass &lt;span class="caps"&gt;HTML&lt;/span&gt; altogether.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;I chose the latter of the two because the Parsing system of FitNesse is &lt;em&gt;trivial&lt;/em&gt; to use.  You just hand it a string of wiki text, and it hands you a nice little parse tree of wiki widgets.  All I had to do was walk that parse three and process my tables.  Voila!&lt;/p&gt;


	&lt;p&gt;This worked great!  In a matter of hours I was making significant progress on processing Slim decision tables.  Instead of worrying about parsing &lt;span class="caps"&gt;HTML&lt;/span&gt; and building my own parse tree, I could focus on the problems of translating tables into Slim directives and then using the return values from Slim to colorize the table.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;Generating&lt;/em&gt; html was no problem since that&amp;#8217;s what FitNesse does anyway.  All I had to do was modify the elements of the parse tree and then simply tell the tree to convert itself to &lt;span class="caps"&gt;HTML&lt;/span&gt;.  What a dream.&lt;/p&gt;


	&lt;p&gt;Or so it seemed.  Although things started well, progress started to slow before the week was out.  The problem was that the FitNesse parser is &lt;em&gt;tuned&lt;/em&gt; to the esoteric needs of FitNesse.  The parser makes choices that are perfectly fine if your goal is to generate &lt;span class="caps"&gt;HTML&lt;/span&gt; and pass it to Fit, but that aren&amp;#8217;t quite so nice when you&amp;#8217;re goal is to use the parse tree to process Slim tables.  As a simple example, consider the problem of literals.&lt;/p&gt;


	&lt;p&gt;In FitNesse, any camel case phrase fits the pattern of a wiki word and will be turned into a wiki link.  Sometimes, though, you want to use a camel case phrase and you &lt;em&gt;don&amp;#8217;t&lt;/em&gt; want it converted to a link.  In that case you surround the phrase with literal marks as follows: &lt;code&gt;!- FitNesse-!&lt;/code&gt;.  Anything between literal marks is simply ignored by the parser and passed through to the end.&lt;/p&gt;


	&lt;p&gt;Indeed, things inside of literals are not even escaped for html!  If you put &lt;code&gt;&amp;lt;b&amp;gt;hi&amp;lt;/b&amp;gt;&lt;/code&gt; into a wiki page, it will escape the text you&amp;#8217;ll see &lt;code&gt;&amp;lt;b&amp;gt;hi&amp;lt;/b&amp;gt;&lt;/code&gt; on the screen instead of a bold &amp;#8220;hi&amp;#8221;.  On the other hand, if you put &lt;code&gt;!- &amp;lt;b&amp;gt;hi&amp;lt;/b&amp;gt;-!&lt;/code&gt; on a page, then the &lt;span class="caps"&gt;HTML&lt;/span&gt; is left unescaped and a boldfaced &amp;#8220;hi&amp;#8221; &lt;em&gt;will&lt;/em&gt; appear on the screen.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m telling you all of this because the devil is in the details&amp;#8212;so bear with me a bit longer.&lt;/p&gt;


	&lt;p&gt;You know how the C and C++ languages have a preprocessor?  This preprocessor handles all the &lt;code&gt;#include&lt;/code&gt; and &lt;code&gt;#define&lt;/code&gt; statements and then hands the resulting text off to the true compiler.  Well, the wiki parser works the same way!  Literals and &lt;code&gt;!define&lt;/code&gt; variables are processed first, by a different pass of the parser.  Then all the rest of the wiki widgets are parsed by the true parser.  The reason that we had to do this is even more devilishly detailed; so I&amp;#8217;ll spare you.  Suffice it to say that the reasons we need that preprocessor are similar to the reasons that C and C++ need it.&lt;/p&gt;


	&lt;p&gt;What does the preprocessor do with a literal?  It converts it into a special widget.  That widget looks like this: &lt;code&gt;!lit?23?&lt;/code&gt;  What does that mean?  It means replace me with the contents of literal #23.  You see, when FitNesse sees &lt;code&gt;!- FitNesse-!&lt;/code&gt; it replaces it with &lt;code&gt;!lit?nn?&lt;/code&gt; and squirrels &lt;code&gt;FitNesse&lt;/code&gt; away in literal slot &lt;em&gt;nn&lt;/em&gt;.  During the second pass, that &lt;code&gt;!lit?nn?&lt;/code&gt; is replaced with the contents of literal slot &lt;em&gt;nn&lt;/em&gt;.  Simple, right?&lt;/p&gt;


	&lt;p&gt;OK, now back to &lt;span class="caps"&gt;SLIM&lt;/span&gt; table processing.  There I was, in Norway, teaching a class during the day and coding Slim at night, and everything was going just great.  And then, during one of my tests, I happened to put a literal into one of the test tables.  This is perfectly normal, I didn&amp;#8217;t want some camel case phrase turned into a link.  But this perfectly normal gesture made a unit test fail for a very strange reason.  I got this wonderful message from junit: &lt;code&gt;expected MyPage but was !lit?3?&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;I knew exactly what this meant.  It meant that the value &lt;code&gt;MyPage&lt;/code&gt; had been squirreled away by the first pass of the parser.  I also knew that I had utterly no reasonable way of getting at it.  So I did the only thing any sane programmer would do.  I wrote my own preprocessor and used it instead of the standard one.  This was &amp;#8220;safe&amp;#8221; since in the end I simply reconvert all the colorized tables back into wiki text and let the normal parser render it into &lt;span class="caps"&gt;HTML&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;It was a bit of work, but I got it done at one am on a cold Norwegian night.  Tests passing, everything great!&lt;/p&gt;


	&lt;p&gt;Ah, but no.  By writing my own preprocessor, I broke the &lt;code&gt;!define&lt;/code&gt; variable processing &amp;#8211; subtly.  And when I found and fixed that I had re-broken literal processing &amp;#8211; subtly.&lt;/p&gt;


	&lt;p&gt;If you were following my tweets at the time you saw me twitter ever more frantically about literals.  It was the proverbial ball of Mercury.  Every time I put my thumb on it&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; it would squirt away and take some new form.&lt;/p&gt;


	&lt;p&gt;I fell into a trap.  I call it the &lt;em&gt;fudge trap&lt;/em&gt;.  It goes like this:&lt;/p&gt;


	&lt;p style="text-align:center;"&gt;&lt;span style="color:chocolate;"&gt;&lt;code&gt;forever do {&lt;/code&gt;&amp;#8220;I can make this work!  Just one more little fudge right &lt;em&gt;here&lt;/em&gt;!&amp;#8221;&lt;code&gt;}&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;


	&lt;p&gt;I was in this trap for two months!  I was making progress, and getting lots of new features to work, but I was also running into strange little quirks and unexpected bizarre behaviors caused by the fudging I was doing.  So I&amp;#8217;d fudge a little more and then keep working.  But each little fudge added to the next until, eventually, I had a really nasty house of cards (or rather: pile of fudge) ready to topple every time I touched anything else.  I started to fear my own code&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;.  It was time to stop!&lt;/p&gt;


	&lt;p&gt;I knew what I had to do.  I had to go back to my original architectural decision and make it the other way.  There was no escape from this.  The FitNesse parser was too coupled to the wiki-ness, and there was no sane way to repurpose it for test table processing.&lt;/p&gt;


	&lt;p&gt;I dreaded this.  It was such a big change.  I had built so much code in my house of fudge.  All of it would have to be changed or deleted.  And, worse, I needed to write an &lt;span class="caps"&gt;HTML&lt;/span&gt; parser.&lt;/p&gt;


	&lt;p&gt;I was lamenting to &lt;a href="http://www.8thlight.com/main"&gt;Micah&lt;/a&gt; about this one day in late November, and he said: &amp;#8220;Dad, there are &lt;span class="caps"&gt;HTML&lt;/span&gt; parsers out there you know.&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;Uh&amp;#8230;&lt;/p&gt;


	&lt;p&gt;So I went to google and typed &lt;code&gt;Html Parser&lt;/code&gt;.  Duh.  There they were.  Lots and lots of shiny &lt;span class="caps"&gt;HTML&lt;/span&gt; parsers free for the using.&lt;/p&gt;


	&lt;p&gt;I picked &lt;a href="http://htmlparser.sourceforge.net"&gt;one&lt;/a&gt; and started to fiddle with it.  It was &lt;em&gt;easy&lt;/em&gt; to use.&lt;/p&gt;


	&lt;p&gt;Now comes the good part.  I had not been a complete dolt.  Even when I was using the FitNesse parse tree, I ate my own dogfood and &lt;em&gt;wrapped&lt;/em&gt; it in an abstract interface.  No part of the Slim Table processing code actually &lt;em&gt;knew&lt;/em&gt; that it was dealing with a FitNesse parse tree.  It simply used the abstract interface to get its work done.&lt;/p&gt;


	&lt;p&gt;That meant that pulling out the wiki parser and putting in the &lt;span class="caps"&gt;HTML&lt;/span&gt; parser was a matter of re-implementing the abstract interface with the output of the new parser (which happened to be another parse tree!).  This took me about a day.&lt;/p&gt;


	&lt;p&gt;There came a magic moment when I had &lt;em&gt;both&lt;/em&gt; the wiki text version of the parser, and the &lt;span class="caps"&gt;HTML&lt;/span&gt; version of the parser working.  I could switch back and forth between the two by changing one word in one module.  When I got &lt;em&gt;all&lt;/em&gt; my tests passing with &lt;em&gt;both&lt;/em&gt; parsers, I knew I was done.  And then the fun &lt;em&gt;really&lt;/em&gt; began!&lt;/p&gt;


	&lt;p&gt;I &lt;span style="color:red;"&gt;&lt;em&gt;deleted&lt;/em&gt;&lt;/span&gt; ever stitch of that wiki parse tree pile of fudge.  I tore it loose and rent it asunder.  It was gone, never to darken my door with it&amp;#8217;s fudge again.&lt;/p&gt;


	&lt;p&gt;It took me a day.  A day.  And the result is 400 fewer lines of code, and a set of Slim tables that actually work the way they are supposed to.&lt;/p&gt;


	&lt;p&gt;Moral #1: &amp;#8220;Fudge tastes good while you are eating it, but it makes you fat, slow, and dumb.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Moral #2: &amp;#8220;Eat the damned dog food. It&amp;#8217;ll save your posterior from your own maladroit decisions.&lt;/p&gt;


	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; I do not recommend that you actually put your thumb on any Mercury.  Never mind that I used to play with liquid Mercury as a child, sloshing it around from hand to hand and endlessly stirring it with my finger.  Wiser heads than I have determined that merely being in the same room with liquid Mercury can cause severe brain damage, genetic corruption, and birth defects in your children, grandchildren, and pets.&lt;/p&gt;


	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; Fearing your own code is an indicator that you are headed for ruin.  This fear is followed by self-loathing, project-loathing, career-loathing, divorce, infanticide, and finally chicken farming.&lt;/p&gt;</description>
      <pubDate>Wed, 31 Dec 2008 16:01:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:36578e35-eb79-4c39-bb15-e36e3acf4548</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2008/12/31/fudge-anyone</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Clean Code</category>
    </item>
    <item>
      <title>Hudson -- A Very Quick Demo</title>
      <description>&lt;p&gt;I recently set up Hudson as the continuous integration server for FitNesse.  I was impressed at how very very simple this was to do.  The Hudson folks have adopted the same philosophy that we adopted for FitNesse: download-and-go.&lt;/p&gt;


	&lt;p&gt;So I recorded a quick (&lt;5min) video showing you how I set this up.  In this video you'll see me start Hudson from scratch, create the job to build FitNesse, and then run the FitNesse build.&lt;/p&gt;


&lt;object width="400" height="300"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=2498115&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=2498115&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;a href="http://vimeo.com/2498115"&gt;Hudson&amp;#8212;A Very Quick Demo&lt;/a&gt; from &lt;a href="http://vimeo.com/user947916"&gt;unclebob&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.</description>
      <pubDate>Thu, 11 Dec 2008 20:04:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:0e3d9a88-ac60-485c-8d0e-442fe52ef99f</guid>
      <author>Uncle Bob</author>
      <link>http://blog.objectmentor.com/articles/2008/12/11/hudson-a-very-quick-demo</link>
      <category>Uncle Bob's Blatherings</category>
      <category>Videos</category>
      <category>Agile Methods</category>
    </item>
  </channel>
</rss>

