Wednesday, May 25, 2005

My Favourite Smells

Hi, I'm Chris, and I've written smelly code. In fact, I still do it. I mean, you can't remove code smells if you don't put them there in the first place.

A recent conversation around continuous design and refactoring towards a good design got me thinking along a tangent- are there smells that I have a hard time escaping? What are the ones that I can't seem to shake, no matter how hard I try?

So I came up with one that I am especially fond of, and that special place in my heart goes to primitive obsession. This is the smell that I use all the time. What is it? Well, it's when you use primitive types, like doubles, strings, ints, to represent ideas that really deserve their own type.

My brain doesn't always detect the need for a new type. Sometimes I am perfectly content to represent something, say, like the concept of Mass, as a double. All over the system, I merrily use my 'Mass is a double' notion, until....

I need a tolerance!?! You never told me I needed a tolerance! Now I need to go around the system and change all my Masses to use a tolerance... ok, done, not so bad... What!? I need to convert my Mass to Energy?!?! Why didn't you tell me?! Ok, why is this not working? Those darn tolerances are messing everything up!

This is a semi-regular occurence, and I personally find two things interesting about primitive obsession.

  • It is easy to live with for a while, sometimes a long while. But it tangles itself into a system nice and tight, and is one of the hardest smells to remove.
  • If avoided, your code is so easy to change and you get some nice side benefits.

Let me give an example of the latter point. I work on a system that has a mixture of one-based indices and zero-based indices (legacy, gotta live with it). As we built the new stuff, we decided everything would be one-based. However, there were all kinds of errors popping up. Anyone who has programmed for more than a week will concur (hopefully, or I'm the only fool who can't add and subtract) that i + 1 and i - 1 all over the place get's really hard to figure out after a while, and your head spins while trying to convert zero-based and one-based indices back and forth. Never mind all the guess work when trying to figure out if a parameter to a method was zero or one based.

Well, I tried something. I made a OneBasedInt and a ZeroBasedInt value type and began using them everywhere. Soon, there were all kind of cool things happening:

  • People suddenly knew the type of index they should pass into a method
  • Things started to fail fast - I could no longer assign zero to a one-based index, and I could tell exactly when I was doing that!
  • No more index + 1 and index - 1 all over the code.

So much for my weakness(es). I see the benefits of avoiding primitive obsession, but continue to get stung by it often. Maybe I will be old and wise one day. For now, I will relish my small victories.


<< Home