Thursday, August 27, 2009

Builder Pattern in Clojure

We've been working steadily on our toy traffic simulator and doing TDD along the way. Of course a major concept in a traffic simulator is a car, so we of course have a car struct + cars have some behavior patterns so we also have a behavior struct. They look like:

(defstruct behavior :accel-dist :decel-dist)
(defstruct car :name :position :length :speed :behavior)

So to construct a valid car you need to do something like:

(struct car :a 1 1 1 (struct behavior 10 5)))

Yikes, we constantly wanted cars for our tests and constructing a car like that was often more code than the real stuff we wanted to test. So, we made a bunch of convenience methods (object mother type stuff), like:

(defn slow-car [name position]
 (struct car name position 1 1 (struct behavior 10 5)))

(defn car-with-speed-position [speed position]
 (struct car :a position 1 speed (struct behavior 10 5)))

Suddenly we started creating lots of car-with-* methods. We got annoyed and accidentally started implementing the builder pattern.

(defn default-car []
 (struct car :a 1 1 1 (struct behavior 10 5)))

(defn car-with 
 ([key value]
  (assoc (default-car) key value))
 ([key1 value1 key2 value2]
  (assoc (car-with key1 value1) key2 value2)))

Ignore the total ugliness of the car-with function for a moment, this let us do things like:

(def a-car (car-with :speed 1 :position 4))

as opposed to:

(def a-car (car-with-speed-position 1 4))

Our new version, was not only easier to read, and didn't make us create new methods for each different thing we wanted to do, but hey, that looks really similar to the builder pattern. Now I'm sure there are better ways to implement car-with, but it works for now.

Wednesday, August 26, 2009

Null once again

InfoQ has a nice talk by Tony Hoare, Null References: The Billion Dollar Mistake. I've been in a few arguments in that past that languages would be much better without null, so it's nice to hear someone much smarter than myself, who also happens to have invented the null reference regret their existence. But he doesn't feel as bad as he thinks the C language designers should feel, because he says, they allowed the for the buffer overflow by abusing the get routine. And that allowed for viruses, which have cost industry much more than his billion dollar mistake. He's tough on the language designers (and himself): "Language designers should be responsible for the mistakes programmers make". Thanks Tony, for giving me someone to blame when I muck things up :)

Saturday, August 1, 2009

Returing Null... again

so... thinking more about returning null. I'm thinkin' returning null is allowing you to return a second type from a method. And a null pointer exception is equivalent to a class cast exception. AND a null check if (foo == null) is the same as an instance of check.

nulls are syntactic sugar for a type! I refuse to think of them as values for references any longer. They are types, returning them from functions is returning multiple types from a function (not in a polymorphic way, but in a type system abusing way) and null checks are instance checks.

Returning Null

I've always had a problem with returning null from a method. And I was reminded of this when reading a post at Misko Hevery's blog about how to think about OO

I think returning null is a problematic, it's often abused as a way to have two different return types from one method. A quick googling of "returning null" has the suggestion of returning a null object implementation of your return type. Returning a Null Object is appropriate in some cases, but not when you need to signal to your client two different things. Misko's code refactoring show's an example of this. He refactors some login code (I really like the steps he took btw) down to something like:

  Cookie login(Ldap ldap) {
    if ( ldap.auth(user, password) )
      return new Cookie(user);
    return null;
  }

When I read this code I see two things (structurally that is)

  1. If authentication succeeds then notify the client of the successful authentication with a new Cookie
  2. If authentication fails notify the client by returning null

What could a client of this method look like?

  public void authenticateUser(User user) {
     Cookie userCookie = user.login(ldap);
     if (userCookie == null) {
           //notify someone that auth failed
     } eles {
           //register them as logged in
     }
  }

We're doing the same work twice in each place, but with slightly different syntax, each place we need to check if login failed or not. What if instead we used IoC / "Tell Don't Ask" / "Hollywood Principle"

  Cookie login(Ldap ldap, AuthenticationRegistry authenticationRegistry) {
    if ( ldap.auth(user, password) )
      authenticationRegistry.authSucceeded(new Cookie(user));
    authenticationRegistry.authFailed(user);
  }

and the client

  public void authenticateUser(User user) {
     user.login(ldap,this);
  }

  public void authSucceeded(Cookie cookie) {
     //register them as logged in
  }

  public void authFailed(User user) {
     //register them as auth failed
  }

This new code is a little more complicated, but I think it is clearer, and more straight forward to implement. Now we have two entities that are communicating with each-other and we've defined the way in which they are communicating. Again I liked Misko's refactorings, I'd just take it one step further. It's all definitely arguable, but I think if you're ever in a situation where you want to be returning two types of data from a method using IoC is the way to go.

Tuesday, July 21, 2009

Clojure + Bowling Kata

Just the other day (yesterday) Uncle Bob had a post about Learning Clojure. He implemented a bowling scoring kata. So Dan P. and I decided to try it ourselves, but since we're from Boston we implemented candle pin bowling rules:

As we were talking through designs for this, and as we talked about scoring frames, we realized that there were three cases:

  1. Strike – score the first ball, plus the next two ‘bonus’ balls, then remove the first ball (the strike) from the list, then continue scoring.
  2. Spare – score the first two balls, plus the next ‘bonus’ ball, then remove the first two balls (the spare) from the list, then continue scoring.
  3. No-mark – score all three balls in the frame, then remove them from the list, then continue scoring. (Remember: candlepin!)
In all these cases you want to score three balls, the only difference was in how many balls you remove from the list before you continue scoring (i.e., how many balls were in the frame you are removing from the yet-to-be-scored list). So this is what we came up with: http://github.com/zdsbs/candlepin-bowling/tree/master
(ns scorecard)

(defn third [rolls]
    (first (next (next rolls))))

(defn first-two [rolls]
    (+ (first rolls) (second rolls)))

(defn strike? [rolls]
    (= 10 (first rolls)))

(defn spare? [rolls]
    (= 10 (first-two rolls)))

(defn remove-strike [rolls]
    (rest rolls))

(defn remove-spare [rolls]
    (rest (rest rolls)))

(defn remove-normal-frame [rolls]
    (rest (rest (rest rolls))))

(defn remove-frame [rolls]
        (if (strike? rolls)
            (remove-strike rolls)
            (if (spare? rolls)
                (remove-spare rolls)
                (remove-normal-frame rolls))))

(defn score [input-rolls]
    (loop [rolls input-rolls score 0 frame-counter 0]
        (if (or (empty? rolls) (= 10 frame-counter))
            score
            (recur 
                (remove-frame rolls) 
                (+ score (first rolls) (second rolls) (third rolls)) (inc frame-counter)))))

And the tests:

(ns scorecard-test
    (:use clojure.contrib.test-is 
        scorecard))

(deftest test-third
    (is (= 3 (third [1 2 3 4]))))

(deftest test-first-two
    (is (= 3 (first-two [1 2 3]))))

(deftest test-remove-frame
    (is (= [3 4 5] (remove-frame [0 1 2 3 4 5])))
    (is (= [3 4] (remove-frame [10 3 4])))
    (is (= [5] (remove-frame [6 4 5]))))

(deftest test-remvo-two-frames
    (is (= [] 
        (remove-frame 
            (remove-frame [0 1 2 0 0 0])))))

(deftest test-scores
    (is (= 0 (score [])))
    (is (= 6 (score [1 2 3])))
    (is (= 15 (score [1 2 3 4 5 0])))
    (is (= 19 (score [10 1 2 3])))
    (is (= 17 (score [5 5 1 2 3])))
    (is (= 300 (score [10 10 10 10 10 10 10 10 10 10 10 10])))
    (is (= 19 (score [5 5 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 ])))
    (is (= 21 (score [10 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 ]))))

Also check out:
Stuart Halloway's implementation. Besides just an implementation, he has a great discussion on how to approach the problem in a functional way. (his implementation is much nicer than this one)
Uncle Bob's son over at 8th light also wrote up an implementation

Sunday, July 19, 2009

Git Commands Part I

I'm always forgetting a very useful git command, so I'm posting it here in the hopes that: a) writing it down will help me remember and b) if I forget again, at least I can just goto my blog.

git add -u
(if you're like me and you rename or delete files without calling git rm git add -u takes care of staging the changes)

and thank you Stack Overflow: git rm multiple files that have already been deleted from disk

Oh and if you're pushing a Java project into a git repository, the .git/info/exclude file is very useful to ignore all the generated .class files.

Wednesday, July 15, 2009

Block Editing in Eclipse Galileo

Eclipse now has block editing hooray!

Ummm, what's the key binding for it? There's nothing in eclipse help, nothing in cmd-shift L, too many of my google searches took me to a crappy reddit page which doesn't tell you what the key binding is. Eventually someone decided to be helpful with this post. The key binding on OS X is cmd-alt-a

Anyway, hooray for block editing. Boo for wasting time looking for the keybinding, I hope this saves someone some time.

 
Web Statistics