Skip navigation

Monthly Archives: March 2008

One of the biggest problems of the concept of null in modern programming languages is the choice API designers have to make between returning null or a conceptually empty object, for example string.Empty or new List<Type>();

On one hand, null is the obvious choice because it prevents wasting resources.  Creating an empty list each time a call returns no results is wasteful.  This can be averted by creating a static empty singleton (like string.Empty), but unless the object is immutable (as string is, or returning a ReadOnlyCollection) you can run into trouble here since the caller can modify the result.  Even this is wasteful when what you’re really trying to say is: “hey, I have no results to return.”  That’s what null means, isn’t it?

On the other hand, for the consumer of an API, even when the API author and the consumer is the same person, it’s hard to guess whether a method will return null or an empty object.  Even the .NET API authors struggle with this fact as evidenced by the string.IsNullOrEmpty static method, which is great for argument and return checking.  Since it’s hard to guess, most good programmers are in the habit of always checking for null first even when they know that the method will never return null because they wrote it.

The reason good programmers check for null religiously is because things change.  You may not be returning null today (in favor of an empty list) but tomorrow you may change your mind.  The problem with an API designer changing his mind is that he can’t predict whether or not the consumers of his API are properly checking for null.  As I said, good programmers will.  But what about the bad ones?

In my opinion, you should generally always return null instead of an empty object except with strings.  The reason for this is that it forces even the average programmer to check for null immediately.  A simple negative unit test will result in a a NullReferenceException.  There is no harm in returning null in version 1.0 and then changing it to return an empty object in version 2.0 but the reverse is deadly, because it has the potential of breaking all your consumers.  Checking for null is benign.  Making the assumption that the result of a method will never be null is an exception waiting to be thrown.

The exception to this rule for strings is because of the string.IsNullOrEmpty method.  Good programmers should rarely check strings of being null or empty independently.  Good APIs do not distinguish between the two in the majority of cases.  In some cases, null is different than empty – for example, in a login form, an empty string means an empty password, but a null password may imply an error occurred somewhere (or may imply integrated security, for which a password is unnecessary).  But generally, this distinction should be obvious from the context.

I would have expected an enterprise technology to be smarter than this.

 Want Team Foundation Server for free?  Install it and roll back your computer’s date 10 years.

 If you can tolerate your histories saying “1998” when it actually means “2008” then you have it for free.

 The idiot in charge of installing TFS at our location installed a trial and let it expire.  Since this precludes us from doing anything as basic as a task query or access our team portal, our entire development shop is offline… until I rolled the server’s clock back 1 week.

 You know, they say locks keep honest men honest, but having been involved in implementing concurrent user server-based licensing for our own product, I can tell you that the “rolling back the clock” is not even remotely hard to detect.  All you have to do is encrypt and hide a registry key (the COM registry is a wonderful place to stick something like this) that names the date you installed it, and also encrypt the date of the last login.  If the current machine date is earlier than either of these values, reject.

Anyways… in our situation we can’t really do this because we’d really corrupt our histories and it’s not worth the risk that TFS will go haywire if we have pre-dated checkins, but if we had known this from the start we could have pulled the 10 year trick.  Oh well.