I spent an hour or so this afternoon refactoring some code deep inside reek. I wanted to simplify the code that checks for the Uncommunicative Name smell, but it just wouldn’t fall out as clean as I would like. And at some points it seemed that I was going around in circles — a name is represented as a Symbol here, needs to be a String there, but when I add a call to
to_s something else seems to need it back as a Symbol again. It’s the old feeling of squeezing water in a balloon: squeeze in any one place and the problem seems to pop up somewhere else. I put the problem down to tiredness and took a break — actually I took a drive in falling snow, which is not necessarily a cure for tiredness!
But the change of scene cleared my thoughts, and I realised what was going on: The troublesome names were a case of the Primitive Obsession smell. Several classes throughout reek “know” when a name travels around as a Symbol and when it travels around as a String. I needed a new class, Name, to hide the details of the actual representation. I added it (following the recipe in the ruby refactoring workbook, you’ll be glad to hear), and all was well. The new class even acquired some behaviour along the way, so all is well.
So, nothing new there; why am I even writing this at all? Because I asked myself why it had happened — why had such a huge case of Primitive Obsession escaped my attention for so many weeks, and why didn’t I pick it up this afternoon when it hit me repeatedly between the eyes (can a smell do that)? Is this another manifestation of my anosmia? Am I smell-blind to Primitive Obsession? I don’t think so.
Every day in my coaching practice I see code riddled with this same smell. I point it out, we have a quick ad-hoc training session and a couple of lunchtime dojos. I can spot this problem easily. The difference is that the teams I work with all use C# or Java or C++, where the types are stated clearly in the method signatures. But in Ruby that’s not the case: when you read a method in Ruby code, you have to infer the types of the actual arguments by looking at how they are used. Parameter names don’t always help here either (in the reek source code above, sometimes the names were called ‘sym’, other times ‘name’).
So I contend that dynamic typing makes Primitive Obsession harder to diagnose. Do you find that too? Does this smell linger longer in Ruby code than in Java code, for example?
And if my contention is true, what new diagnostic tools do we need? If we don’t have statically typed method signatures slapping us with the wet fish of
string, are there any simple alternative cues we can look for?