Libraries

Writing a library is usually more than writing code, it is writing idiot proof code. And that’s because sooner or later, an idiot will use your code and it might not work. Idiots usually are very creative, mind you – involuntarily.

One old problem is that of returning error codes versus throwing exceptions. We all know the theory, so I won’t repeat it here. I will just reinforce it… I’ve seen a lot of code not checking error codes. Lazy programmers, pressured programmers, idiots, novices, it doesn’t matter. The code will fail in hard to predict ways and you’ll spend days/weeks/months investigating. Solution is simple, throw an exception – it has to be explicitly caught and ignored.

It’s especially important in a library where you don’t know who is going to use your code and sometimes not even how they’re going to use it.

 

A special case of ignoring return values is when the return is a pointer to a memory that you’ve allocated in the library. That shouldn’t happen too often, but some design patterns (e.g. Factory method) explicitly address this problem. If this value is ignored, the memory allocated will leak. Do this many times and your application will become the laughing stock and your reputation in tatters.

The solution: Smart pointers, and there are few flavors. I will only name two here, the auto_ptr which is part of the standard library and the shared_ptr which part of the boost library. They are not equivalent, so choose whichever you want carefully. But at the end of the day, both will do what you want … if the value is ignored, it will be cleaned up properly.

 

The interface of the library is also an interesting part, because whatever you put in the interface (ie classes that you explicitly pass as parameters or return values in the interface methods) becomes an extra coupling between the library and the client app. Basically, because objects of these classes are passed between the client app and the library, the library and the app need to be binary compatible in regards to these classes. For example … if you pass a struct in the interface, when you change the struct, you need to recompile both the library and the app.

One more interesting problem of this type is when you use the STL. Some clients might choose to use the microsoft STL, some clients might choose STLPort, some might even have their own implementation of STL (who?!). That’s guaranteed to fail.

Solution: Use const char* instead of std::string and stay with basic types whenever possible.

 

Documentation can be another serious problem, especially if you don’t ship the source code. Library writers can access the code, so sometimes documentation is not their top priority. But for users, the library is a black box (as it should be) and all they can see is the interface. Solution: Document the interface. Use standard patterns and idioms that people can easily recognize when designing interfaces. Use meaningful names for interface members, arguments, return types, etc.

Advertisements

Tags: ,

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


%d bloggers like this: