Monday, January 30, 2012

Artisan: Week 2

It was a pretty quiet day at the 8th Light office today. As such, I was able to study the Artisan (our project management tool) code base more in depth along with completing some small clean up stories. Looking at Artisan today reminded me of my first week at my previous job. Diving head first into an existing code base can be overwhelming regardless of how large it is. Artisan's code base is by no means bad and is fairly well maintained, but it is still daunting to try and grasp everything that is going on. I've used two methods to help me try and understand features in the code base. 1) I look at specific use case in the UI and then try and trace the feature the entire way through the system. 2) Look at the tests. This method may be harder for those who don't have a large suite of tests wrapping their application, but lucky for me Artisan is well tested. However, some tests with in the code base are really hard to read, especially tests that make heavy use of stubbing. This had made me realize that I probably shouldn't use much stubbing in my tests because it is really hard for others to understand. Setting up five stubs, then calling one method isn't really too helpful to read and doesn't always reveal the intend of the test. So, this is yet another reason that I prefer to use hand rolled mocks over framework stubs. Overall, I think I'm learning a lot about Rails development through working on Artisan, but there are still some pain points (like slooooow tests).

Friday, January 27, 2012

First Live Kata

I had the pleasure of presenting the Ruby to JSON kata that I posted a few days ago at 8th Light University today. I had a few issues towards the end of my kata, but overall it went well. When I first started practicing the Ruby to JSON kata, it took me around 10-12 minutes to complete. The video I posted a few days ago took me about 8 minutes. Today it took me about 6. In order to cut the time in half I had to practice this kata relentlessly for a few days. I think that I have probably written this kata close to 50 times now. But, that is what it takes to perform a cool kata in 5ish minutes. One cool thing that I did for my kata was playing music in the background. I made this decision because my kata did not really need any specific narration and I didn't want the silence to be awkward. Through this I discovered that it is really hard to perform a kata along with music. I don't just mean playing music in the background while you code, but actually pacing yourself to play along with the music. Towards the end of my practicing for the kata, I was able to do this pretty well. I picked a song throughout that lasted 5:30 and was able to track myself with certain markers in the song. However, during the live presentation, it flopped because I was so nervous. At first, I was typing really slow and got really behind in the song. Then, I had a few typing mistakes that put me behind further. In the end, I finished about 30 seconds after the song, which stinks, because in my practice I would usually end the kata about 15-30 seconds early (the song fades at the end). Overall, I believe that I benefitted a lot from performing the kata and I think (hope) that the views did as well.

Thursday, January 26, 2012

Working with Rails again

After working with Clojure for the majority of my apprenticeship, I'm now working on a Rails project. The transition has been pretty smooth, but nonetheless it has certainly been a different experience. In may ways, it feels like I am learning Rails all over. In my previous experience with Rails projects I never practiced TDD. So, now I am learning how to write good tests with rspec. Which, as it turns out, is kind of hard in Rails. Also, I'm learning how to write testable (i.e. good) code in Ruby, something I have never done. One of the ways we are attempting to write testable Rails code is abstracting all the actually application logic away from Rails. This is great. It makes it really easy to test the core application logic without being coupled to Rails. What sucks about this is that there really isn't that much core application logic, or at least there is not that much abstracted. The bulk of the application is the UI. Therefore, most of features are implemented with a combination of Haml, Coffee Script and Ruby, wherein lies the difficulty in testing. For each feature, we have to write rspec tests, Jasmine tests, and cucumber acceptance tests. Something about this doesn't sit quite right with me, however, I'm not quite sure why yet. Perhaps I will write a future blog analyzing what about this perturbs me. However, the transition to Rails has made me realize a one things about Clojure development that I took for granted. The Speclj auto runner. Writing tests an getting instant feedback is a complete game changer. I didn't realize this until we started writing tests a few days ago and had to manually run the tests every time we changed something. It was a complete waste of time. So we started using rspec-guard, a nifty gem that auto runs rspec tests upon change. However, this was only a partial solution. After getting guard up and running with our project, I realized that I wasn't getting the instant feedback loop that Speclj provided me. This is because every time guard detects a change, it has to reload the spec helper file, which essentially reloads Rails. So, every time I changed a spec file that has two tests in it, I have to wait 10 seconds for Rails to load. This is huge time waster. I'm guessing that the solution to this problem is to not use Rails, or at least isolate it as much as possible. However, that doesn't seem like too feasible of a solution with the current project I'm working on because as I said previously, there isn't really that much application logic. So, what can I do? Anyways, moving back in to Rails code has been interesting to say the least.

Chicago Clojure Meet Up: Overtone

Last night I had the pleasure of attending the Chicago Clojure meet up on Overtone. This was actually the first meet up I've ever attended. Over all, the experience was really cool. First, I was pleased to see 20 people gathered about Clojure. I love Clojure and I was excited to see other people passionate about Clojure. Second, the software demoed, Overtone, was really cool. Kevin Neaton, one of the contributors, gave an hour and a half demo on the capabilities of the Overtone, and a brief preview of where the project is going. For those unfamiliar, Overtone is an open source project that allows users to create musical synthesizers. So, Kevin started the night by showing us a very simple sine wave and then incrementally built upon it throughout the night until he created a dub-step beat. Pretty cool. The Overtone project offers the benefit of being written in Clojure, which offers some cool features, for instance, recursive beats. The built-in recursion of Clojure allows users to create recursive beats with ease. Also, it offers users the REPL. Users can fire up the REPL and create, test and demo beats on the fly without a ritzy setup. Overtone seems like a great tool for musicians and audiophiles alike. However, being neither of the two, I don't see myself using Overtone much, except of course to play around a see what comes out. Overall, I had a great time at the meet up and I hope to keeping attending.

Tuesday, January 24, 2012

Ruby to JSON Kata

I spent a large portion of my day today practicing for the Kata that I will be presenting on Friday. My original intention for this Kata was to take a well known kata that has a commonly accepted solution and rewrite it without using mutable data. Unfortunately, I was unable to find an existing kata that would showcase immutable data well. So, I decided to use the kata written by a fellow apprentice, Patrick Gombert, which does showcase immutable data rather well. Following is the Ruby implementation of this kata. Originally, this kata was written using Clojure, which really showcased immutable data. I believe that my implementation could be greatly improved by Clojure multimethods, which is what I would like to try tomorrow.

# Acceptace Criteria # ------------------ # nil -> null # Fixnum # Float # Booleans # Strings # Symbols -> converted to strings # Arrays -> all values converted to JSON # -> values can be anything # Hashes -> all values and keys converted to JSON # -> ignores keys that are not Symbols or Strings # -> values can be anything def str_or_sym?(data) data.is_a? String or data.is_a? Symbol end def convert(data) if data.nil? "null" elsif str_or_sym?(data) "\"#{data}\"" elsif data.is_a? Array "[#{ {|entry| convert(entry)}.join(", ")}]" elsif data.is_a? Hash "{#{ {|key, value| "#{convert(key)}: #{convert(value)}" if str_or_sym?(key)}.select {|x| !x.nil?}.join(", ")}}" else data.to_s end end describe "Ruby to JSON" do [ [nil, "null"], [1, "1"], [1.0, "1.0"], [true, "true"], [false, "false"], ["a", "\"a\""], [:a, "\"a\""], [[nil, :a], "[null, \"a\"]"], [{:a => nil, :b => :c}, "{\"a\": null, \"b\": \"c\"}"] ].each do |value, json| it "convert #{value.class}" do convert(value).should == json end it "array values can be #{value.class}" do convert([value]).should == "[#{json}]" end unless str_or_sym?(value) it "ignores hash key type #{value.class}" do convert({value => 1, :a => 1}).should == "{\"a\": 1}" end end it "hash values can be #{value.class}" do convert({:a => value}).should == "{\"a\": #{json}}" end end end

Monday, January 23, 2012

Prime Factors Kata with Immutable Data

Here's my take on the Prime Factors kata in Ruby. I set out with the goal to use immutable data instead of the normal implementation which mutates an array. Check it out here.

Friday, January 20, 2012

Dependency Inversion Principle

In a recent project I have been working on, I've been learning a lot about the Dependency Inversion Principle. There were some places in our code base were Micah showed us how we were violating the DIP and showed us how to refactor. In short, the DIP states that no module should be dependent on a concrete class, but rather an abstraction. Violations of this principle are commonly seen in higher level modules depending on lower level modules, such as a UI depending on a Controller or Model. This means that the modules within the UI become coupled and are not able to be reused later. In our case, our UI layer was directly depended on the concrete implementation of our application classes. In order to adhere to the DIP, we needed to refactor so that our UI was not dependent on our application logic. This required that we build two abstractions. We built an abstraction for the application (called an Interactor) and an abstraction for the UI. The UI interface talks to the Interactor interface and the Interactor interface talks to the UI interface. This allows the UI to be decoupled from the application logic. So, in theory, we could build another implementation of the application underneath of the UI and the UI would be none the wiser. By the same token, we can now build any number of UI's on top of the application and the application is non the wiser. The second scenario is not really a theoretical possibility, but reality. There are tentative plans to build a web application on top of the current architecture (in addition to the desktop app we are building now). Without these abstractions, building the new Web UI would turn the code base into a tangled mess that no one could maintain. So, in summary, always program to an interface or abstraction, never a concrete class.

Thursday, January 19, 2012

Test Generation with speclj

Let's start with a simple test definition in speclj, the BDD testing framework for Clojure.

(describe "my module" (it "has the correct value" (for [item {:item1 "value1" :item2 "value2"}] (should= (val item) (get-value item)))))
This test simple asserts that my module has the correct value for item1 and item2. Pretty simple. Ok, let's say that we add 15 more fields to my module. Our test will now look like this...

(describe "my module" (it "has the correct value" (for [item {:item1 "value1" :item2 "value2" :item3 "value3" (etc.)}] (should= (val item) (get-value item)))))
Not too bad. For every test that we add all we have to do is add a key and value to the for loop. Seems pretty extensible to me. So later, one of the assertions fails. However, we only get one error. Thats not good. That makes it seem like our entire module is broken. We first have to identify will field the test broken on, then we have to go fix the bug. This could be especially painful if there were more like 1000 fields! Ok, so lets find a better solution. Consider this example.

(describe "my module" (for [item {:item1 "value1" :item2 "value2"}] (it (str "has the correct value for " (key (name item))) (should= (val item) (get-value item)))))
So what is different in this example? Instead of generating assertions inside of the (it...) block, we loop over it and generate a bunch of (it...) blocks. So what is useful about this? If we consider the example above were "my module" has 1000 fields. Using this new method, we will be able to tell exactly which field this test failed on. This is extremely helpful because it cuts out the entire time it takes to find which assertion was the culprit of the failure. Also, when this module fails, not every test will fail. We will get better feedback on what is actually being tested and breaking. So, in summary, if you need to test a large list of items, it's better to generate tests for it rather than generating assertions.

Wednesday, January 18, 2012

ns-resolve in Clojure

One interesting feature of Clojure that I was able to make use of today is ns-resolve. This feature allows you to dynamically find a var within a specific namespace. This is especially useful for dynamically calling a function, given a string. I have also used this method in the metis validations project to dynamically load validation functions. Consider the snippet from metis,

(defn get-validation [validatior-key] (if-let [fn (ns-resolve 'metis.validator.validations (symbol (name validatior-key)))] fn (throw (Exception. (str "Could not locate the validator: " (name validatior-key))))))
Here I'm using ns-resolve slightly differently because this method is within the metis.validator.validations namespace already. This function is used to retrieve a validation function based upon a keyword. For instance, (get-validation :inclusion) returns the function inclusion from the validations namespace. This is allows us to not violate the open/closed principle. Users have access to the entire namespace by only using one method on the namespace. This means that if a new validation is added, the user does not have to change their namespaces imports to use it, they just start using it. In this way, the validator is closed to modification and open to extension.