tags:

views:

1660

answers:

14

Background:

I am taking a class at my university called "Software Constraints". In the first lectures we were learning how to build good APIs.

A good example we got of a really bad API function is the socket public static void Select(IList checkRead, IList checkWrite, IList checkError, int microseconds); in C#. The function receives 3 lists of sockets, and destroys them making the user have to clone all the sockets before feeding them into the Select(). It also has a timeout (in microseconds) which is an int, that sets the maximum time the server can wait for a socket. The limits of this is +/-35 minutes (because it is an int).


Questions:

  1. How do you define an API as 'bad'?
  2. How do you define an API as 'good'?


Points to consider:

  • Function names that are hard to remember.
  • Function parameters that are hard to understand.
  • Bad documentation.
  • Everything being so interconnected that if you need to change 1 line of code you will actually need to change hundreds of lines in other places.
  • Functions that destroy their arguments.
  • Bad scalability due to "hidden" complexity.
  • It's required from the user/dev to build wrappers around the API so that it can be used.
+10  A: 
  • Useful - it addresses a need that is not already met (or improves on existing ones)
  • Easy to explain - the basic understanding of what it does should be simple to grasp
  • Follows some object model of some problem domain or real-world. It uses constructs that make sense
  • Correct use of synchronous and asynchronous calls. (don't block for things that take time)
  • Good default behavior - where possible allow extensibility and tweaking, but provide defaults for all that is necessary for simple cases
  • Sample uses and working sample applications. This is probably most important of all.
  • Excellent documentation
  • Eat your own dog food (if applicable)
  • Keep it small or segment it so that it is not one huge polluted space. Keep functionality sets distinct and isolated with few if any dependencies.

There are more, but that is a good start

Tim
+47  A: 

In API design I've always found this keynote very helpfull:
How to Design a Good API and Why it Matters - by Joshua Bloch

Here's an excerpt, I'd recommend reading the whole thing / watching the video.

II. General Principles

  • API Should Do One Thing and Do it Well
  • API Should Be As Small As Possible But No Smaller
  • Implementation Should Not Impact API
  • Minimize Accessibility of Everything
  • Names Matter–API is a Little Language
  • Documentation Matters
  • Document Religiously
  • Consider Performance Consequences of API Design Decisions
  • Effects of API Design Decisions on Performance are Real and Permanent
  • API Must Coexist Peacefully with Platform

III. Class Design

  • Minimize Mutability
  • Subclass Only Where it Makes Sense
  • Design and Document for Inheritance or Else Prohibit it

IV. Method Design

  • Don't Make the Client Do Anything the Module Could Do
  • Don't Violate the Principle of Least Astonishment
  • Fail Fast - Report Errors as Soon as Possible After They Occur
  • Provide Programmatic Access to All Data Available in String Form
  • Overload With Care
  • Use Appropriate Parameter and Return Types
  • Use Consistent Parameter Ordering Across Methods
  • Avoid Long Parameter Lists
  • Avoid Return Values that Demand Exceptional Processing
Tim
+1 This is far more complete and useful than my answer. Worth reading.
Tim
yeah +2 if possible ty :)
fmsf
It would be worth expanding the main points of the slides into the post, if someone is willing to do the work.
Barry Kelly
Thanks for the comments / votes.. Expanded my post to include some information from the slides, as suggested by Barry Kelly
Tim
When I see "Document Religously", I can't help but think of the instructions for using the Holy Hand-grenade of Antioch.
T.E.D.
"And Saint Stallman raised the API on high, saying, "O Lord, bless this Thy API, that with it Thou mayest interface to Thine Operating System..."
T.E.D.
"Minimize Mutability" -- I really wish Microsoft would learn this one
Robert Fraser
+10  A: 

Many coding standards and longer documents and even books (Framework Design Guidelines) have been written on this topic, but much of this only helps at a fairly low level.

There is also a matter of taste. APIs may obey every rule in whatever rulebook, and still suck, due to slavish adherence to various in-vogue ideologies. A recent culprit is pattern-orientation, wherein Singleton Patterns (little more than initialized global variables) and Factory Patterns (a way of parameterizing construction, but often implemented when not needed) are overused. Lately, it's more likely that Inversion of Control (IoC) and associated explosion in the number of tiny interface types that adds redundant conceptual complexity to designs.

The best tutors for taste are imitation (reading lots of code and APIs, finding out what works and doesn't work), experience (making mistakes and learning from it) and thinking (don't just do what's fashionable for its own sake, think before you act).

Barry Kelly
+1  A: 

An API is bad when it is badly documented.

An API is good when it is well documented and follows a coding standard.

Now these are two, very simple and also very hard points to follow, this brings one into the area of software architecture. You need a good architect that structures the system and helps the framework follow its own guidlines.

Commenting code, writing an well explained manual for the API is Mandatory.

An API can be good if it has a good documentation which explains how to use it. But if the code is clean, good and follows a standard inside itself, it doesnt matter if it doenst have a decent documentation.

I've written a little about coding structure here

Filip Ekberg
The example posed in the question -- public static void Select(IList checkRead, IList checkWrite, IList checkError, int microseconds); -- wouldn't be any better if it was well-documented (it probably is) and I would bet it follows some coding standard. It's still ugly, having astonishing side-effects and unreasonable limits. If an API is scalable, does not violate Least Astonishment, and can be used *without* documentation, I will always prefer it over one with a tidy coding standard and copious documentation that I *have* to read in order to understand its limits and side-effects.
system PAUSE
A: 

I think what is paramount is readability, by which I mean the quality that makes the greatest number of programmers to make sense of what the code is doing in the shortest possible amount of time. But judging which piece of software is readable and which is not has that indescribable human quality: fuzziness. The points you mention do partly succeed in crystallizing it. However, in its entirety it has to remain a case-by-case affair and it would be really hard to come up with universal rules.

Frederick
+3  A: 

A good API has a semantic model close to the thing it describes.

For example, an API for creating and manipulating Excel spreadsheets would have classes like Workbook, Sheet, and Cell, with methods like Cell.SetValue(text) and Workbook.listSheets().

Dan Vinton
+21  A: 

You don't have to read the documentation to use it correctly.

The sign of an awesome API.

Quibblesome
How can you say that? Imagine getting a customer which want you to use a specific API for a certain task. First of all you need to know what the task is, then you need to Learn the API. If you don't have access to the code, how can it be self explained?
Filip Ekberg
@Quarrelsome Can you give an example of this?
Tim
Minimalist API - meaning there is no confusion as to which methods to call. Good naming making it easy to find the methods you're looking for. Exceptions that correct you if you are using the API incorrectly, etc.
Quibblesome
Exactly. Using SQLite ADO Wrapper 2.0 is an example, where by seeing the name of the class, method or exception, you can practically guess (correctly) what is going to happen.
Manuel Ferreria
I have also seen some excellent APIs that were basically self-documenting, by very good design, proper naming and concise comments/descriptions. It's totally fascinating how a simple header file can suddenly become all you need.
none
+1  A: 

I think a good API should allow custom IO and memory management hooks if it's applicable.

A typical example is you have your custom compressed archive format for data on disk and a third party library with a poor api wants to access data on disk and expects a path to a file where it can load its data.

This link has some good points: http://gamearchitect.net/2008/09/19/good-middleware/

Laserallan
+1  A: 

A bad API is one that is not used by its intended audience.

A good API is one that is used by its intended audience for the purpose for which it was designed.

A great API is one that is used by both its intended audience, for the its intended purpose, and an unintended audience for reasons unanticipated by its designers.

If Amazon publishes its API as both SOAP and REST, and the REST version wins out, that doesn't mean the underlying SOAP API was bad.

I'd imagine that the same will be true for you. You can read all you want about design and try your best, but the acid test will be use. Spend some time building in ways to get feedback on what works and what doesn't and be prepared to refactor as needed to make it better.

duffymo
+5  A: 

A good API allows the client to do pretty much everything they need to do, but doesn't require them to do a lot of mindless busy-work. Examples of "mindless busy work" would be initializing data structure fields, calling several routines in a sequence that never varies with no real custom code in between, etc.

The surest sign of a bad API is if your clients all want to wrap it with their own helper code. At the absolute least, your API should have provided that helper code. Most likely, it should have been designed to provide the higher level of abstraction the clients are rolling themselves on their own every time.

T.E.D.
+1  A: 

If the API produces an error message, ensure that the message and diagnostics help a developer work out what the problem is.

My expectation is that the caller of an API passes in input that is correct. A developer is the consumer of any error messages produced by the API (not the end user), and messages aimed at the developer help the developer debug their calling program.

Alan
+4  A: 

I've always liked this article in queue titled API Design Matters

http://queue.acm.org/detail.cfm?id=1255422

And this columns also that deals with API design issues:

http://queue.acm.org/detail.cfm?id=1229903

jasonco
A: 

A good API is one that makes simple things simple (minimum boilerplate and learning curve to do the most common things) and complicated things possible (maximum flexibility, as few assumptions as possible). A mediocre API is one that does one of these well (either insanely simple but only if you're trying to do really basic stuff, or insanely powerful, but with a really steep learning curve, etc). A horrible API is one that does neither of these well.

dsimcha
A: 

There are several other good answers on this already, so I thought I'd just throw in some links I didn't see mentioned.

Articles

  1. "A Little Manual Of API Design" by Jasmin Blanchette of Trolltech
  2. "Defining QT-Style C++ APIs" also Trolltech

Books:

  1. "Effective Java" by Joshua Bloch
  2. "The Practice Of Programming" by Kernighan and Pike
Lorin