Archive for the 'Beautiful Code' Category

The Specification is the Documentation Part Two

Tuesday, August 5th, 2008

Two (related) thoughts on “The Specification is the Documentation“.

One of the things that I like to do, when developing, is to start with a sketch (you know, with 95g/m2 paper and a 6B pencil) of how the UI will look. There are two reasons for this. Firstly, it helps communications with the client – they can see something concrete, while it’s also blatantly apparent that there’s a long way to go yet. Secondly, it puts me in the position of starting from the ideal position and working “downwards” to what is possible, rather than starting from what is easy and working “upwards” to what is nice. In other words it forces me to raise my standards.

Writing my specifications with the helper methods as described is the coding equivalent. I start with a high-level, abstract, description of the problem I am trying to solve (“given a logged in user and three gizmos, expect the gizmos to be tagged when I go to the ‘tag-gizmos’ page”). I then work on setting up the environment (implementing the helpers) and the getting the specification to pass (implementing the code). Again, I start with the ideal position and work downwards as I implement.

The second thing is that it is one of those techniques where I am sure that I am along the right lines. How can I tell? Because as soon as I wrote my first specification in this way it “felt right”. After I had written a couple more I wanted to go back to every piece of code I had ever written and rewrite it all in this new way.

The Specification is the Documentation

Friday, August 1st, 2008

In a former life I used to write “functional specifications”. These were long, dense, hard-to-read documents that detailed what an application (not yet written) was supposed to do. I would spend (literally) weeks typing these things up, the customer would read it, think they understand and I would quote them based upon the document. And then the project would go over budget as all the tiny subtle details became apparent about two weeks before deadline day. But, even worse, the document would slowly become out of date, as changes were made in response to feedback – while the spec stayed unchanged.

As you might expect, this lead to general disillusionment with functional specifications. What’s the point if they didn’t help with the budget and didn’t reflect the actual application?

But when I read about Test-Driven Development the key thing that struck me was the tests became a living embodiment of what the application is supposed to do. They are a specification; but not only that, they are a specification that has to remain up to date.

Only one problem. They are written in code. Making them meaningless to the client. In fact, often, some tests were so obscure they were only meaningful to me; as I was writing them. Come back to it six months later and try and figure out why that change has made it fail? No idea.

Which is why RSpec and its Stories are so exciting. A Story is a text document that describes the required behaviour of the application. Read that again. A text document; written in English. So your clients can read them. Can help to write them. You then supply some Ruby code, that matches the sentences in your stories and associates them with code. That code is run, testing your application and proves that it does what it is supposed to (providing you’ve written your test code correctly of course).

Story: measure progress towards registration goals
  As a conference organizer
  I want to see a report of registrations
  So that I can measure progress towards registration goals
  Scenario: one registration shows as 1%
    Given a goal of 200 registrations
    When 1 attendee registers
    Then the goal should be 1% achieved 

  Scenario: one registration less than the goal shows as 99%
    Given a goal of 200 registrations
    When 199 attendees register
    Then the goal should be 99% achieved

Now, I have to admit, I’ve not used RSpec Stories in anger yet. But it has had a strong effect on my “unit” tests.

The difference between stories and unit tests are that stories test your full stack. Go to ‘/’, fill out the text fields, click the submit button, it should insert into the database successfully and then show these three records on the ‘/whatever’ page. Unit tests will check that the form is shown when you go to ‘/’. A separate test will check that your record can be inserted into the database. Another test will prove that ‘/whatever’ asks the database for three records.

But, having read about Stories, the way I write my unit tests have changed. Check this controller specification out:

describe ReportsController, "at the admin site" do
  it "should show this month by default" do
    given_the_admin_site
    given_a_system_user

    when_getting :index do

      expect_to_find_orders_for Date.today

    end

    assigns[:date].should be_today
    assigns[:orders].should == @orders
  end
end

Not quite plain English. But, when it comes to maintenance, using given, expect and when as prefixes for your helpers makes a world of difference.

 

UPDATE: now using block syntax around the “when_getting” statement

Setting up a mock object to test a :dependent => :destroy association in RSpec and Rails

Thursday, July 10th, 2008

One of the great advantages of using mock objects to test and specify your objects is that you concentrate solely on the thing you are testing.  

If you weren’t using mocks to tests that a controller re-shows the “new” form if given an invalid object, you would do post :create, :model => { ... } where … is a set of fields that are invalid. This means that, when writing your spec, you have to remember what it is that makes that model invalid. This also means that, every time you change that model, and its rules for validity, you potentially have to amend the controller test as well. In other words, you are not actually testing the controller in isolation, you are also testing the model.

Using mocks lets you write the following:


  @model = mock Model
  Model.should_receive(:new).and_return(@model)
  @model.should_receive(:save).and_return(false)
  post :create, :model => { :some => :fields }
  response.should render_template('/models/new')

In other words, it doesn’t matter what parameters you send to create. The Model (class) will return you a mock instance of model, and the mock instance will return false on save (you can actually get save! to raise an ActiveRecord::RecordInvalid – but I’ve had some difficulties with that). In other words, the real model is no longer part of the test and you are concentrating on the behaviour of the controller alone.

This concentrating on what is important is a vital advantage when using mocks.

But how does this work on testing models?

I wanted to test that a default value was copied from one field to another under certain circumstances. So I set up a method, called set_default_value and wrote some specs to ensure that it was working. Then I wrote the following:


  it "should set the default value before validation" do
    @model = Model.new
    @model.should_receive(:set_default_value)
    @model.valid?
  end

This failed, as it should do. Then I set a before_validation :set_default_value on the model and the spec passed. Each spec concentrates purely on what is important – a couple to show that set_default_value works under different circumstances, and one to show that it is called when it is supposed to be.

What about testing a :dependent => :destroy association?

Unfortunately, that can’t be done without saving at least one of the objects in the association (which means knowing enough about it to make it valid). But, as David Chelimsky (Mister RSpec) points out on the RSpec mailing list, you can do it using mock objects for part of the association. Which was a relief as my “child” object was complex with a whole set of interdependencies of its own.

To DRY or not DRY?

Wednesday, July 9th, 2008

A very interesting article about how DRY you should be in your specs.  

http://lindsaar.net/2008/6/24/tip-24-being-clever-in-specs-is-for-dummies

Personally I agree with everything said.  Readability comes first, even at the expense of efficiency and DRY; “be nice to those who have to maintain the code”.  The really interesting thing though is the example is actually quite DRY – it’s more about how you organise and order the code, more than repeating yourself.  

Ruby on Rails Basics

Wednesday, May 21st, 2008

Sometimes, it’s worth stating the basics for all to see:

  • Follow the Model-View-Controller paradigm.  In particular, your views house your user-interface, your models handle the application and your controllers mediate between the two.  Controllers do not contain rules, conditionals dealing with business conditions, queries looking for objects related to the one in question.  All those things belong in the models.  
  • Use ActiveRecord conventions at all times.  It may not be the most efficient thing in the world but for most of you out there, it doesn’t matter.  
  • Use ActiveRecord and migrations to define and manage your database.  All your business related stuff stays in one place – the models – including defining relations (associations), validations and rules.  In particular, ActiveRecord associations makes some tasks easy (very simple many to many relations) and gives you things (such as polymorphic associations) that you can’t safely define using straightforward SQL.  With judicious use of validations you can ensure that the data stays safe.  
  • Use RESTful designs in your controllers.  This means that your controller very rarely grows beyond seven actions (index, show, new, create, edit, show, destroy) – and RESTful routing ensures that GETs and POSTs go to the right places.  If you need to extend things then add a sub-controller.  For example, if you were transferring an employee to another, you could have a route: /employees/1 for the employee him/herself, /employees/1/transfers/new to let the user define which company the employee is moving to and /employees/1/transfers/create to actually do the transfer.  And if you’ve defined your model correctly, the implementation of /employees/1/transfers/create should be as simple as @employee.transfer_to(@company)
  • Write your tests (or specs) first.  One – this gives you a series of small wins, which is good for your self-esteem.  Two – it helps to clarify your thinking.  ”I need to write something that does X and Y, resulting in Z … oh hang on, do I really need Y?  What about U and V?”
  • Use mock objects when testing your controllers.  Why bother coming up with lots of test data when all you really need to say is “if I the model saves correctly then redirect to X, if it doesn’t save then show Y”.  In the “transferring employees” example above, you only need to test that the controller calls “transfer_to” on your model.  Of course, your model will have already tested that transfer_to does what is expected of it.  
  • If you find yourself repeating a bit of code, or writing something similar then STOP and refactor.  Add methods to the application controller, create a new controller descendant, stick it in a view helper, add a module to your models, write a partial (and if it needs parameters, write a helper that takes a set of parameters and does the call to render :partial for you)
  • Did I say write tests and specs first?
  • Oh, and if it starts getting complicated you’re almost definitely doing it wrong.  

rake db:fixtures:load

Friday, November 9th, 2007

rake db:fixtures:load is probably one of the most useful commands I have used recently.

You see, I was meeting some people about some potential work. They wanted to see an example – preferably related to payment systems. I had some code but unfortunately, the service that is part of had been switched off (a number of reasons, none of which connected to my supreme stylings). I had a copy of said code on my machine, but no database and I had no time to prepare.


So how could I demo it? Easy peasy.


cd ~/Source/my_app
rake db:migrate
rake db:fixtures:load
ruby script/server

And then start Camino.

Because the application had been developed test-first I knew that there was a decent set of data within those fixtures. Data designed to show all the edge cases, all the complexities of the application. From users and logins through to payment records and customers.

It is fair to say that when writing your applications, test-first, the fixtures are the hardest thing. It can take ages and it is detailed, painstaking work. Especially if you are trying to build a narrative (:dave logs in, selects a :cucumber, goes to the :checkout, pays with his :expired_credit_card which is rejected).

But the benefit is there. Building a narrative helps you when you come back to the code in six months time. Defining a wide-range of test fixtures helps you when you make changes and need to ensure that it won’t break a feature over there. And it helps you demo your code in front of a prospective client when faced with the unexpected.

Data Highway by KLatham.

If you find this useful then please take a look at some of my other writing – or recommend me on Working with Rails. Cheers.

My favourite plug-ins

Thursday, October 25th, 2007

You know how it is – there are some things that you are just not comfortable without. My phone in my back pocket, my wallet in my front pocket, the key in the front door when I go to bed (just in case there’s a fire and we have to make a hasty exit), the dog under my feet (tripping me up), one of my large collection of jackets (current favourite: leather biker jacket).

And so it is with Rails projects. Before I do anything I do the following:

  • Load the Exception Notification plug-in and configure it with my email address
  • Load the form_test_helper plug-in so I can confidently test my forms
  • Load the ARTS plug-in so I can confidently test my AJAX user interfaces
  • Load Markaby so my views are beautifully coded and semantically correct
  • Create the Rails session store within the database (rake db:sessions:create)

Of these, the one I really can’t do without is Markaby (although ARTS comes a close second). I don’t know what it is (apart from Why the Lucky Stiff is genius). I can’t stand looking at rhtml files any more – too many angle brackets for a start. Instead, my mabs are things of beauty – and as I write the code to produce the views, I find that they are more semantically correct as well. For example:


div.row do
label "Email Address: "
text_field :person, :email_address
p.explanation "Please supply a valid email address so that we can send you a confirmation email"
end

As I’m writing the Markaby code, class names like “explanation” seem to fit naturally – the code reads better, the HTML is semantic and the CSS is simple.

What more could you want?

Why you should use PHP instead of Rails

Sunday, September 23rd, 2007

or why Jeremy Kemper joined 37Signals.

Ok. All that being said, I’m looking forward to using Rails some day when I start a brand new project from scratch, with Rails in mind from the beginning.
But I hope that this reaches someone somewhere thinking, “God our old code is ugly. If we only threw it all away and did it all over in Rails, it’d be so much easier!”

The advantage of testing first

Saturday, September 22nd, 2007

I really like Test-Driven Development. Think about what you need to write, write a test (that fails), then make it pass. Repeat. Refactor.

Obviously, the major benefit is that further down the line you can be sure that what you are writing today won’t break what you (or someone else) wrote six months ago. The tests also serve as a type of documentation (why is that method on the invoice class so complicated? let’s simplify – oh, that test fails – it appears you can’t allow the invoice value to be less than £3 on a Wednesday) – especially if you are using RSpec.

But one advantage, that I feel is often overlooked, is because you are starting from the point of view of a user of your code, your method names and parameters are automatically designed from the user’s perspective, not the implementor’s perspective.

One of my favourite examples is

dave.hit nail, :on => :head, :with => hammer.

This makes your method definition look like


def hit target, options
place = options[:on] || :head
object = options[:with]
...
end

In other words the method definition does not reflect how the caller would actually use your method. If you started from the method definition you would probably come up with

def hit target, place, object
...
end

This makes much more sense from the implementers point of view, but our call becomes

dave.hit nail, :head, hammer

which is slightly less readable from the point of view of someone examining the call in six months time. And those tiny annoyances add up without the reader realising it, till they are tired, the last few lines of code didn’t really sink in and they think fondly back to that other chunk of code that was a joy to read. “Why can’t all code read like that?” they think.

Well, it takes a switch of perspective – one that test-driven development encourages and most other “methodologies” don’t even acknowledge.

unless versus if !

Thursday, August 16th, 2007

Why should you use unless when it is little more than if !?

Because unless let’s you write code like this:


dave.punch george unless george.is_hard?

Isn’t that what code should look like!