Object Commando languages, development and design

13Jun/100

Mocking Clojure Protocols with Atticus

Atticus is a mocking library written by Hugo Duncan. For more information on Atticus, you can see Hugo's blog post from May here. I have added the ability to mock protocols to Atticus and would like some feedback as to the best approach for binding the mocked protocol instance. There's a survey below, but first a little background on the implementation.

Mocking Protocols

What makes the protocol instances a bit tough to mock is that they're not just straight Clojure functions. They dip a bit into Java and a bit into Clojure. With that in mind, using Atticus without modification, wouldn't allow the mocking of those protocols. Below is an example of some code that uses this new functionality:

(defprotocol Squared
  (square [impl x]))

(deftest mock-protocol-test
  (expects
   [(instance Squared
	      (square [impl y] (once (* y y))))]
   (is (= 9 (square instance 3)))))

Originally I had a marker function name mock-protocol-instance which didn't serve much purpose and was a bit awkward. Talking with Hugo, I switched it to the above syntax. The first item in that list is instance and is the symbol that the mocked protocol instance is bound to. The next item is the protocol followed by functions. The (once...) wrapped around the body of the function is existing functionality in Atticus that expands into the code to ensure the function was called exactly once. An example of mocking a regular function in Atticus is below:

(deftest test-cube
  (expects
   [(cube [y] (once (* y y y)))]
   (is (= 8 (cube 2)))))

The difference in this code and the first is that the binding syntax is familiar because it is similar to letfn. Below is an example of letfn:

(letfn [(add5 [x] (+ x 5))
	(subtract5 [x] (- x 5))]
  (= 7 (add5 (subtract5 7))))

In the style above, the first argument is the function name and so anything that refers to add5 in the body of the letfn gets the function bound above in the letfn. This letfn type of binding makes sense for Atticus when mocking functions. They both have similar goals, binding a function temporarily. Where this is a little more tricky is in mocking the protocol. In the first example above, the first element in the list is special. It's the symbol bound to the protocol instance. This is really more appropriate for a let style of binding. Where one element is the symbol and the other is an expression. Unfortunately, switching to a let style binding for the expects macro will make the syntax a little more cumbersome for mocking functions because you would have to add "fn". This would probably look something like this:

(deftest mock-protocol-test-alt
  (expects
    [instance (Squared
	       (square [impl y] (once (* y y))))
     cube (fn [y] (once (* y y y)))]
        (is (= 9 (square instance 3)))
	(is (= 8 (cube y 2)))))

The above is just spit balling, but the key point is that expects would use a let binding style. The first is a let style binding of the protocol instance and the second is binding a function.

Put it to a vote!

The question is, which one is better? Is sticking with the letfn binding and the brevity that it allows worth it even though the protocol mocking is a bit different? The letfn style is the first and second code examples above. Or is it confusing enough to warrant a little extra code around mocking functions (the example immediately above). Is there another approach that would be better? Below is just a quick survey on which one is preferable. Thanks for giving your input!


17May/104

Easy Java Interop with Clojure

This past week I started writing some code to work with Amazon EC2 Instances. I started using the JClouds library . It's a great library for spinning up public AMIs in a cloud neutral way, however didn't it do everything that I needed. Some of the things I needed were EC2 specific, so that's not so surprising. I fell back to the AWS SDK for Java, which basically just wraps calls to the Amazon web services. Using that library, I wrote some Clojure functions that wrapped the Java calls to do what I needed. Examples of what I needed would be to start up an existing EC2 EBS backed instance, stop an EBS instance and determine what state an EBS VM is in. This led to Clojure code that would build up some request objects and interpret some response POJOs. The API is a little awkward, even using Java. Starting, stopping and describing an instance via the API all require one thing, one or more instance ids. In the Amazon API, they have created a separate class for each (DescribeInstancesRequest, StopInstancesRequest and StartInstancesRequest) and have those classes include a method where you setInstanceIds rather than just calling a method and passing a list of Strings (or something similar). Working with this API helped me learn more about the Clojure Java Interop functions.

dot dot

The first feature that made my life easier was .. . This is a macro for chaining Java calls. It takes code that in Java would look like this:

instance.getState().getName()

And puts a similar feel in Clojure:

(.. instance getState getName)

Without this macro, you would have to:

(.getName (.getState instance))

It takes the return value of the first part (in the inner expression above) and passes it into the second. The code above works great for chained method calls, but doesn't help much with side affects.

doto

I found doto useful when I needed to call setters in constructing POJOs. Calls to determine the status of a running EC2 instance returns an object graph of several nested objects and were particularly awkward to test, since there were a decent amount of objects to construct. Before I realized doto could help me, I had code that looked like below:

(defn single-instance-result-example []
    (let [reservation-list (ArrayList.)
           instance-list (ArrayList.)
           reservation (Reservation.)
           instance (Instance.)
           instance-result (DescribeInstancesResult.)]
       (.setInstanceId instance "testinstance")
       (.add instance-list instance)
       (.setInstances reservation instance-list)
       (.add reservation-list reservation)
       (.setReservations instance-result reservation-list)
       instance-result))

I then transformed this into some code that used some nested dotos

(defn single-instance-result-example []
    (doto (DescribeInstancesResult.)
        (.setReservations
        (doto (ArrayList.)
            (.add
                (doto (Reservation.)
	            (.setInstances
	                (doto (ArrayList.)
	                    (.add
                                (doto (Instance.)
                                    (.setInstanceId "testinstance")))))))))))

I must admit that the dotos here took some time to get comfortable with. Some interesting things to note is that the above does not include all of the intermediate references to objects. In the first example above I always passed the objects in, such as (.setInstanceId instance "testinstance"). This is no longer necessary with doto. The intermediate let-bound variables are also not necessary. I seeing the above code, I felt like I still had some room for improvement. In the above example and in other areas of my code I was seeing a common pattern:

(doto (ArrayList.)
    (.add (doto...))
    (.add (doto...))
     ...)

So I created a quick macro that I called doto-list that would bundle that piece up:

(defmacro doto-list [& forms]
     `(doto (ArrayList.)
         ~@(map (fn [item] `(.add ~item)) forms)))

Which then made the function look like:

(defn single-instance-result-example []
    (doto (DescribeInstancesResult.)
        (.setReservations
        (doto-list
            (doto (Reservation.)
	        (.setInstances
	            (doto-list
	                (doto (Instance.)
	                    (.setInstanceId "test")))))))))

Which I think is a nice improvement when I'm creating a decent amount of ArrayLists.

memfn

The next piece I used integration with the AWS APIs was memfn. The call to describeInstances returns a List of Instance objects which have a few fields I'm interested in. There are quite a few fields on the Instance object (20+) and I was only interested in a few. Furthermore, I also did not want the callers of the functions to have to know they were dealing with a Java objects. One was bean, which transforms an object into a map of it's bean properties. It seemed like it would work for me, but would pull over fields I cared about and a lot of ones that I didn't. It would also require knowledge of the Java object and the generated map structure. I thought a better way to do this would be memfn. The memfn macro takes an method name (and optionally arguments) and returns a function that takes an object as a parameter. The function then invokes the method on that object when called. It basically translates the above call into:

((memfn getPublicIpAddress) some-object)

This seemed closer to what I wanted, but what I really wanted was a function called "public-ip" that you could pass an instance to. So I ended up attaching a name to the memfn function that was returned by creating a little macro:

(defmacro defmemfn
     [name method-name & args]
     `(def ~name (memfn ~method-name ~@args)))

A call to defmemfn looks like:

(defmemfn public-ip getPublicIpAddress)

And asking for a public ip looks like:

(public-ip instance)

Up Next - Testing

In conclusion, I think that working with the AWS APIs was easy thanks to Clojure's great Java integration. Testing this code was also much easier than I thought which I'll post next.

9May/101

Narrowing the Scope of Globals with Let

I've been reading OnLisp by Paul Graham. It's about becoming a better Lisp programmer. It's written for Common Lisp, but I have found quite a bit of it carries over into Clojure. One interesting code snippit I found in the book was on using let when two functions required the same value. Previously I would have done this through a def, like below:

(def step-by 7)
(defn increment [x] (+ x step-by))
(defn decrement [x] (- x step-by))

Paul Graham instead approaches it like:

 (let [step-by 7]
	   (defn increment1 [x] (+ x step-by))
	   (defn decrement1 [x] (- x step-by)))

Obviously the example above is trivial, however there are times that shared immutable data is necessary. Database connection properties, connection URI information etc. I often have a small number of functions that need that sort of data. For these kinds of situations, I like this second approach. It more narrowly scopes the variable and I can't think of any drawbacks. I think this also highlights a difference in approach from imperative languages and functional languages in general. Paul (on page 30 of OnLisp) describes imperative language code structure as more "solid and blockish" whereas functional code tends to be more "fluid". The first example above fits the blockish imperative model where you define your variables and functions at the same level. This is exactly how I would go about it in Java. I've noticed that with the Clojure code I've been writing, and thinking back to code I've written in OCaml, it is definitely more fluid, a less rigid block structure. I've gone through about 6 chapters of the book thus far and am looking forward to reading through the chapters on macros.

Tagged as: , 1 Comment