First off, this question goes beyond my example (don't want this to be too localized or migrated to Stack Overflow) but I've come across this when thinking about something I wanted to try in C so I thought I'd use that as an example.

So my idea is to create a generic linked list in C and started it last night and it is coming along pretty well for being new in C. The issue I ran into is type casting and it leads me to this question: how much work should a library designer expect the end user to do when using the library?

If you take my example, right now, I don't perform any casts and return an Object (which is a typedef of void*). Is it reasonable to make sure that the end user keeps track of their types or should the library designer make sure that the list is type safe (I think I have a general idea on how to implement that for at least the built in data types)? Is it reasonable, when designing a library to expect a certain amount of work on the end users part to use the library or should it be dumbed down as much as possible? Are there factors that would affect this decision, such as language?

6 Answers
6

When you write the "end user", I assume you mean the "developer of the calling code".

The TDD methodology makes you write the tests first, then the code.

Among others, a huge benefit is that your API is designed to be usable (because the test code is calling your code, just as a regular caller of your API). The calling code becomes simple, and very readable. That should answer any questions you have about the exact API you should offer.

Please also note that an API often allow changing language level. For example, a functional code about farm cows and pigs, can use an API for disguising them, before they can play ninja turtles ;-) Or grouping clients
can use the List data structure, and don't even consider the technical details.

I think it depends based on the library you're building. If you're building a library with implementations of Abstract Data Types as in your example I wouldn't want to do anything myself. I would expect something which is completely finished and supports a typesafe way of adding/removing/selecting/iterating.

The reason for this is that it's a domain of which anyone can have a very complete understanding. I would expect anyone who builds a library and expect me to use it to be an expert in the domain he's building the library for (if he's not I can just as well build it myself). For me typesafety in datastructures is an absolute requirement.

If you have a problem domain which is much more flexible (or which is not yet that cultivated) I would expect a library to leave more room for adjustments by consuming code as multiple implementations might be possible. But as I've stated before, the developer has to be a real expert in the domain so he'll probably know where to make his library extensible (as this is a key part of knowing a domain well).

And in any case, spend a lot of time on your public interface as this will be the primary thing your 'users' will see when consuming your library. If they have to check the documentation for every single function they want to use, because the can't tell by the signature what it will do, the benefits are minimized

Your library should be considered to be a black box. The user of the library should not have to have any prior knowledge going into the process. They should be able simply to call the methods in the library with the following understanding:

Calling method X with parameter Y produces Z
z = x(y);

They should know the type going in as a parameter and they should know the type coming out as a parameter. The user should not be required to have any inside knowledge of your library or how it produces the type, only that the type being produced is what is expected.

First of all, you might not want to reinvent the wheel. GLib has a very useful linked list library in C.

However, if you are intent on rolling your own, GLib and GTK+ are good models for relatively clean APIs. Keep in mind that a few design principles in other languages don't really apply in C due to its limitations. For example, GTK+ requires users to perform typecasts in several places, but they provide macros to make it easy, like the GTK_WINDOW() in:

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

In another language, it would be considered poor practice not to use polymorphism for the window variable. In C, casts like this are par for the course. Likewise for needing to cast a void* return value into something useful. In other languages, best practices would dictate you use something like templates to give you the right return type. In C, that's not available, and most importantly, C programmers don't expect it to be. APIs are all about meeting the users' expectations with the least amount of surprise.

Thanks Karl. I'm just rolling my own for C practice, data structure practice and to see if what I was thinking about (generic linked list) was doable by myself. The original question was something I thought about and was curious as to the answer. Thanks again for providing a C specific answer.
–
JettiAug 17 '11 at 17:39

Who the library is for is definitely a consideration. If the library is for use by other people in your team, then I wouldn't call it unreasonable to expect a little bit of extra work on their part to use it (type casts and such. Perhaps some less leniency on data coming in to functions and the like).

If the library is for public use, I would expect to reduce the amount of work required as much as possible, to reduce the "difficulty" of using it.