20080523

How to Load Nothing

I ran into a problem with loading the other day that I felt was a shortcoming of the design. I found a situation where I needed to load from the data file the fact that a particular property of something is empty or nil. Really, this can happen whenever a property is optional.

In this particular case, the optional property was the short description of a character. Although Nipics tend to have short descriptions all the time, since there's no other real way to refer to them--having no name, and all--characters are usually referenced by their name in lieu of a short description.

None of that really matters. What matters is there was an optional property, and a shortcoming of the way loading was designed made me have to go through contortions in other places to support it. I decided, finally, to fix the design, because contortions don't scale well.

As you may recall from previous posts, there is some intermediate state during which an object is being loaded from the data file. During this time, the object is semi-initialized, and the process of loading keeps track of what parts have been initialized and which parts have not yet. Usually, those parts can't yet be initialized because they're waiting on some data on which they are dependent.

The problem with the design--and any CS people reading this will immediately agree--is that the unloaded state of a property of some object was represented by the nil value. What this effectively meant is that the nil value itself could never be loaded from a data file; every piece of data needed to be some real, concrete object, be it an empty string or some other kind of placeholder.

The way I fixed this is by instead using some arbitrary value to represent the not-yet-loaded state. As an implementation detail, I decided to use a Symbol, probably because it's very unlikely that I'll ever have a symbol being loaded from a data file. Consequently, I updated every single place where I made the assumption (implicitly, sometimes!) that nil represents a not-loaded value, and replaced the check or value or whatever with this symbol.

This was really quite painful, due mainly to the parenthetical above: there were many implicit assumptions, and most of them were hard to nail down. Aside from now supporting optional properties very easily, the upside of this change is that now there's no way for me to make that kind of assumption implicitly anymore. If I'm expecting or handling a not-loaded state, it jumps out into my face. In a way, it's a step towards making wrong code look obviously wrong. Perhaps more importantly, it's purged this automatic link in my brain between nil and not-loaded.

0 comments:

Post a Comment