Richard Hart

Head of Something @ Somewhere
Kent, UK

My Music
My Photos

LinkedIn
Mastodon

The Code Shall Set You Free

I was recently asked why I don’t comment my code. It’s a fair enough question. There was a time when commenting your code was the done thing. I was once a great believer in commenting code as much as possible and would bash those that didn’t, but now I vary rarely comment my code at all. In my current project of over 1,500 LOC, there are only a handful of comments. Many people will argue this is irresponsible. Well how is anyone supposed to pick up and understand my code, if it’s not commented?

The code should comment itself.

That just sounds silly. It’s like saying a car should drive itself. But it can be done. A lot of this change of heart about comments has come from my commitment to becoming a better developer and spending countless hours reading about the practice of great development, which is something I’ve written about in the past. I’m a big believer that most of the time if you need to comment a piece of code, then it’s either bad code or too complicated. Of course that’s not true 100% of the time, but for the other 99% it really is. There are cases where things need to be explained and especially warned of, but a lot of the time, commenting is just an easy escape from having to do “proper” coding. It took me years and years to get a basic understanding of proper OO and I’ve still got a long way to go to reaching Journeyman levels of understanding, but I would always create large objects with huge and complex methods, when really what I needed were more concise classes with more responsibility for what they should be able to do. It’s not object orientated when you’re focus is on the method and not the class.

A simple example of commented code:

  # Feed the fish.
  def check_food(food)
     # Check if Fish has eaten more then 5 hours ago.
     if self.last_meal_time < 5.hours.ago
       return "Not hungry"
     # Check if the Fish eats this food.
     elsif !self.edible_foods.contains?(food)
       return "Can't eat that!"
     # Make sure the fish isn't being underfed.
     elsif food.amount <  fish_feeding_amount(self.type)
       return "Not enough food."
     # Make sure the fish isn't being over fed.
     elsif food.amount > fish_feeding_amount(self.type)
       return "Too much food."
     end
     # Eat food.
     self.eat(food)
  end

Most comments can be done away with. If we split out functionality into more concise bits, then just reading the code should explain what’s happening better:

  def feed(food)
    return "Not Hungry" if self.recently_eaten?
    return "Can't eat that!" if self.does_not_eat?(food)     
    return "Not Enough food" if self.not_enough_food?(food)
    return "Too much food" if !self.too_much_food?(food)
    self.eat(food)
  end

This isn’t a great example as once again the validation of whether the food can/will be eaten should move into it’s own method or class ever. If we’re follow Uncle Bob’s SOLID principles, the above examples breaks the OCP (Open Closed Principle) where entities should be open to extension and closed to modification. If more validation rules were needed, then that would require the code to be modified.