adrift in the sea of experience

Monday, May 28, 2007

20 kilometers of Brussels

Like last year, I participated in the 20 kilometers of Brussels yesterday along with some of my coworkers. I had my sights set on finihsing within 1h40m.

Up to the 17th kilometer I was perfectly on schedule for that time. Unfortunately I got recurring cramps in my calf muscles during the last 3 kilometers, which almost halved my speed :( I still finished in 1h46m15s. That's an improvement of 2 minutes over last year, so the result was not a complete disappointement.

Wednesday, May 16, 2007

Don't document that you throw ArgumentException or InvalidOperationException

When programming by contract (which should always be the case, at least implicitly), each method has pre-conditions that the caller should adhere to and post-conditions which the callee guarantees if the pre-conditions were satisfied; if they weren't, all bets are off.

Let's look at an example in the .NET framework: System.XML.XmlReader.ReadElementContentAsString. This method has the precondition that the xml reader should be positioned on an element. However, Microsoft has chosen to actually document this as a postcondition: if the xml reader is not positioned on an xml element, InvalidOperationException is thrown. This is the normal documentation style for the .NET framework, but it has never sat right with me for two reasons.

The first reason is that you shouldn't encourage programmers to rely on avoidable exceptions. I feel it would be better if this was simply documented as a precondition which must never be violated. What happens when the caller violates the contract doesn't need to be documented, so the guarantee of an InvalidOperationException could be omitted. It would of course still be thrown, but as an indication of a programming error. It shouldn't be relied upon.

Another reason is inheritance. One of the great things of programming by contract is that it provides rules for what you can do in an overriding method. Any method must implement the contract of the method it overrides, because the caller may not be aware of the exact type of the callee. However, the overriding method may loosen the pre-conditions. It must merely accept anything that the overridden method would have accepted. It may accept more. Unfortunately, if the preconditions are documented as exceptions, they are now post-conditions which restrict the overriding method without good reason.

Conclusion: don't document ArgumentException and InvalidOperationException if it is sufficient to document pre-conditions.