Better interfaces to your data source

There is a reason why most Java programmers create classes that match the structure of their database tables. To get to that conclusion, let’s talk about a mistake I made when building MapTap.

So, initially MapTap was recording (in terms of data) just the name of the map from an archive. A simple file (should have been a database) listing the bsps would do the trick. But then we wanted to keep track on the date when each map was played and (this might come as a future feature) a rating.

Now, this data is being obtained by the main executable from a DLL. In order not to depend on the changes done for the DLL, we’re loading it with an explicit call of “LoadLibrary”. All nice and dandy.

Now, assuming that the first version of the DLL had this function:

int GetMapsForArchive (char * iszArchiveName, char *** oaszMaps);

and the main exe would do a GetProcAddr to find it in the DLL, and that you have two possible ways to extend the interface:

Method 1:

int GetMapsForArchive (char * iszArchiveName, char *** oaszMaps, char *** oaszPlayedDates, int ** oaRatings);

or Method 2:

struct MTFileData
{
    char * mapName;
    char * playedDate;
    int rating;
};

int GetMapsForArchive (char * iszArchiveName, struct MTFileData **oaFileData);

which one do you think it’s better?

You’re right, it is Method 2. There is one particular reason why the second one is better: less worries when the data obtained changes further.

If you remember what I mentioned earlier, in order to call the function from the DLL, we need to do a GetProcAddress. The function pointer returned by it must then be cast to the type of function we know of. This means that the actual type of function returned must match the signature of our local definition of the function pointer.

If we keep changing the signature of the function, we’ll also need to change the definition of the local function pointers. This is not only tedious, but outright dangerous: if you forget to do it, you end up with crashes.

By using data structures to encapsulate the format of the data, you’re delegating any interface changes from the function you call to the object you get. And that is much safer than having to change function signatures in several places, since you’ll only change the one header that defines that struct.

The Java guys got that right, and their constant use of databases keeps them from forgetting the lesson.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s