Skip to content
Alvaro Garcia edited this page Dec 8, 2015 · 5 revisions

(Video)

In Midje's readme, I showed this fact:

  (fact
     (numerical-reverser 103) => 301)

One way to implement numerical-reverser would be to convert 103 into a string, reverse it, and then parse that string into an integer. String reversal is easy, right?

Well, actually, it doesn't seem to be, not using the Java API. My thought process might go like this: "There's no reverse function for String?! Wait, there's one on StringBuffer? So I have to move the string into a StringBuffer, reverse it, then toString it? That's crazy. Clojure's reverse works for vectors, I see, but it gives me a seq. How do I turn that back into a string?... Man, this is not what I want to be thinking about right now."

What I want to do instead of that thinking is what Abelson and Sussman dubbed "programming by wishful thinking" in their masterpiece Structure and Interpretation of Computer Programs. In that style, while writing numerical-reverser, I'd say to myself "I'm going to assume a function string-reverser exists. That'll make it easy to write numerical-reverser. When I've finished that, I'll implement string-reverser if it happens not to exist. Long journeys are made from small steps."

The Midje fact that makes that coding test-driven would look like this:

 (fact 
   (numerical-reverser 103) => 301
   (provided 
      (string-reverser "103") => "301"))

And the code could be written like this:

(defn numerical-reverser [n]
    (String/parseInt (string-reverser (str n))))

Actually, Clojure rips you out of the lovely world of wishful thinking a bit early. Because string-reverser doesn't actually exist, you have to declare it to keep the compiler from spewing a huge stack trace at you. I like predeclaring wishful thinking functions like this:

 (unfinished string-reverser)

That's the same as declare, but it fails more informatively if it's ever called.

In the object-oriented world, this style is well described in Freeman and Pryce's Growing Object-Oriented Software, Guided by Tests. My original goal for Midje was to repaint that style onto the functional landscape, where we can think of test-driven design as building a web of interrelated facts.

Clone this wiki locally