I recently had to revisit code that I'd last worked on several years ago. The app involves the building up and editing of data items, using a pretty graphical user interface. My job was to implement the sorting of these items into ascending or descending order, according to the values of various properties they might have.
It doesn't take much technical expertise to realise that the sorting operation can be achieved by moving items around. In fact, it's hard to think of any other way to do it. And since the app already allowed items to be moved from here to there, all I had to do was work out a sequence of moves sufficient to implement a given sorting. Elementary stuff!
So I duly implemented my custom QuickSort algorithm in its own special class, added as much wiring as needed to provide for the various user-available options, and vigorously refactored everything until no more methods could be shaken out, even using the new improved method shakeout vigour in the stripey packet.
The result was first tested, then repeatedly rewritten using my Patent Genetic Algorithm (change something random; determine whether the result is an improvement; rinse & repeat) until it worked perfectly with any data I could throw at it, including all the corner cases.
Finally, all that remained was to connect to the existing "move" logic in the app. There was just one point of interface, where my class wanted to move an item so that it ended up next door to another item. As mentioned earlier, this required method already existed in the app, so I hooked it up, committed my masterpiece and said "Test That."
You're way ahead of me, aren't you?
It's not exactly that the results were random. No, they were perfectly repeatable for any set of input data, and perfectly nonsensical. Sequentially repeated sort operations would seem to edge the results closer and closer to the correct order, like a shuffling row of housemates trying to rank themselves in order of niceness, but always giving up before ever getting it right. Clearly Halfwit was in the kitchen.
What The Feck?!
Turns out it's all in a name. The existing method which I linked into, the one that moved item so that it ended up next to another item, had a parameter labelled "AsNextSibling". Now, I had no problem with the "Sibling" part of that name; each sortable set of items had a common parent, so the items were all children of that parent, and therefore siblings of each other. No, the problem was with the "Next".
Gentle reader, imagine that I showed you a list of items including one called A, then handed you a new item B, asking you to place it in the list, next to A, "as next sibling". Where exactly would you place it? Your two options are:
- add it after item A, as its next sibling;
- push item A out to the right, then insert item B into the just vacated slot where A used to be, so that your new item becomes the previous sibling of A.
It's easy to say, whenever there's any ambiguity about the name of a class, method, parameter or variable, more thought need to be invested in the readability of your code. As a very last resort, you should at least document the correct usage in such cases, but do so knowing that your comments will inevitably be blissfully ignored. Always try to eliminate rather than just mitigate the issues.
This was vividly borne out to me recently when another colleague asked why his usage of my code appeared to be causing so many problems. My reply involved just pointing at his screen, where once in the long ago, I had been reduced to the desperate measure of providing quite rare (for me), but full and detailed commentary. I guess he mistook my wise and precious counsel for the kind of commented-out, obsoleted material that he encounters every day! Truly, hell is other people's code...
Yet in the case above, I saw no scope for ambiguity, and still have trouble squinting enough to see it. My interpretation was obviously the correct one, dammit.
Nothing deserves more care and attention than assigning the best possible names to each entity in your design. No, not even getting the functionality right; that's far less important. You will always make mistakes anyway. At least if the intention is clear, the next guy - who will often be you, some years later! - should have a good chance of fixing them.
Is it just me, or does anyone else around here think that this particular problem affects English speakers, with their jammed-up adjectival phrases, more than say the French, with their liberally dispensed prepositions? N'est-ce pas?