
Annoyances of API Design - ayi
http://chickenwing.software/scratches/programming/annoying-apis
======
cballard

        outputImageProviderFromBufferWithPixelFormat:pixelsWide:pixelsHigh:baseAddress:bytesPerRow:releaseCallback:releaseContext:colorSpace:shouldColorMatch:
    

No, this is _great_! I can glance at something calling this, and, without any
comments, determine immediately what each parameter is!

Note that standard formatting is to place each argument on its own line, with
the colons lined up, and that Xcode does this automatically, and will
autocomplete the entire nonsense. It's fairly disingenuous to line the whole
thing up as if you need to type it all out.

Also, this is an API that clearly bridges to C-style data structures. Higher
level APIs will have much fewer parameters.

> What’s the difference between a tap and a touch?

In Apple-land, at least, a _tap_ is an action (touching somewhere and
releasing quickly, as opposed to a swipe, etc.), and a _touch_ is where a
user's finger is currently placed.

~~~
derrickdirge
I couldn't agree more wrt the virtues of descriptive names. An enormous set of
code comments is made redundant by the use of more descriptive names. Modern
tools make it trivially easy to reproduce names of arbitrary length.

I can't see the downside, yet the author of the article acts like it should be
obvious.

~~~
_yosefk
Long names are hard to read. This makes autocompletion dangerous (I had a
terrible bug where I locked the wrong of two mutexes with long, descriptive
names which were too similar visually.)

A good name is short enough to read as a sign in itself, it shouldn't be
parsed as a sentence.

The more code reuse there is, the less you might be using the same name, as a
sister comment says - but the more names you have, and a lot of long names is
really hard to read. So I disagree with sister's "downside" of "it's bad for
bad programmers". It's even worse for otherwise good ones who buy into this
style. (Or maybe not, maybe they just read differently from me and say Rob
Pike who objected "names which are short essays about the thing they name.")

~~~
mjmsmith
I'm a big fan of Apple's descriptive and remarkably consistent APIs, but the
combination does make autocomplete errors easy to make and hard to notice. For
instance:

    
    
      - tableView:didSelectRowAtIndexPath:
      - tableView:didDeselectRowAtIndexPath:
    

If you accidentally choose the latter, the behavior seems baffling: the first
tap on an item does nothing, and every tap afterwards gives you the indexPath
of the previously selected item. I'm embarrassed to admit how long I spent
looking at indexPath values in the debugger and thinking "this can't be
happening" before realizing what actually was happening.

~~~
srikz
I made the same mistake a couple of times! Felt so stupid once I found the bug
:-/

I still prefer long descriptive method names though.

These days, I format the method so that each param goes into a newline (after
Xcode autocompletes it) and this helps me catch such bugs.

------
hibikir
Yes, XML is a big annoyance. But let me give you a bigger one: Json.

XML's saving grace was that it came with good schemas out of the box, so
turning something from XML to, say, a Java object, was not very difficult. It
wasn't difficult to use a SOAP service without having to do manual
serialization work.

Today though, we are using something that has, at best, extremely weak types,
and with schema equivalents that are bolted on, rarely used, and end up
relying on humans understanding exactly what the data looks like, just for
serialization/deserialization. I guess you can live with that easily if you
are writing in a language that has really weak types in the first place, as
you'd have to read the documentation anyway (What date format is the field
using? Better go read about it), but the moment you try to do something even
slightly more sturdy, the process is excruciatingly painful.

Heck, even tools like try to "help" document APIs, like swagger, end up with
specifications that chill the bones.

It is as if the web was built for and by people that are absolutely allergic
to both specification and types: In a more sensible world, we'd get something
like: If the RDS is postgres, then the data format is like this, and if it's
MySQL, it's like this instead. But what we have out there in the world is big
lists of optional fields that will be illegal, or ignored, or who knows what.

I was a big XML hater, back in the days of SOAP, but the more I see how
services are defined today, the better the old rust bucket looks.

~~~
dpark
> _XML 's saving grace was that it came with good schemas out of the box, so
> turning something from XML to, say, a Java object, was not very difficult._

Huh? How do you know what types <a><b c="d"><e/></b><b f="g" /><a> has? How do
you transform that into a Java object? For that matter, if you manage to turn
this into a Java object, how do you know how to transform it back into XML?
What members turn into attributes and which turn into sub-elements?

Or are you referring to XSD, which showed up years later, is not required, and
often not used? Yes, XSD grafts typing onto XML quite effectively, but this is
a bolt-on just like the JSON approaches. It just turned out to be a widely-
adopted bolt-on.

~~~
elktea
Who cares what the XML looks like? You import the wsdl and off you go.

~~~
annnnd
_IF_ it works. Which it almost never does (in my experience: 3 fails out of 3
trials), unless you are using the same SOAP library on both ends.

~~~
eoincathal
Similar experiences for me. Needed to spend time tweaking a wsdl so it
produced the same behaviour in 2 SOAP webservice endpoints, one using dotNET
tooling and the other Java. Worked fine after a bit of fiddling but leaves an
uneasy feeling.

------
aji
'dup' is a bad example from C, in my opinion. ('dup' and 'dupe' are both short
forms of 'duplicate' anyway.)

What about 'strncpy' versus 'strlcpy'? Or 'vsnprintf'? 'fcntl.h'? 'execlp'?
'EBADF'? 'SIGSEGV'? 'lstat'?

~~~
Gibbon1
Course those come from a primordial age when max symbol sizes and file names
were limited. Circa 1975 you were asking for trouble with a file name like
string_copy.c or file_control.c

~~~
annnnd
Also, I kind of like the short versions. They are not any more difficult to
remember ("Hmm, was it CopyFile of FileCopy?") and you need to search for them
the first time around anyway. And it does save the effort when typing.

~~~
timlyo
Maybe it's just me but I find the short ones much harder. Was it strnCopy or
strCopy etc.

And I mostly use some form of auto complete so I'm not worried about the
effort saved from typing.

~~~
dkersten
Also, if you glance at them, strcpy and strncpy look identical, which I find
can be problematic.

------
Rockslide
The Objective-C example is not even close to the worst case :) I raise you

    
    
        shapeEffectSingleBlurFrom:withInteriorFill:offset:blurSize:innerGlowRed:innerGlowGreen:innerGlowBlue:innerGlowOpacity:innerShadowRed:innerShadowGreen:innerShadowBlue:innerShadowOpacity:outerGlowRed:outerGlowGreen:outerGlowBlue:outerGlowOpacity:outerShadowRed:outerShadowGreen:outerShadowBlue:outerShadowOpacity:hasInsideShadowBlur:hasOutsideShadowBlur:
    

(as queried with
[https://github.com/leoschweizer/Heliograph](https://github.com/leoschweizer/Heliograph)
)

~~~
pavlov
Since nobody uses Obj-C without Xcode, you actually never need to type out a
long method name. Typically you'd just write "sha", Xcode will autocomplete
the method, and you press Tab to fill out all those parameters. Seeing them
all at once as part of the method name is pretty convenient.

I'm not saying that the method name in your example makes any sense, it's
definitely insanely long... But the Apple API mentioned in the original post
is OK in my books because it's a rarely used initializer for a low-level
object. It essentially wraps a raw C pointer into an object, so of course it
needs all that metadata about what the pointer is! Putting the same data in a
struct wouldn't save any typing.

~~~
wingerlang
Sometimes I write it in Sublime. Although even then, I sometimes just write
the method in Xcode to get the autocomplete then copy paste it, or just open
the non-xcode-project file in xcode.

------
50CNT
The "self-explanatory"/"brevity" problem is quite interesting. It reminds me
of the point Donald Norman made in "The Design of Everyday Things", where
information is either found in the world, or in our heads, coupled with issues
of information-density. When we pick names, it's a trade-off between
abbreviated (-> fast to use), descriptive (-> fast to learn), and mnemonic (->
easy to remember).

I roughly divide naming problems into 3 areas mentally. Most commonly used
commands(/functions/identifiers/...), commonly used commands, and rarely used
commands.

Most commonly used commands are things like ls or cd or mkdir. Due to their
usage frequency, an intermediate user will remember these by heart, and
mentally substitute their long forms whilst reading them out. Technically we
could assign these to even shorter codes, but then they would loose their
mnemonic value.

Preferably they would also have a long-form alias to provide a certain amount
of easing into them. (list-directory, change-directory, make-directory)

Commonly used commands should not be abbreviated as readily. The few extra
characters required to type them are usually well worth the additional
clarity. Pythons .deepcopy() is a good example. It copies a data structure and
its sub-structures completely. .dpcp() would be a lot harder to remember given
how often it is used.

It should be possible to alias these to shorter versions as well, should
someone have to use them frequently. Auto-complete functionality may also
reduce the amount of memorization necessary whilst typing these in.

I personally think emacs handles these two cases very well, with it's quick
chords that need to be memorized but provide speed, and calling commands by
name via M-x which provides ease of use.

Then there's the rarely used stuff. These names may get very long if they are
to be descriptive (ncursescplusplusmusicplayer), which means that they, or
parts of them should probably be abbreviated (nccppmp, or preferably nccpp-
musicplayer). Runs of abbreviated words should not become too long, 3-5
characters being the maximum. Past that length, it becomes hard to remember
which characters one has already typed. (ncpmpp? or nccppmp?). Past that
sensible chunking through full words or hyphenation may become necessary.

I do think these are sensible rules of thumb, but then they are rules of
thumb, and there are most likely thousands of exceptions to them.

~~~
sundarurfriend
> Most commonly used commands are things like ls or cd or mkdir. [...]

> Preferably they would also have a long-form alias to provide a certain
> amount of easing into them. (list-directory, change-directory, make-
> directory)

This reminds me of MS Powershell. `Set-Location` is the command for changing
to a new directory location, and it's also abbreviated (aliased) as `cd`.
Similarly with `ls` and many other commands. Powershell scripts often have the
full forms of the commands, while in the shell itself you get the convenience
of the shorter commands.

------
maxxxxx
Writing a good consistent API for things of a certain complexity and
maintaining and extending it for a long time is an extremely difficult thing.
I have been doing this for a few years now and it's humbling to see how
something that looked really smart a while ago is causing you major headaches
now.

------
euske
API naming is hard because of the conflicting goals:

1\. You want to make it easy to type/read. 2\. You want to make it
descriptive. (conflicting with #1) 3\. You want to make it consistent and
unique. 4\. You want to make it compatible with older APIs. (conflicting with
#3) 5\. You want to make it unambiguous. 6\. You want to make it
flexible/amenable to future changes. (conflicting with #5) ...

etc, etc. It's just impossible to meet all these requirements with developers
that live in a different time and space.

------
happywolf
The title is misleading because this is focused on Android, but the title
seems to imply generic API design pitfalls

~~~
gregmac
The last half definitely devolves into Android API-bashing. The first half
does generally apply to most APIs.

The main issue with most APIs boils down to documentation. Document it well,
and it will largely be usable. This means everything from cross-references
("If you are trying to do X, ThisOtherMethod may be a better fit") to
examples, and also extends to the API itself (good naming, and discoverable
methods). Most developers using your API do not live in your API -- they live
in their application domain. So you need to put effort into ensuring jargon is
explained, the API is discoverable, and basically they can use the API easily,
and get on with their application.

I really like the idea of thinking of API design in terms of Developer
Experience (DX), in the same way that user interface designers consider User
Experience (UX) about much, much more than simply the layout and colors.

~~~
ascagnel_
> Document it well, and it will largely be usable.

And a simple, easy-to-use API will also be comparatively simple to document.
If you're at the point where writing documentation is hard, that's strong code
smell that something is amiss.

~~~
laveur
Agreed! The API should basically document itself. If you have to provide long
examples of how to do something then there is a good chance the API isn't that
good. Easy to use for developers makes a platform more stable and produces
better quality apps, IMHO.

------
laveur
This is priceless! Pretty much contains everything that I hate about Android
Development.

------
dimonomid
I enjoyed the read, entertaining and to the point, thanks.

Personally I'm in favour of long and descriptive names. I'm not afraid of
typing. But since I'm writing in C (mostly embedded stuff), I'm not in the
mainstream of the C community with my preferences. Sigh.

------
muzani
Haha, this has a lot about what I hate about Android. I actually did quit
programming and became a barista, because of the exact thing he said. Then I
slowly got into programming again.

I actually started when Fragments were being introduced. Now that was a
nightmare. The backwards compatibility was a red herring. The real problem was
that Fragments were a poor practice, unsuited for many apps and teams... but
Google played them out as The Next Big Thing. Today it's happening with
Material Design.

~~~
annnnd
Not sure what you mean with the last sentence?

Anyway, Fragments are a nightmare. I learned them, I used them, and if I have
to use them today I would still need to open that tutorial I have saved
somewhere. That is one ugly solution if there ever was one.

------
gaara87
So... what is an example of a well written API/SDK?

~~~
JadeNB
> So... what is an example of a well written API/SDK?

I think that this is an underrated question. I am not a programmer, but a
mathematician; I will write from my experience in that field.

I was trying to understand a paper which used horrible, ad hoc notation that
obscured the simple ideas at its centre. I invented a new, harmonious notation
that beautifully revealed these simple ideas, and wrote a paper using it.

The notation was beatiful and harmonious as long as you were its inventor, and
it was the most recent thing that you had been thinking about. Now, when I go
back and read that paper … I think "wow, this horrible notation obscures the
simple ideas at the centre of the paper."

Incidentally, I still think that the notation is better than the original; but
the main thing that I've learned is to do it yourself before you complain
about what someone else has done—after which (a) you'll have a good
implementation and won't need to complain, or (b) you'll feel much humbler and
won't want to complain.

~~~
allengeorge
Or maybe, the takeaway is: revisit your work later, when it's no longer fresh
in your mind :) You'll understand what the strengths and weaknesses of your
new design are, and are better placed to make an improved iteration.

Incidentally, writers have been doing this for years with drafts and editing.
We definitely need to do that with our APIs and designs (aka. more incremental
refactoring).

~~~
dpark
> _We definitely need to do that with our APIs and designs (aka. more
> incremental refactoring)._

Not with APIs we've shipped. Then it becomes breaking changes that appear
pointless to others. Even when it's logically worth it to go back and fix
APIs, it's rarely worth it practically. If no one is using your APIs, then do
whatever. If your APIs are popular, you might find yourself in "version next"
limbo like so many major projects that redesigned and couldn't convince their
users to follow.

~~~
allengeorge
You're absolutely right. FWIW, I think this iterative process should take
place before publishing your API. Sometimes a design needs to 'sit' for a
month or two and be used a bit before you realize its boundaries: what it does
well, and what could be improved. If you're judicious about improvements (i.e.
don't rewrite) you'll avoid the second-system effect and put out an API
that'll be better than your first attempt. I realize that's not always
possible.

------
spacecowboy_lon
The main ones I find are

1 Using the wrong sort of approach for your api eg using a basic REST when the
obvious paradime to use would be a Queue.

2 Documentation only comprehensible to insiders who all ready know the system
backwards ( I am looking at you Google)

------
danenania
As with other types of interface design, the best way to write a good api is
to get frequent feedback from the intended users.

Liberal application of the WTF test is critical[1].

As the author of the api, you yourself will be too close to it to judge
fairly. Poorly named functions and over-complicated architecture will appear
perfectly reasonable to you if you don't seek outside opinions.

1: [http://commadot.com/wp-
content/uploads/2009/02/wtf.png](http://commadot.com/wp-
content/uploads/2009/02/wtf.png)

------
TazeTSchnitzel
Abbreviations can be annoying, but mainly because you don't know what they
mean. I'd be less bothered by them if APIs using them would clearly document
the meaning. Alas, that never happens.

------
efaref
> why say dupe when we can save that valuable E and say dup?

"dup" is short for "duplicate", a saving of 6 characters, not "dupe", which
means to deceive or fool.

------
beat
There are only two hard problems in computer science - naming things, cache
invalidation, and off by one errors.

Glad to see "naming things" made the top of the list. Names that are readable
and sensible can be remarkably hard.

------
frontsideair
I'll just put this here: phpsadness.com

------
LoSboccacc
"What’s the difference between a tap and a touch? I have no idea"

TL;DR api design is hard because these are the programmers we write api for.
Never happy, can't grasp the basic of the platform they're using, won't read
any documentation to save their lives and expect all code to come to them
magically perfect as if formed in a vacuum and not having a back-compat
history.

------
njharman
> Annoyance the 5.1beta3 – Version incompatibility

That makes no sense. Yes, version X+1 is incompatible with version X. That's
why we upped the version number!!!

I wonder if author never had to deal with API/Service that changed and was
poorly or unversioned. Suddenly and mysteriously breaking things.

~~~
ktRolster
It's annoying when an API isn't backwards compatible for no good reason.
Android increases their version numbers quite often, which means you have to
do extra work (which is annoying if someone is paying you, but worse if
someone isn't).

Crockford said, "Changing an API is an act of violence." An API designer
should think long and hard before breaking backwards compatibility: usually
it's not necessary.

~~~
izacus
Uh... Android's APIs are one of the most backwards compatible I've worked with
(most applications written for 2.0 will work without issues on new Androids).
Could you elaborate what extra work do you have to do? In comparison to what?

------
Jean-Philipe
Thanks for speaking my mind! I especially enjoyed your word creations.

------
daxfohl
I have never needed a Kardashian for an API call.

------
ericmcell
These are all library/SDK functions, can you just call anything an API
nowadays? What application is my application interfacing with when I call an
android SDK function?

------
ericmcell
Can you just call anything an API nowadays? These are all SDK/Library
functions. What application is my Android app interfacing with when I call
android SDK functions?

~~~
sgt
This is definitely an API; Application Programming Interface. An API can be a
remote Web API such as a RESTful API or SOAP, or it can be against a shared
library (i.e. a set of functions or methods) on your own computer.

------
draw_down
I think the selector in #2 is great. Sure it's long, so what. Reading it tells
you exactly what the hell that line of code does.

