Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Theres talk about what syntax and feature you like in a programming language; i'll now ask what core principles or feature would you like in a library in your favorite (or any) language?

An example is having adding list += anotherList valid as oppose to only allowing list += listElement (although some may see this as a bad idea)

share|improve this question
5  
Traditional library values, like "shhh" and "no snogging in the stacks". :-) –  Stephen C Nov 8 '10 at 13:51

6 Answers 6

I would follow the best practices you can find in How to design a good API and why it matters by Joshua Blosh (Google). The PDF version can be found here.

According to him, characteristics of a good API are :

Easy to learn
Easy to use, even without documentation
Hard to misuse
Easy to read and maintain code that uses it
Sufficiently powerful to satisfy requirements
Easy to extend
Appropriate to audience

share|improve this answer
    
"Easy to misuse" would be a hacker's (in a broader sense) wish I think. –  mojuba Nov 8 '10 at 17:58
    
@mojuba: I'd rephrase this slightly as "doing the right thing should be easy, doing the wrong thing should be hard", i.e. the lib user is nudged toward using the library the right way. That doesn't prevent the kind of abuse pleaisng a hackers mind. –  peterchen Nov 9 '10 at 12:14

I want the following:

  • A clearly defined name space. Since C is my primary language, I also want macros to match this. Resolving conflicts in that area sucks.

  • If you allocate something, give me some obvious clue that it has to be freed. This goes to my next point, which is documentation.

  • Document the library. Tools like Doxygen are simple and portable, there is no excuse for not giving me something I can generate and browse.

  • Document opaque types in public headers. I'm going to find them anyway, tell me why you don't want me messing with them and what could happen if I do. If you actually want patches, I need to know what you were thinking.

  • Don't drop and run. I really appreciate comments like "Please, don't contact me about this. I have no intention of maintaining it. This solved my immediate problem, maybe it will solve your problem. I don't care, I'm not going to update this and you can feel free to fork it." I can't tell you how much time that saves me.

  • It should add no memory leaks or errors to existing code. If you don't test prior to pushing stuff to your own code, why are you tempting me to push it to mine?

  • If it is indeed a library, use a permissive license and be consistent. Don't decide three months from now that you should be making more money from it. That is beyond annoying the night before you ship something and realize that you have to re-write a bunch of library code because the license changed. That is exactly the kind of thing that makes me irritated enough to re-implement your stuff under the MIT license.

  • Be consistent in coding style, other people have to read your code in order to figure out what it is actually doing when things don't work as expected.

  • Don't use more than 110 columns, your code may have to be edited in place, and I might only have an 80x25 display. If you rely on tabs to make things look more 'elegant', you have other issues to solve.

  • Try to at least consider ports, if not dealing with an interpreted language. Even then, try to at least consider ports.

  • Give me tests. I hope you have them, I might suggest them otherwise and I may actually help write them based on a call graph. If I go through all of that trouble, kindly, use them. Otherwise, you get patches that "work for me!!!" :)

  • Don't break the API, period. I know you may realize that you've gone about it all wrong, but make sure stuff that links to you won't break on a simple update. That may mean some cruft and kludges, welcome to the world of libraries.

  • Give me a roadmap so I don't duplicate your work, or the work of others.

I'll likely edit this post to add more.

share|improve this answer
    
A pet peeve for me in C is cumbersome string returning conventions. For example, using getcwd properly requires making a loop that expands the buffer until it's big enough (see example). –  Joey Adams Aug 2 '11 at 4:18

I'm more concerned about the soft features of an API. That is:

  • Simplicity
  • Consistency
  • Elegance
  • Intuitive
  • It just works

I could right a book on how those apply or would get implemented, but suffice to say unless a user of the API can wrap their head around how to use it effectively, it's of limited use. Simplicity does not mean simplisticness, just as elegance does not mean onate. It simply means that it is just perfect for the job. The less someone has to think about how to use the API, the more they can just use it.

How these look depend on the lnaguage, purpose and target audience of the API. The very last criteria boils down to the principle of least surprise. No errors where you didn't expect them. Any reasonable interpretation of the API will get you the results you want.

share|improve this answer
1  
Technically "it just works" is not a feature of the API but of its implementation ;) –  back2dos Nov 8 '10 at 13:52
    
:) Yet, it seems like that is a differentiator between similar APIs. So I consider it a feature. –  Berin Loritsch Nov 8 '10 at 16:54
    
+1 for consistency. Definitely an underrated value. –  Maxpm Dec 16 '10 at 22:11

Make Simple Things Simple and Complicated Things Possible

This pretty much sums up every other design philosophy. If your library only makes complicated things possible, people looking to solve the easiest 80% of use cases will be tempted to reinvent the wheel rather than deal with your overengineered monstrosity that requires you to use 6 different classes to do your library's equivalent of "Hello World".

If your library only makes simple things simple, people will become annoyed very quickly when they find out that they need to rewrite their code just because they had a requirement that was a little bit off the beaten path.

The best ways to accomplish this are:

  • Be liberal in what you accept. If you're programming in a dynamic language, use duck typing to full effect. If you're programming in C++ or D, use templates wherever possible. Accept anything that satisfies some reasonably universal structural interface. Don't force your users to do a lot of busy work converting data from one format to another.

  • Build high-level convenience functionality into your library, but build it in a transparent way on top of lower level functionality, and make sure the lower level functionality is there for people who need it.

  • Follow the principle of least surprise by default, even when doing so may limit flexibility or efficiency. If necessary, add a second function with a more verbose name that emphasizes its surprisingness to allow for optimizations or increased flexibility.

  • Encapsulation is useful, but don't be anal about it. People with unusual, unanticipated requirements occasionally might need to get underneath one of your abstractions to get the job done. On the other hand, it should be hard to shoot oneself in the foot by accident, when using seemingly innocent constructs. Keep this in mind when deciding how tightly you want to lock stuff down.

  • Use examples heavily in your documentation. This serves both to illustrate common use cases to your user and to force you to think about whether the most common cases are sufficiently streamlined.

  • Have reasonable defaults for everything you can, but make sure those defaults are just defaults and that it's clear how to override them.

share|improve this answer

Good documentation with example code.

share|improve this answer
  • Reasonable, healthy minimalism

That's all. Compare, as an example, the mechanism of pipes on Windows and UNIX. One offers a bunch of specialized API functions with a bunch of obscure, unnecessary or rarely used arguments, each of which can have one of the many macro/constant values. UNIX basically re-uses the existing open/read/write/close interface, plus a few very simple methods for some specific cases, such as socketpair() or pipe(). There is really almost, nearly nothing new you should learn in order to use pipes on UNIX. Now compare to this.

(To be fair, Microsoft originally only "borrowed" that interface from IBM's OS/2.)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.