View Rahoul Baruah's profile on LinkedIn Basecamp project management and collaboration

The blog of Rahoul Baruah from 3hv Ltd

What's going on?

My name is Rahoul Baruah (aka Baz) and I'm a software developer in Leeds (England).

This is a log of things I've discovered while writing software in Ruby on Rails. In other words, geek stuff.

However, I've decided to put this blog on ice - I would ask you to check out my business blog here (or subscribe here).

03 February, 2008

Microhoo!

I stopped reading FSJ a while back but he certainly has the best analysis of the proposed Microhoo! deal I've seen so far. It's also worth noting that nothing has actually happened yet.

Via Imran Ali on Twitter.

30 January, 2008

Dominic

Dominic "The Hodge" Hodgson is doing an SEO experiment - aiming at 26 in Google. So this post is for him.

Why hashes as named parameters in Ruby are a good thing

Back when I used to do lots of Sql Server Transact-SQL, I used to dislike named parameters. They annoyed me and I only used them when I had a stored procedure with a large number of parameters, some of which were optional. (As an aside, we had procs with parameter lists running into twenty or thiry, some of which were optional and some were mandatory - it was a nightmare and named parameters were essential in those cases).

Odd though. Named parameters turn out to be one of my favourite Ruby features - even though Ruby doesn't have them. And, even odder, they used to be one of my favourite Smalltalk features (Smalltalk has always had them).

Today, my learned colleague was on a roll. Fantastic design ideas were flowing. One issue he was busy solving was handling an image at multiple sizes. The application had an ActiveRecord class representing a file - and if the file were an image then it could store that image at multiple resolutions. He proposed something along the lines of this: my_file.required_size(width, height) - the implementation would then hunt through the related images at various sizes, pick out the correct one and return it. This meant that a view would have code looking something like this:

image_tag my_image.required_size(400, 300).web_url, :alt => h(my_image.description).

His proposed implementation was fine - but I suggested renaming the method at - so you could write my_file.at 400, :by => 300.

"But at doesn't explain the method's purpose" was the reply. "That's why you should name the second parameter and pass it as a hash" said I. This would make your view code look like this:

image_tag my_image.at(400, :by => 300).web_url, :alt => h(my_image.description)

Personally, I think this is much easier to read and, with the named parameters, explains the intention of the at method perfectly (although the brackets spoil it a bit).

The key difference between the two languages is that in Ruby, the method is named "at" and you call it as my_file.at 400, :by => 400. In Smalltalk, methods names include the parameters - so it is named "at: aWidth by: aHeight" (and you would call the method by writing myFile at: 400 by: 300.).

The Smalltalk idiom of including the parameter names within the method name is much clearer at explaining the method's intention. And the very act of naming your parameters means you can apply much more meaningful sentences within your code - which is exactly what Alan Kay meant for us to do all those years ago. Don't you agree?

28 January, 2008

Brightbox at NWRUG

Jeremy and John will be speaking at the North West Ruby User Group tomorrow (Tuesday) about the business and technical challenges of setting up a UK Rails-specific hosting company.

23 January, 2008

Moving changes from one subversion repository to another

I'm sure this is old hat to you svn experts but I've just figured it out.

If you need to transfer a load of changes from one subversion repository to another (or you have an external developer helping you out on your open source project who has submitted a patch) this is what you need to do:

Generate a Patch File



Move to your "source" working copy and run:

svn diff -r REV > my_patch.txt

This finds all changes since revision number REV and places them in my_patch.txt.

Apply a Patch File



Move to your "target" working copy and run:

patch -p0 < my_patch.txt

This applies all the changes in my_patch.txt to your target working copy. Running svn status then shows all the files that have changed - you can then review the changes before an svn commit (of course crediting your developer in the comments).

17 January, 2008

A (late) review of the year

It's been a pretty monumental year for me - quitting the day job and doing this Rails business full-time. Plus, I've actually been blogging about it. So, a bit late, here are my favourite posts from last year.

unless versus if ! (absolutely the greatest piece of example code there is)
Great Features you see, Great Features you don't
markup.become(:beautiful)
Death to Professionalism
Dealing with Disaster (Dreamhost take note)
form_test_helper and AJAX (Update)
Ruby on Rails is the MacOS to Java/.Net's Windows
The infamous iPhone SDK
Testing for Unix commands on the path in Ruby
Safari, So Good, So What! (just for the title, Megadeth fans)
Default Values in your Models (one of the most searched for posts on the blog)

Geeeeeeeek Uuuuuuuup

Another Wednesday in the middle of the month, another Geekup meeting in Leeds.

I had a great time chatting with the Brightbox boys and taking photos of the Northcrew, in preparation for the launch of their two new sites - Northcast and Northpack.

Thanks, as ever, to Deb and Rob for organising it. And the next one has Christian Heilmann talking about Javascript.

07 January, 2008

10 Rules of Thumb to radically improve your Ruby on Rails code


Ruby on Rails has generated a lot of hype over the last couple of years.

This is a good thing - Rails is well-supported and well-understood.

But it's also a bad thing.

Lots of people read the "Agile Web Development" book and then charge a fortune to develop RoR applications. Badly.

I have seen some shocking projects, chock full of the type of spaghetti code that the Rails hype claims you cannot produce (of course this is nonsense - you can write shite in any language).

Over the years I have developed a whole number of "rules of thumb" that I use to evaluate a project's code. These are subjective, inaccurate and open to interpretation. But taken as a whole they give you a pretty decent idea of the state of the code.

And here they are:

rake stats

Look at the ratio of code to tests.

  • More code than tests? Lose 10 points
  • Between 1:1 and 1:1.5? No points
  • Above 1:1.5? Gain 5 points
This test is pretty arbitrary. Just because you have lots of test code doesn't mean that the tests are any good. But not having lots of tests is bad.

Dependencies

Is Rails and any required plugins installed into the vendor folder?
  • No? Lose 10 points
  • Yes? No points
It's incredibly easy to include the correct version of Rails and all your dependencies within your application tree. Making it easier to share your code with the rest of your team and taking uncertainty out of deployment.

rcov

Is rcov pre-installed?
  • Yes? Gain 5 points
rcov is easy to install and pretty useful.

What is the test coverage?
  • rcov won't work? Why not? Lose 10 points
  • More than 10% red? Lose 20 points
  • Less than 10% red? Lose 10 points
  • All green? Gain 10 points
This test is also pretty arbitrary. A green line, as above, doesn't mean that the test is any good. But a red line is always bad.

Migrations

Can the database be built completely from migrations?
  • Yes? Gain 10 points
  • No? Why not? Lose 10 points
Databases are key to Rails development and migrations make them easy to share with your team and deploy to your server.

Logic in all the right places?

Is there any application logic in the controllers?
  • Yes? Lose 10 points
  • No? Gain 10 points
Controllers are part of the user-interface, function specific and relatively difficult to reuse. Application logic belongs in the models where it can be accessed via the console, not just the web-server.

Is there any application logic in the views?
  • Yes? Lose 10 points
  • No? Gain 5 points
Views are strictly user interface components - they should be primed by the controller so that the view has nearly all of its decisions made for it.

Warnings and Deprecations

Are there any deprecation notices when running the tests or application?
  • Yes? Lose 5 points
Deprecation warnings mean that your code will probably stop working when you upgrade your version of Rails.

Are there any warnings when running the tests or application?
  • Yes? Lose 20 points
Warnings are there for a reason. Pay attention to them - in most cases, it is purely laziness that keeps them there.

RDoc

Do all the models have RDoc comments - a header describing the class and comments for each method?
  • Header comments? Gain 10 points
  • All method comments? Gain 10 points
  • Some method comments? Gain 5 points
  • No? Lose 10 points
Do all the controllers have RDoc header comments describing their purpose?
  • Yes? Gain 5 points
  • No? Lose 5 points
Do all the helper methods have RDoc method comments describing their purpose?
  • Yes? Gain 10 points
  • No? Lose 10 points
Ruby is easy to read and generally pretty easy to understand. That deals with explaining what your code does. But the point of the RDoc comments is to explain why it does it that way, which, arguably, is even more important.

Repeated Code

Is there any repeated code? Are there similar pieces of code in multiple places that could be consolidated into a single parametrised method?
  • Yes? Lose 10 points
When writing code if you find yourself writing something similar to code you have already written then it is always worth moving it into a centralised method or class - either as a helper, a model or even a module.

Readability

How readable is the code? Can you tell, at a glance, what the most complicated pieces of code do?
  • No? Lose 20 points
  • Yes? Gain 20 points
Unfortunately this one is pretty subjective. But, to my mind, code should read like English wherever possible. This may be sub-optimal - especially with regards to performance. It doesn't matter. You can go back, profile the code and optimise the slow bits (of course, your tests make sure that you aren't breaking any functionality). And when you optimise, keep the original (slow) code as a comment to explain what your unreadable (fast) code is doing.

Idioms

Does the code use symbols as hash keys and (the equivalent of) enumerations?
  • Yes? Gain 10 points
  • No? Lose 10 points
Symbols are sort of like strings but are treated specially by the interpreter - sort of like a literal. Carefully used, they can also make your code more readable.

Does the code pass objects to generate links?
  • Yes? Gain 5 points
  • No? Lose 5 points
HTTP is not object-orientated but Rails can at least pretend that it is.

Writing this stuff down is strange. It takes things that often comes to me as a "gut feel" and documents and codifies it. Necessarily this means that there are things that I notice that I haven't written down here. Apologies - I will update the article as and when I think of them.

What use is this check-list?

If you are worried about the state of your Rails project 3hv is planning a service where your code is evaluated against these criteria and you receive a detailed report with recommendations for improvement. Excellent for managers who are worried about progress, even better for developers just starting out on Rails. Details are still being finalised but contact me if you are interested.

30 December, 2007

Coding in English

I've been programming computers, professionally, for over eleven years now (and programming in general for over twenty). In that time, I've tried a number of different programming environments and languages.

Delphi (Object Pascal),
Java (upto 1.4),
Smalltalk,
Ruby,
Python

and

C#,
Visual J++,
VBScript/Visual Basic,
Realbasic

as well as

Ansi C,
C++ (Borland C++ Builder, Visual C++, Ansi C++),
Objective-C (only a little bit),
PHP,
Lisp (at least some variant of it that was designed by someone at my university),
x86 assembler.

The languages and environments I like are in the first group, the ones I dislike in the latter group and the middle group are "almost but not quite". The question is what do they have in common?

Simple: it is easy to make them read and write like English.

Yeah, it's a bit subjective.

You could argue that Java and C# belong in the same group (I'll get to that in a bit). But the last group are quite happy chucking weird syntactic pieces into the mix - it makes my head hurt trying to remember when you need a & and when you need a * in the C languages. I have to say that Ruby, at first, put me off with its @s and @@s.

What about Java and C#? It has to be said that syntactically they are both very clean. But why is Java in the "good" group and C# in the "maybe" group? Because when I met Java it was cleaner than everything except Smalltalk. But when I met C# my frustration with static typing had boiled over. By the same token, Delphi now belongs in the "maybes" whereas, at the time, it was firmly in the "goods".

But, overall, Ruby wins. Code like:


dave.punch george unless george.is_hard?
(I'll never tire of that example).

Or:

using :lame do
encode '/my/audio/file'
end
(a real bit of code that only executes the block if the given the 'lame' command is present within $PATH)

Or:

hit nail, :with => hammer, :on => head, :at => :maximum_force

The latter is a pattern I often follow - using Ruby's hash as a way of building named parameters. This is something I learnt from Smalltalk, which was originally intended to be usable by seven year olds (hit: theNail :on theHead :at #maximumForce.). This makes the method definition look something like:

def hit object, options = {}
using = options[:with] || my_default_implement
where = options[:on] || my_default_area
force = options[:at] || my_default_force
... some code ...
end

The key thing here is that the options keys do not match the actual variable names because they serve different purposes. The options keys are for the users of the method, the variable names for the implementors.

Likewise, Ruby's arrays combined with blocks give you a whole load of power in a very small amount of text.

Given the choice of using Array#inject or writing something more verbose I will always go with the verbose.


collection.inject(0) { | sum, obj | sum += obj.details.size }

versus:

total = 0
collection.each do | item |
total += item.details.size
end
return total


(OK - not the best example). But, to me, the intention of the second version is immediately apparent whereas the first takes a second of squinting to figure out.

I was recently presented with something looking something like this:

sort{|a, b| index.collect{|i| (a[i] || 0) <=> (b[i] || 0))}.compact[0] || 0}

With apologies to the author, I'm still not sure what that does.


Readability is everything. Code spends longer in maintenance than development. And choosing your tools correctly can mean that, with minimal effort, your code can look like English.

29 December, 2007

Nostalgia ain't what it used to be

I gave away my iMac G3 a few weeks back. I wiped all my personal details off the machine and gave it to Freecycle. But in order to wipe my personal details I had to boot it into OS9 - and it has to be said that it's still better than OSX.

A 500Mhz 512Mb G3 is more responsive (not necessarily faster) than my dual 2.3Ghz 2Gb MBP.

The consistency of the UI, the simple rules (start at the top left and flow to bottom right - which is why the Apple menu and trash can are where they are) and the fact that you had acres of screen space at 1024 resolution.

I miss both the machine and the OS. Sometimes progress isn't all it's made out to be.

21 December, 2007

Test Driven Development

TDD is quite easy. Write the tests first, make them pass, refactor. So why aren't you doing it?

Shameless self-promotion

Some people have recommended me, so the 3hv site has been updated accordingly.

20 December, 2007

Geeking up

Thanks to Deb and Rob for another Geekup. Weird beers, an iPhone and geektalk.

17 December, 2007

8 steps for fixing other people's code

How to submit patches to other people's projects.

And, of course:

If the project has a suite of test cases, please make an effort to add “failing test cases”. That is, add test cases that demonstrate the defect by failing

15 December, 2007

13 December, 2007

UK based Ruby on Rails Hosting

If you're looking for a host for your Rails application I can recommend Brightbox.

They offer Virtual Private Servers that are geared up for Ruby on Rails deployments (even down to supplying a gem to help you get started).

They're nice guys, they know their stuff and they're based in the UK. So what are you waiting for?

Disclosure: I have worked with them on their CMS and order processing system.

Forking Hell

As of today I am now forking this blog.

All your Ruby and Rails based goodness will still be found here but everything business related will be found at my company's blog. Go on, subscribe to both of them.

11 December, 2007

When Enterprise software will finally get respect

Blackfriars Marketing commenting on Bill Gates' claim that Enterprise Software gets little respect (via the Wall Street Journal).

As someone who has worked on 'business' and 'enterprise' software for most of my career (the difference being one of scale as far as I can see) I wholeheartedly agree. I got sick of being told that the user-interface was 'good enough'. Half a second of frustration quickly adds up if you are sat in front of an application for eight or more hours a day(*).

especially when we confront real systems at work that increase workloads, enforce meaningless restrictions that don't help customers, and sport user interfaces that feel Kafka-esque in their user hostility. It's not surprising that enterprise software gets no respect; it is surprising that there aren't more cases of employees throwing their computers out windows in frustration.


(*) Incidentally, that always used to be my response when people said that Windows had achieved parity with the Mac user experience. Give two experienced users a tight deadline, one on a Mac, the other on Windows, and see who swears the most. Frustration => Unhappiness => Staff Turnover (for the buyer) and No Repeat Sales (for the vendor)

10 December, 2007

Weird behaviour involving controllers, modules, namespaces and functional tests

Weird one here.

I was working on some code that had controllers within a namespace (Admin::ThingyController). The controller descended from an Admin::BaseController. And Admin::BaseController included a module (include GenericStuff), which in turn was defined within the Admin namespace.

So far, so good.

The code-base was actually somebody elses and the time came for me to add a new controller into the Admin namespace. So away I went: ruby script/generate controller admin/another_controller, editing the file so that Admin::AnotherController descends from Admin::BaseController.

Then, as I do, I filled out my functional tests, made them pass (ruby test/functional/admin/another_controller_test.rb) and then built up some (reasonably) nice views and examined them in my browser.

All good. The views worked, the tests passed, the controller did what it was supposed to.

One final check before committing to svn - rake. Bugger. A whole load of failures. What have I broken? Eh? It's AnotherController that is failing. Check it in the browser. All good. Check the test individually. Row of dots. Try rake test:functionals. Blam!

To cut a long story short (actually the story is pretty short, it was the investigation that was long) the cause was the included module in the BaseController. What is particularly weird is that it was only AnotherController that had the failures, even though all the controllers within the admin namespace were defined the same way. Adding the new controller had upset the rake loader somehow.

And the fix? Change the include in BaseController from include GenericStuff to include Admin::GenericStuff (even though the admin prefix is not necessary as both GenericStuff and BaseController are within the same namespace). Now they all work - tests, rake and in the browser.

04 December, 2007

How everyday tasks sell iPhones

How everyday tasks sell iPhones

I now have run into two people at my church who have decided to get iPhones after seeing how easy it is for me to use mine for seemingly ordinary tasks. Both people already own either a Palm PDA or a Blackberry, but don't use most of the functions because they are just too hard to master. They see me do a quick weather lookup or Google search with a couple touches, and you can see the light bulb go on over their heads saying, "That's so easy; I'd love it if my phone were that easy."

eXTReMe Tracker