Monday, July 30, 2012

Just make it small, please!

I have seen - and had to maintain - so many messed up, bad code in my carrier that it makes me wonder why I still work in this profession. In fact, I have rarely seen good, clean code. However, I can learn a ton going through open source code repos on Github.

The best definition I have found for clean code is by Michael Feathers captured in the book Clean Code: "Clean code always looks like it was written by someone who cares."

Do you really care about the code or the craft, when:

  • you put 2844 lines of code in the model?
  • you have 167 lines of code in one function?
  • you have several deep nested if statements in for-each loops?
  • you have 1354 lines of code in a js file that drives business logic?
  • you have no tests at all?

I attended the fantastic Simple Design and Testing Conference a while ago. One of the topics we discussed there was the most important principle we'd ask a developer should follow. DRY was the absolute winner.
We all know about and follow the DRY principle but I question if that's enough?

Quite frankly I don't have the patience to analyze a 60 line function loaded with iterators and conditionals. Even the code's author can not understand it 5 minutes after it was written.

My coding style has changed in the last 4-5 years. I tend to write code in a functional style, class objects with a single function that are not longer than 5-10 lines.
Here is one of those:

module Services; module Utils
  class DecryptsData

    class << self

      def execute(service_result)
        return service_result unless service_result.success?

        encrypted_data = service_result.fetch(:encrypted_data)
        decrypted_data = ::Encryption.decrypt(encrypted_data)
        data_key = service_result.fetch(:data_key)

        service_result[data_key] = decrypted_data
        
        service_result
      end

    end
  end
end; end

Look at this piece of code for a moment. Try to understand what I am doing here.

  1. A guard condition (line 7)
  2. Pulling the encrypted data from the context (line 9)
  3. Decrypting data (line 10)
  4. Pulling the key I save the decrypted data with (line 11)
  5. Saving the decrypted data in the context (line 13)

All I am doing is decrypting data. That's it. I am not querying the database, I am not validating data, I am not calling an external service and I am not looping through items and set properties based on some kind of predicate.

People might just shove this into the controller. I won't. I think about software as a collection of functions that's weaved together by organizer functions.

The benefits are enormous:

  • One function
  • -> which is short
  • Easy to understand
  • -> which is easy to test

You could say that I am doing something in Ruby that resembles to functional programming. I call functions on class objects, but the functions I am constructing are not immutable. And I new up an object and maintain state if I need to, but I try to avoid that for the sake of simplicity. I don't want anybody - who maintains the code I write - to spend a lot of time trying to understand what I am doing.

Is functional programming far for me? I don't think so, I believe I am just taking the first steps in that direction.

Tuesday, June 19, 2012

Frequent Job Change?

I've been making a living writing software for the past 12 years (and I am still not in management yet :-). I've worked for small startups and Fortune 500 companies with more than 2,000 people just in IT.

All together I have worked for 8 different companies which averages out at 1.5 year spent at each, the longest being 3 years at one place:

I interviewed with a small startup a couple of years ago and I still remember how disappointed the interviewer was when he learned about my job history. He asked me: "So can I expect you to work for me a year, or two if I am lucky?" What should I have said? We clearly were not a match.

Whenever I start a new job the most important thing for me is to be productive from day one. I am sure I won't understand all the business logic right away. It might take a few months to pick it up, but I strive to add value as soon as possible. If it's only by adding automated tests, it doesn't matter: I contributed.

I have clear goals of what I want to learn or practice in the future. But there were times when I picked up skills by chance.

I had to take courses on data warehousing and dimensional modeling when I worked for a large corporation. First I was not very interested in it, but as I learned more about the topic I realized that you can't use your OLTP database for data mining and reporting: you need to lay out data in a different format to make it efficient.

My views have changed on progressive enhancement thanks to the bright UX folks I had the pleasure to work with. I did not like the idea of making a web app "gracefully degrade" for a more solid architecture but they pushed me to develop applications that way. I thought this is crazy: why would I build the same logic twice with- and without JavaScript? But that's nonsense. If you architect your application properly, building your web app without JavaScript and adding it after is not all that hard. Besides, you don't have to write much more code.
Of course I wouldn't consider progressive enhancement if I was building a one-page web app, like the excellent Trello.

It's been only four months since I started working for my current employer and look what we have accomplished already:

  • We moved our source control repository to git and Github from Subversion, so it's easier for us to release code into different environments.
  • We began carving out business logic and putting it in a business logic gem, so we can easily share logic between different Rails apps.
  • We can drop, recreate and seed our development database in one, single script (yeah, I know, that did not work when I started), so our acceptance tests will have a set database state before they are executed.
  • Introduced Gherkin to the team so we make sure we build the right thing.
  • We are automating acceptance tests using Cucumber with capybara-webkit so our regression cycle is shorter.
  • We set up a build process using Jenkins so we can run both unit- and acceptance tests after each push to Github.
  • We started building new features with progressive enhancement so our application will graceful degrade on devices that can't handle JavaScript.

Dear Employer: please don't be afraid of hiring those "job-hopping" individuals. Just make sure you are selecting the right person and let them produce value from the very beginning. They might have picked up skills - you will need - here and there. When they write tested and clean code they can leave the job any day knowing that somebody else should be able to jump in and continue the work they've started.

Tuesday, May 8, 2012

Running Mocha Specs in the Browser

The way I've been writing JavaScript code might not appeal to other developers: I live my life in the terminal, I write and execute specs in it hitting the browser occasionally just to make sure everything I do works there. Others use the terminal as little as possible. One thing we have in common: we test our JavaScript code with Mocha.

I still remember the cold, autumn day when I first downloaded Jasmine's standalone test-runner a couple of years ago. All I had to do was unzip the file, hook in my own JS source and spec files and I was in business. It even had simple JavaScript objects like Player and Song guiding me through the first steps.

Mocha - unfortunately - does not have a downloadable zip file to help you get started and its browser based tool is deeply buried under its own tests. Extracting it from there takes time and effort.
This writing describes how you can get started with executing your Mocha specs in the browser.

I put all the code of this starter project in a Github repo: mocha-in-browser. You can either clone it or just download the project zip file.

I used the String Calculator Kata as an example. Open up the public/index.html file in your favorite browser and you should see this:

Just type 1,3 in the text box, hit the "Calculate" button and the correct answer appears in green color under the text box.

When you open up the spec/runner.html in the browser, Mocha is happily reporting the test output:

I did not finish the String Calculator Kata. Please work through it not only to sharpen your skills but to get familiar with JavaScript unit testing with Mocha as well.

You can drop the spec directory from this project into your working directory, reset your JavaScript source and spec files in the spec/runner.html file and start using it.

Both Mocha and Should.js are rapidly changing projects. I'd encourage you to download and use the latest source code of those projects as ofter as you can.
I created a Makefile to make this super simple for you. Just run "make" in the project root and you should have the latest version of those files brought to you by node.js and npm.

Monday, April 9, 2012

Refactoring Workflows to Chain of Actions

Everything we do in life is a series of actions. Just to get to work I need to wake up, eat something, brush my teeth and drive to work. Or when the data is sent to the server your code has to validate the user input, it has to create a new object with the attributes, this new data has to be saved and a response data needs to be generated in JSON format if your request happens to be an Ajax request.

When I write code for a series of tasks I start out with a "coordinator" object that has several private methods internally. The main and public method orchestrates the calls for the private methods. The tests around this object start out pretty nice, but as the complexity grows I need to stub more and more external objects. The complexity of the tests are soon becoming indicators of the worsening design and I need to start pulling out objects before the whole thing turns into an iceberg class.

The example I use in this writing is a simple one: The "Dude" wants to go to the park to enjoy the nice weather. He has to go through several steps to get there:

  1. Leave the house
  2. Close the door
  3. If he has a car - Jump in the car
  4. If he has a car - Drive to the park
  5. If he has a car - Park the car
  6. If he has NO car - Jump on the bike
  7. If he has NO car - Ride to the park
  8. If he has NO car - Park the bike
  9. Enter the park
  10. Take a walk

All my examples are in CoffeeScript. I use CS for brevity and for its concise format.

In my example the coordinator object is called "GoesToThePark". It interacts with the House, Car, Bicycle and Park models like this:

And all this described in CoffeeScript:

House = {
  leave: (dude) ->
    'leaves the house'
  closeTheDoor: (dude) ->
    'closes the door'
}
Car = {
  jumpIn: (dude) ->
    'jumps in the car'
  driveToThePark: (dude) ->
    'drives to the park'
  parkTheCar: (dude) ->
    'parks the car'
}
Bicycle = {
  jumpOn: (dude) ->
    'jumps on the bike'
  rideToThePark: (dude) ->
    'rides to the park'
  parkTheBike: (dude) ->
    'parks the bike'
}
Park = {
  enter: (dude) ->
    'enters the park'
}

class GoesToThePark
  constructor: ->
    @messages = []

  toEnjoyTheWeather: (dude)->
    @messages.push House.leave(dude)
    @messages.push House.closeTheDoor(dude)
    if dude.hasCar()
      @messages.push Car.jumpIn(dude)
      @messages.push Car.driveToThePark(dude)
      @messages.push Car.parkTheCar(dude)
    else
      @messages.push Bicycle.jumpOn(dude)
      @messages.push Bicycle.rideToThePark(dude)
      @messages.push Bicycle.parkTheBike(dude)
    @messages.push Park.enter(dude)

Please check out this gist to see the specs. I used mocha to test-drive my code.

It's all nice and sweet. Except we have that nasty "if statement" in the middle of the GoesToThePark#toEnjoyTheWeather method.

Whenever I see a conditional block in the middle of a function call I immediately assume the violation of the Single Responsibility Principle.
I tolerate guard conditions in methods, but that "if statement" must die.

I remembered in my early Java and C# days reading about the Chain of Responsibility design pattern. Every little command object is linked together with a linked list, the first one is called from the "coordinator" object and they each check if there is anything to do with the arguments. If there is, the action is executed and at the end of the method call the next command in the chain is being called.

I found them especially helpful in workflows similar to the example described above. The coordinator object only knows about the action objects and its only responsibility is to call the one and only method on them in order. There is no conditional in the method any more, the actions are smart enough to figure out if they have to deal with the object in the context or not.

I introduce the four new action objects:

  1. LeavesTheHouse - delegates calls to the House object
  2. DrivesToThePark - invokes the methods on the Car object if the dude has a car
  3. RidesToThePark - sends messages to the Bicycle object if the dude has no car
  4. EntersThePark - executes the enter method on the Park object
Only the DrivesToThePark and RidesTheBikeToThePark protects itself with guard conditions, their execution is dependent on the fact of the Dude having a car or not. But those are simple return statements at the very beginning of the method call.

...

LeavesTheHouse = {
  execute: (messages, dude) ->
    messages.push House.leave(dude)
    messages.push House.closeTheDoor(dude)
}

DrivesToThePark = {
  execute: (messages, dude) ->
    return unless dude.hasCar()

    messages.push Car.jumpIn(dude)
    messages.push Car.driveToThePark(dude)
    messages.push Car.parkTheCar(dude)
}

RidesToThePark = {
  execute: (messages, dude) ->
    return if dude.hasCar()

    messages.push Bicycle.jumpOn(dude)
    messages.push Bicycle.rideToThePark(dude)
    messages.push Bicycle.parkTheBike(dude)
}

EntersThePark = {
  execute: (messages, dude) ->
    messages.push Park.enter(dude)
}

class GoesToThePark
  constructor: ->
    @messages = []

  toEnjoyTheWeather: (dude)->
    for action in [LeavesTheHouse, DrivesToThePark, RidesToThePark, EntersThePark]
      do =>
        action.execute(@messages, dude)

...

You can review the entire file in this gist.

The beauty of this code lies in the toEnjoyTheWeather() method. It is simple and now it's super easy to test.


... 

  toEnjoyTheWeather: (dude)->
    for action in [LeavesTheHouse, DrivesToThePark, RidesToThePark, EntersThePark]
      do =>
        action.execute(@messages, dude)

...

In fact, I worked on a Ruby code where the coordinator object called a dozen different objects through it's private methods. Tests were brittle, I had to stare at the code to figure out why something was failing after a simple change. My specs were a clear indication that the code needed serious refactoring. I changed my code using the pattern above and I eliminated all the private methods - they became simple action objects - and testing became much simpler.

Here is what it takes to test the coordinator object's method with stubs:

should = require 'should'
sinon = require 'sinon'

...

describe 'GoesToThePark', ->

  it 'calls the actions in order', ->
    goesToThePark = new GoesToThePark
    messages = goesToThePark.messages
    dude = {}

    leavesTheHouseStub = sinon.stub(LeavesTheHouse, 'execute') \
                              .withArgs(messages, dude)
    drivesToTheParkStub = sinon.stub(DrivesToThePark, 'execute') \
                               .withArgs(messages, dude)
    ridesToTheParkStub = sinon.stub(RidesToThePark, 'execute') \
                              .withArgs(messages, dude)
    entersTheParkStub = sinon.stub(EntersThePark, 'execute') \
                             .withArgs(messages, dude)

    goesToThePark.toEnjoyTheWeather(dude)
    entersTheParkStub.called.should.be.true
    drivesToTheParkStub.called.should.be.true
    ridesToTheParkStub.called.should.be.true
    entersTheParkStub.called.should.be.true

I leave you the exercise of writing the specs with stubs for the example prior to using the action objects.

Listen to your tests, they tell you the story (or the quality) of your code. Don't be afraid of creating tiny classes or objects with only 6-10 lines of code. They are super easy to test and I consider them the building blocks of reliable and maintainable software.

Big thanks to websequencediagrams.com for their tool I used to create the sequence diagram in this blog post.

Monday, March 5, 2012

Job Change

After about a year of employment I decided to leave my employer.
We have had great times together: I worked on their software rewrite, helped them move from 23 (most of them failing specs) to some 5700 passing specs and we started on the curvy path of automated acceptance tests. I had worked with some amazing people there whom I'll miss in the future.

I wasn't looking for a new job. No, but an opportunity came up and I did not want to miss it.

A good friend of mine - Dave Speck - joined a small startup in Independence, OH late last year. I talked to him a couple of times and it seemed I could do a lot of things there. A few meetings and some beers later I made up my mind: I joined Dimple Dough in the middle of February.

I have only worked there for a little over a week but we have already done so much!
Here is one of them:

We can provide basic translation for our international clients, but some of them want to further customize it. The only way they can make translation changes is sending us what they want to change and one of our engineers has to do the updates in our database. Our customers would be happy to do it themselves, if there was a tool they could use. Hence the translator idea was born. We had a vague idea what it will look like but we did not know how the tool SHOULD exactly WORK.

We started by prototyping the tool in pure HTML with CSS and JavaScript. The benefit of doing this is the low cost of change. Imagine how far less expensive it is to modify a raw prototype than the fully functioning product. There are no domain objects, data models, data migrations to change when the client wants to tweak the preview version. It's just a dummy HTML with very simple jQuery that allows us to demonstrate it to the client who can provide us feedback well before development begins.

Once we knew our prototype was close to what we wanted to build and our customer was happy with it we sat down with our business and quality focused team members. In this "three amigos" meeting (BA, QA and Developer) we wrote scenarios in Gherkin syntax using our prototype and other documentation the team had collected by then.

It made me smile to realize that after the first three or four scenarios we were discussing edge cases nobody thought about before. The scenarios we came up with are short and are not tightly coupled to the User Interface, they explain how this new tool should behave.

I tried using Gherkin and cucumber at my previous employer, but I don't think it really caught on there. After talking with @chzy (Jeff Morgan) on a cold December morning I understood why: we used Gherkin for automated system testing and not to discover functionality with BAs and QAs prior to development.

Monday, January 23, 2012

JavaScript Testing with Mocha

JavaScript is a neat and powerful language. Sure it has its flaws, but serious software can be developed with it. The way I prefer developing JavaScript applications is by test driving the code with some kind of testing tool. And I am not thinking about hitting the browser's refresh button. No, I mean executing the specs right in the terminal.

I recently started playing with Visionmedia's mocha testing framework. The code is well maintained and the authors are responding fairly fast to pull requests or issues.
I would recommend it as an alternative to Jasmine.

This blog post will show you the first couple of steps you need to take to test drive your JavaScript code with mocha in the CLI. All my instructions are for OS X, but setting it up should be very similar on Linux and (maybe) on Windows as well.

First of all, you need node.js to run JavaScript code in the terminal. You can download the source code and compile it yourself, but I'd recommend using Homebrew and let it do the job for you.

$: brew install node

At the time of this writing my current node version is 0.6.6. You can check your node.js version by running this command:

$: node -v
v0.6.6

Next you need node's package management tool (npm). Your version of node may include npm, I list this step here in case it does not. Installing it is super easy, just follow the instructions on their web site and in your terminal.

With these two steps you're ready to roll. Create the project directory, cd into it and start moving in. Create a "src" and a "test" directory. You need to install mocha and should.js as npm packages. Having sinon.js - an excellent spying framework - wouldn't hurt either. Create your spec and source file and you are ready to test drive your app with mocha.

I really wanted to help you - Dear Reader - so I created this shell script to make your life easier. Create a directory, cd into it and run the command below in your terminal:

   curl -L http://git.io/setup_mocha_project | sh

If everything goes OK, you will see this:

create the src directory...
create the test directory...
write the package.json file...
install npm packages...

create a sample spec file...
create a sample src file...
run the spec with mocha...
  .

  ✔ 1 tests complete (1ms)

run the spec with list reporter...

   Person should be able to say hello: 1ms

  ✔ 1 tests complete (2ms)

Let's add one more feature to our Person object. Open up the test/person_spec.js file - it was created by the shell script above - and add the "can say good night" spec:

var should = require('should');
var Person = require(__dirname + '/../src/person');

describe('Person', function() {
  it('should be able to say hello', function() {
    var Person = global.theApp.Person();
    var personInstance = new Person();
    var message = personInstance.sayHelloTo('adomokos');

    message.should.equal('Hello, adomokos!');
  });

  // Add this spec
  it('can say good night', function() {
    var Person = global.theApp.Person();
    var personInstance = new Person();
    var message = personInstance.sayGoodNight();

    message.should.equal('Good night!');
  });
});

Run the mocha specs with this command:

$: ./node_modules/mocha/bin/mocha

The error is obvious: the Person object does not yet have the method "sayGoodNight".

  ..

  ✖ 1 of 2 tests failed:

  1) Person can say good night:
     TypeError: Object [object Object] has no method 'sayGoodNight'

Let's fix it by adding the missing method to the Person object:

global.theApp = {};

global.theApp.Person = function() {

  var Person = function() {
   this.sayHelloTo = function(anotherPerson) {
      return 'Hello, ' + anotherPerson + '!';
    };

   // Add this method
   this.sayGoodNight = function() {
     return 'Good night!';
   };
  };

  return Person;

};

When I run the specs again, they all pass.

  ..

  ✔ 2 tests complete (2ms)

You can try other reporters as well. The "list" reporter will give you the documentation text:

$: ./node_modules/mocha/bin/mocha -R list

Try the landing reporter, I found its output unexpected but really cool!

$: ./node_modules/mocha/bin/mocha -R landing

The steps once more:

  1. Make sure you have node.js installed
  2. Check for npm as well
  3. Create your project directory and cd into it
  4. Run this script $: curl -L http://git.io/setup_mocha_project | sh
  5. Execute the specs with $: node_modules/mocha/bin/mocha
And I almost forgot: mocha will pick up CoffeeScript files as well.

Enjoy!

 

::: Update (01/24/2012):
I asked TJ Holowaychuck, the author of Mocha of what thoughts he had on my blog post. He recommended adding a "test" script to the package.json file making it easier to run the specs. I made that change: npm test executed in the terminal should run all your specs under the test directory.

Monday, January 2, 2012

The Tic-Tac-Toe Game

I've been pretty busy lately working on this Tic-Tac-Toe game. It all started as a project to learn CoffeeScript, Backbone.js and turned into a big journey into JavaScript and node.js.

I am test-driving the code with jasmine-node, a great node adapter to Jasmine BDD.
The computer's moves are quite predictable, I will work on that in the future.


Won: 0
Lost: 0
Tie: 0

Enjoy!