Not the wonderful basketball player that amazed people during the 80’s and part of the 90’s (although I have to admit I had another favorite players), but the fact that sometimes it is not immediately obvious what happens in very simple pieces of code thanks to tricks that makes our life difficult sometimes.
I have already ranted about the subject and its principal the culprit, the implicit conversion operator.
The scenario is described as follows: a struct that was going to be the type of a property in an Asp.Net UserControl. The value of the property was going to be set from a string representation of the object in the markup of the page, so I thought the only way to achieve it was to have implicit conversion from string to my type. It happens that the struct implements also IEquatable<T>.
My type was, more or less, like this one:
Nothing fancy, you see, just a facility struct to express some sort of custom dimension.
My small proof-of-concept was working with the user control setting the right value in my type, but when I proceed with unit testing (test-near, not test-first as you see) this test was failing complaining with some reference being null:
What? Of course is null, and looking at my Equals() implementation that is perfectly fine!!!
After scratching my head for some minutes I could not believe that such a small piece of code was giving me a head-scratching time and was making me fire the debugger
But then I remembered that magic happens where you are not looking at, so I looked somewhere else and found that the most probable cause was that my magic code (the converter) was being executed in order to translate null into my object.
Does it make sense? Well, I have to admit that it sort of does. But what annoyed me (apart from the head-scratching) was that it is not at all obvious. And if it not obvious for me, the guy creating it, imagine for the fellow programmer maintaining my solution.
The solution? Simple, make the operator explicit and all tests passed and the control was still setting the right value.
- Unit testing is goodness (once more). Just imagine how difficult would have been this small bug to track if it ever happened in a live system with hundreds or thousands of moving parts that make up a medium-size software solution. Matter of minutes writing tests and head-scratching.
- Test-driven development would not have helped in this case. I just would have hit the problem marginally earlier.
- I won’t be tired of saying: implicit conversion operators are mildly evil at least. You are better off implementing custom methods or explicit converters (if anything).
- Magic is bad: magic strings, magic numbers, … But I guess that asking the question to celebrity illusionists that dated supermodels might yield a different answer ;-)
Enjoy your tricks while they last