Paying my Taxes

This talk about continuous tax is timely for me. I spent several hours earlier this week tracking down a problem with some Ruby Subversion hooks. There were two bugs that contributed to my woes.

This particular comment by Emmanuel Pirsch on Cedric’s blog caught my attention:

There is a “continuous tax” for any system that is being maintained. The fact that the system is build with a statically or dynamically typed language has nothing to do with that.

It all comes down to how well the system is designed and documented. While statically typed language offer a bit more “default” documentation, they do not offer any more insight about the behaviour of an API than a dynamically linked language.

I call bullshit, although the scare quotes are a great tactic that I use often. The “default” documentation offered by explicit type declarations and return statements seems like a Very Good Thing to me, at least they did a few days ago when I was cursing at some Ruby code I could not understand.

The World is Not TRUE/FALSE

Positions like this always seem suspect, because the world I live in is not this clear cut. Consider the finality of his statements:

  • …has nothing to do with that…
  • …It all comes down to…
  • …do not offer any more insight…

When trying to maintain and fix problems in someone else’s code, static typing and a more explicit syntax are often helpful. Allow me to describe the two bugs I tracked down.

First, one of the Ruby methods had a comment indicating it returned an array of strings. This threw me off because in reality the method did not return an array at all. It returned a single string. The comment was wrong, which of course is possible in ANY language:

/**
 * @return an array of error messages if something goes wrong.
 */
public String doSomething() { ... }

Yet as you can see, static typing and explicit compiler-checked syntax are helpful in this case. I can look at the method and immediately know it returns String rather than an array, despite the bogus comment.

I made up the Java code above. I am not making up the Ruby bug I had to diagnose. The bad comment really threw me for a loop. So there you have it. One example where explicit compiler-enforced syntax offers more insight into the code, even when the comment is wrong.

Does Not Offer “Any” More Insight?

The second bug took me far longer to understand and was more insidious. In Ruby you don’t even have to say “return” at the end of a method. Instead, the result of whatever expression happened last is automatically returned. Invisible magic is the quintessential example of a feature that saves the original coder a few extra keystrokes but makes every downstream programmer pay the continuous tax for years to come.

I made the problem worse by adding a simple “if” statement to the end of the method, thinking I could explicitly change a bogus error message to nil. But now the method didn’t even return a string any more…I inadvertently changed the return type from a string to a boolean.

The final fix? I added an explicit return statement to the end of the method. I’m sure I’ll eventually write more Ruby code, and when I do, I’ll probably adopt a convention of using explicit return statements whenever possible. But since this is not enforced by the language, I’m sure I will eventually have to maintain something that relies on this magic.

Duck!

Bring on the flames. Seriously, I’m not making any profound statement about Java versus Ruby here. It just seems silly to take such hardened TRUE/FALSE positions on every issue.

Static typing and explicit return statements have SOMETHING to do with my ability to gain insight into code.


6 Responses to “Paying my Taxes”

Glen Says:

I’m not exactly sure what a continuous tax is supposed to be honest. Clearly there are trade-off’s in both directions when you choose between static and dynamically typed languages. It will most likely be one of those areas where developers will be arguing about for many years to come.

I’m personally happy developing with either sort of language. My main issues with Java don’t have much to do with the fact it’s statically typed. There are bigger issues that could be argued over.

Mario Aquino Says:

You have a good point about the need for up-to-date documentation for methods in dynamic languages. There’s just “no way” to fix this “problem”. ;-)

Out of curiosity, did whatever code that had the mismatched method comments/return value have test coverage for that method?

On returning the last evaluated statement in a method, I feel like that should be chalked up to learning the way the language works. In my own reading of Ruby code, it is more common for methods to be written without a return statement. As you become more familiar with the language and common idioms, you just get used to that.

Dan Lewis Says:

Good test coverage and language familiarity don’t fix bad documentation. Static typing doesn’t fix it either. However, “static typing” highlights the contradiction between docs and implementation.

Eric Burke Says:

This particular method does not have good test coverage. Many other parts of this very small set of hooks do have good coverage. I just don’t like invisible magic. I think it sucks for maintenance because there is no visible text telling you what is actually returned.

Weiqi Gao Says:

Had you made a similar return-type-altering change in Java, the compiler would have caught it as an error. In that regard, the static typing works just like unit tests—it prevents you from breaking your code.

Leave a Reply