Third bullet: As if that’s not enough pressure.. Hopefully I’ve convinced you that API design is important. But why is it important to you personally?
If you get it right, it looks obvious in retrospect. It’s a good sign if people say: “of course that’s how it should look; so what?” Appropriate to audience: a good API in C++ might be a bad API in Java; a good API for economists might be a bad API for physicists.
So now you know the characteristics of a good API. In the remainder of the talk I’ll outline the general principles that lead to good APIs and specific attributes of Class, Method, and Exception APIs that lead to goodness. Finally I’ll conclude with a couple of quick examples API refactorings. First two sections are a bit fluffy but the last four are chock-full of code examples
Mention “subtle color code”
Худшее, что Вы можете сделать, это провести 6 месяцев над написанием 248-страничной спецификации прежде чем показать ее кому либо. К этому моменту Вы не сможете отказаться от API даже если принципиально ошибочно.
A static utility class containing decorators for applying retry policies, and static factories for the retry policies themselves. This one-page description isn’t yet a true specification, but it’s good enough to evaluate and improve the API. So how do you evaluate it?
You write code to it, early and often! Examples are among the most important code you’ll ever write to an API. They form the basis of thousands of actual programs so any good practices are magnified a thousand-fold, and and bugs pop up in a thousand places.
It’s best if different people write the plug-ins. The you test SPI doc as well.
I don’t mean that you shold take one API component from everyone and throw them together into a rude semblance of an API; that’s a recipe for disaster. Rather, you should come up with a unified, coherent design that represents a compromise among all the stakeholders in the API. You generally can’t fix API mistakes outright, but you improve things by making judicious, compatible additions
That’s all I have to say about the process of API design, now onto the principles of what makes for a good API design.
Often these names are metaphorical in nature, e.g. Publish-Subscribe service. (Some of these ‘bad’ names cross the line into ugly.)
If you remember only one thing in the talk, this is it. Conceptual weight, sometimes called conceptual surface-area
Не всегда легко понять, что входит в детали реализации. Хороший настраиваемый параметр : размер пула очередей ; плохой : Число элементов в хэш-таблице.
This advice is somewhat controversial, and is less applicable in a research setting
Parnas said it better than I ever could, so I’m simply going to read you what he said: I don’t know about you , but I find that inspiring. I’ve got religion. <next slide> and the only thing to do about it is to document religiously.
There is no excuse for an undocumented API element – period
(Next slide contains Dimentsion ex.)
Here’s an example from Java’s awt
That’s the last general principal I’m going to talk about.
Now let’s see how all of this applies to class design
This idea is central to functional programming
In plain English, ask yourself “is every Foo a Bar”? Unless you can say yes *with a straight face*, Foo must not extend Bar.
That’s all I have to say about class design
Now on to method design
Here’s and example from the W3C DOM API
Here’s a particularly egregious example of what not to do
I believe that method overloading is overused
Mention that Builder pattern is a special case of breaking up the method Nasty example from Win32 API
The get method on ByteBuffer in Java’s nio package violates this advice ThreadGroup.enumerate returns void
In a language that has checked and unchecked exceptions, …. A checked exception represents a strong statement by the API designer that a method can fail in some way, and the programmer should consider this and attempt to take corrective action. If you can’t take corrective action, then it shouldn’t be a checked exception.
Two quick API refactorings
This is an example where you win by solving a general problem
Around 1996 many people wrote thread-local variable implementations in Java. Most of them looked like this:
Code to assign a serial number to each thread and print a thread’s serial number Notice that outer class class is noninstantiable, and each of its static methods takes a single instance of the inner class. So why don’t we move the set and get methods onto the inner class? Once we do that there are no methods left on the outer class except the getKey static factory. So why don’t we do away with the outer class entirely? This is what we’re left with:
This is essentially the ThreadLocal API that Java adopted in release 1.2 Notice that it’s trivial to generify this API. It was impossible to generify the first API, and difficult to generify the second.
Not a glory profession - API designers like plumbers. Your APIs won’t be perfect, but with a bit of luck they’ll be good
An homage to Jon Bentley’s “Bumper-sticker Computer Science” in “More Programming Pearls” iJava Best-Practices book with a hidden agenda of encouraging programmers to think about API design **** Timothy Boudreau Jaroslav Tulach: Designing APIs that Stand the Test of Time Thursday 10/26, 3:30 P.M.