A few months ago I read a blog post where someone discussed familiarity and automobiles. I can’t remember if the specific post was about software design or not, but I do remember the crux of the message: users don’t have to relearn how to drive a car each time they get into a new automobile. Each car has the same basic set of features: a steering wheel, a throttle, an engine, some mirrors and a shifter. These controls are basically in the same spot in every car. All the user has to do is familiarize themselves with the minor differences from model to model, but the overall contraption is the same.

I think we, as software developers, ought to heed this sort of design principle more frequently when it comes to API’s.

For instance, take today. Myself and two colleagues spent some time this afternoon trying to configure an Infragistics UltraWinGrid to display data a particular way. We have a love/hate relationship with Infragistics. Their controls are spectacular in the sheer amount of properties that can be set and the methods they expose; they are highly configurable. They’re power is awesome and monolithic. Unfortunately, by contrast, their documentation is scant and good examples are difficult to find. This puts a huge burden on the developer; you must be able to inspect the API and glean important information from it. And it would help the developer greatly if the API resembled the API of similar objects (like the .Net DataGridView, for instance).

A specific example: We were immediately impressed when we first bound a business object collection to the Infragistics grid. Our business objects inherit from base classes that have code for databinding and propertynotification, so that they can track things like dirty and new states, and handle databinding to grids automatically (very similar to what Rocky did with CSLA.Net). The particular collection we were dealing with consisted of business objects that contained a sub collection of objects, so a nested graph. To our great surprise and thrill the Infragistics grid displayed the collection and the nested collections automatically without any additional tweaks by us, with the proper level of “bands”. So much GUI goodness for so little effort.

But our business objects also have fields we didn’t want to display. There are properties like IsDirty and ConcurrencyTimestamp that the user just doesn’t need to know about and wouldn’t know what to do with.

Now, in a normal .Net DataGridView it’s really easy to prevent all the columns from showing by default. You simply set the DataGridView’s AutoGenerateColumns property to false and bind your data. The only columns that display after that point are ones that you explicitly define when you declare the schema for the grid.

You might think that the UltraWinGrid from Infragistics also handles things this way, but you would be wrong.

After an hour or so of fiddling around, manually duplicating the object schema and hiding columns, we finally fell upon the SetDataBinding method, which can prevent the columns from being automatically generated if you set the third parameter to false when you call it (as opposed to simply setting the DataSource property, like normal).

That sounds intuitive, doesn’t it?

Which brings me back to the point about the automobile. API’s are things that developers become familiar with over time, like a car. We become as familiar with API’s as we do with general language constructs (foreach…) or design patters. We don’t have to relearn the Subject/Observer pattern every time we want to wire up an event. We don’t have to relearn enumeration every time we want to iterate over data.

Some of us have been writing .Net code for a few years now, and we’ve gone through all the Google searching to figure out how to configure controls to do our bidding. We don’t want to have to do that again. Or at least we don’t want to have to do it with the same regularity as we did when we were first learning the framework and API’s.

Third party tools, controls and frameworks, whether they’re open source or not, are there to make our jobs easier. To keep us from having to reinvent the wheel every time we need to do something productive. But an API that doesn’t at least try to follow existing, established “standards” (for lack of a better term) only slow down our productivity, because we have to research the proper way to do things all over again. It’s worse when your API doesn’t reveal the most obvious and natural ways to do things through simple inspection.

I know API design isn’t easy. And I’m certain that in my own code I’ve bucked a trend here and there that caused someone else to break out the Advil while they beat their head against a wall trying to figure out how to use my code. But that doesn’t mean we can’t get better at this stuff. Take some time to look at your code and ask this question: “A year from now, if a junior developer on my team is using this API while I’m on vacation and I’m not there to answer questions, will they be able to use it productively? Or are they going to get stuck because I didn’t follow an established pattern/principal/naming convention?”

I don’t know about you, but I’d like to be sitting on a beach without a care in the world, and that includes wondering if people are going to get stuck using my code.

One Comment

  1. Yuu says:

    Chris: I found an alternative solution to this problem, is not very nice but it works.
    http://news.infragistics.com/forums/p/4171/20708.aspx#20708
    I´m agree in your comments.
    Tanks for the post.