Hacker News new | past | comments | ask | show | jobs | submit login
Annoyances of API Design (chickenwing.software)
220 points by ayi on Jan 28, 2016 | hide | past | favorite | 101 comments



    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.


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.


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.")


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.


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.


All of the names in the selector are short and easy to read, there's just a lot of them. I don't even know what the method does or what any of the parameter types, but I can make what I'd assume is a fairly accurate guess:

    outputImageProviderFromBufferWithPixelFormat:
Some kind of pixel format enumeration, probably along the lines of "[Class name of the receiver]PixelFormat". Also, the function probably returns an "OutputImageProvider", or something like that (could be a id with a protocol associated, due to "provider"). This one is longer than the others, but that's just because it contains information about what the message will return.

    pixelsWide:
The width of the output image in pixels, hopefully an NSUInteger (but sadly, probably an NSInteger, and Swift is only making this discrepancy worse).

    pixelsHigh:
Same as above.

    baseAddress:
A pointer to the buffer referenced.

    bytesPerRow:
The number of bytes per row, probably size_t?

    releaseCallback:
Something to call when the provider is released, probably a block? Actually, judging by the next parameter, probably a function pointer. Wow, this must be an old API!

    releaseContext:
An argument to pass to releaseCallback.

    colorSpace:
A color space value. Possibly an enumeration of RGB, HSV, etc., or a more complex type.

    shouldColorMatch:
While I'm not sure what color matching actually is, I do know that this parameter enables or disables it, and is of type BOOL.


If I may offer the downside... :)

There exists a type of programmer who will write essentially the same lines of code over and over and over again. If you're this type of programmer, having to type long function names is extremely painful.

There exists another type of programmer who refuses to retype the same thing over and over, so instead uses some technique for reusing that code. If you're this type of programmer then long, descriptive names are preferable.


It is already mentioned: you never have to type those by hand, there is autocomplete with placeholders.


But you do have do have to read them multiple times, and while while a descriptive name is good, there is a point where you are taking things too far and causing more problems than you are solving.

If I'm reading a variable name and by the end I've forgotten the first half of it's name, the long descriptive name isn't helping me nearly as much as the author might think.

Really, the variable name has a context, and I want to evaluate it within that context. That is, within the function as named, or the class and method, what does this variable name mean.


Also mentioned: usually in these cases you have items on separate lines, aligned at co colon. So you have to read just the first line to know what it is all about.


It's OK, but I wouldn't call it great. It's readable, but sort of hard to use. The trouble is that the interface is too flexible, more so than the underlying code, and so it's hard to know which combinations of parameters are legal. If you ask for a disallowed combination, you just get nil back and no explanation.

Edit: wrong API! This one does have a pixel format object.

It also tries to be helpful and so doesn't require all parameters. If you don't give it a data pointer, it will allocate memory for you. If you don't give it bytesPerRow, it will calculate it for you. These ought to be separate calls, not all glued together into one gigantic do-everything call.

The verbosity itself is fine, but it's symptomatic of some suboptimal API design behind it.


Though it's a C API, CGBitmapContextCreate is notorious for this.

While it doesn't address everything you're alluding to, I'm a big fan of Swift's nonnull/nullable making its way into Objective-C since some of Apple's APIs don't play well with a nil parameter (e.g., -[NSString isEqualToString:]).


Yup, I like it too.

Besides being clear w/o having to dig into references or source, it also makes 'oops, wrong variable order' bugs much less likely to occur (e.g., swapped width and height is obvious using the above, not so much if using positional args).


Seriously, if you are annoyed by the long string, in most languages you can make a short form wrapper with trivial effort and trivial (if any) runtime overhead. I don't understand the complaining.


Sometimes a long name is just a hint that the code wasn't factored enough.

For instance, the phrase "outputImageProviderFromBufferWith..." suggests that the Buffer concept should have been a separate thing (probably its own class), that OutputImageProvider could be constructed from.


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.


I would argue that JSON wins by the maxim of "worse is better"; its vastly reduced feature set works to repel bad architects' efforts to incorporate horrendous and partially-supported WS-* concepts, external entities, doctypes, crazypants XSDs, and the horrors of XSLT--not that these things are bad in and of themselves, in fact they can be great, but interop can turn into absolute hell. IME if you have the luxury of working purely in .NET, on an updated, common version of WCF, and also nobody on the team goes wild with overdesign, the tooling and the things you can do are pretty great. OTOH testability is questionable, security might be bad, you spend a lot of time finding the right magic incantations to make everything work, and sometimes the tooling breaks in bizarre ways despite good efforts.

TLDR I used to be a big fan of XML, have switched to JSON, and probably won't be going back.


> 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

You really should try to use SOAP again, you will soon change your mind. I used it a few weeks ago (after about 5 years of peaceful life) and let me tell you - it still sucks.

The problem with SOAP is that, even if it is a standard, every $@%#*! library implements it in a slightly different way, leading to incompatibilities. Maybe it was just my luck, but every time I tried to use SOAP I ended up debugging XML envelopes and whatnot. With REST/HTTP + JSON? Just send, receive, parse, do what you want.

</rant>


> 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.


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


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.


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.


> XML's saving grace was that it came with good schemas out of the box

JSON is inherently "schema-less". So this provides us with no grievance.

> something that has, at best, extremely weak types

You provide the reader with nothing that indicates that strong-typing is important for JSON use-cases.

> schema equivalents that are bolted on, rarely used, and end up relying on humans understanding exactly what the data looks like

There are no schemas in JSON.


There is always a schema.

True, json has no formal explicit schema attached to the data.

However, there is still the ad-hoc informal schema that's defined by what the code interacting with the data does. Because this tends to be poorly specified and hard to get at, it's rather annoying to work with.


Haha, I've just always thought that if XML was too hard for you, maybe you should stick to graphic design...


'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'?


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


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.


I still don't remember if it is useradd or adduser - one is core linux command, other is script that also set ups home directory and stuff like that.


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.


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


Or 'tmpfile' and 'tmpnam'. Gotta save those characters. 'tempfile' and 'tempname' would be to hard to type. (Also, why not 'tmpfil'?)


The number of significant characters in an extern symbol was only upgraded to 31 with C99... prior to that, it was all of 6.


This sounded a bit far-fetched so I did some digging. It is true that C89 had a maximum of 6 characters for external identifiers. C89 is often called ANSI C.

C89 says:

"The implementation shall treat at least the first 31 characters of an internal name (a macro name or an identifier that does not have external linkage) as significant. Corresponding lower-case and upper-case letters are different. The implementation may further restrict the significance of an external name (an identifier that has external linkage) to six characters and may ignore distinctions of alphabetical case for such names./10/ These limitations on identifiers are all implementation-defined."

Source: http://flash-gordon.me.uk/ansi.c.txt


creat


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 )


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.


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.


> Since nobody uses Obj-C without Xcode

Hey now, I do! But I'm convinced that I'm subconsciously some kind of masochist, so that's probably not proving you wrong.


hey now, I edit objc in emacs all the time!


I'm sorry but that sounds like a horrible excuse. Not only you are bound to a platform but also an IDE.


Let's create the "Tweetable API" movement. If the most common call of a function doesn't fit in a tweet, you're probably doing it wrong.


> If the most common call of a function doesn't fit in a tweet, you're probably doing it wrong.

As with all metrics, that can be gamed. Would

    s:o:b:iGR:iGG:iGB:iGO:iSR:iSG:iSB:iSO:oGR:oGG:oGB:oGO:oSR:oSG:oSB:oSO:I:O:
(the same arguments, obfuscated), which comes in at a much-reduced character count of 75, be any better?


Well then we can just add "if you have to abbreviate your function name and arguments for the common form to fit in a tweet, you're probably doing it wrong".


> "if you have to abbreviate your function name and arguments for the common form to fit in a tweet, you're probably doing it wrong".

There go all my Unix commands! (OK, that is an uncharitable interpretation—changing `mv` to `move` wouldn't overflow a tweet—but it does indicate, I think, that it's not always obvious when an abbreviation is reasonable.)


Those abbreviation decisions were made in the early 1970's. How does that indicate the non-obviousness of deciding when it is or is not appropriate to use abbreviations today?


I was writing from the point of view of someone who finds Unix abbreviations perfectly acceptable (as compared to my comically abrogated SmallTalk / Objective-C (I don't even know which) invocation above (https://news.ycombinator.com/item?id=10990803), which I'd say is clearly not acceptable). Certainly, my argument will not be convincing to someone who doesn't share that point of view.


Unix is incredibly guilty of this. Everything would be so much easier to learn if mv was generally aliased to move and all code examples used the long version.


> Everything would be so much easier to learn if mv was generally aliased to move and all code examples used the long version.

I dunno; Tim Berners-Lee has said that his single biggest mistake was including two slashes in URLs (as in http://news.ycombinator.com, as opposed to http:/news.ycombinator.com). (I can't find any better citation for this than http://www.plughitzlive.com/theupstream/298-creator-of-the-w..., unfortunately.) I think that one shouldn't underestimate the apparently negligible impact of an extra character or two, if there will be millions of people typing those extra characters potentially many times a day, over the course of decades or centuries.

(Actually, now that I read your post more carefully, you say that `mv` should be aliased to `move`, meaning, I assume, that `mv` would also be available. I am still unsure about that, because most people would never bother to learn the short version—witness how many people don't know keyboard shortcuts for their most commonly used programmes—but I guess the experts would, and that, perhaps, is enough.)


It wasn't too hard to track down the quote; it is:

http://library.fora.tv/2009/10/08/Next_Decade_Technologies_C...

He wasn't even saying that the // should be a single /, he was saying that the : at the end of the protocol identifier is already sufficient. He wanted something more like:

    http:news.ycombinator.com/


I'm totally onboard with saving two keystrokes. I don't have all second to move this file.


Don't listen to me—I don't know anything about good API design. (That's not sarcasm or modesty, but the simple truth.) However, if the self-diagnosed biggest mistake of Tim Berners-Lee's life was to add a single extra character to a commonly typed string, then surely one has to consider that the addition of two extra characters could eventually also be judged a mistake?


From my point of view, he wasn't saying it because it's an extra character, but because http://news.ycombinator.com is more cryptic and harder to understand than http:news.ycombinator.com.

That fits into my belief that more readable (move instead of mv) is better.


In iOS 9, there currently seem to be 45 methods whose selector alone is longer than 140 characters. But how many of those are actually supposed to be used is another question ;)


I would guess that this method was created by a code generator, starting from a data structure with all of those fields.

More generally, a long initializer (or class method that returns an autoreleased object) is a fairly common pattern in Objective-C because it provides a common piece of code that all other initializers can call. There is usually some more obvious and convenient choice available, to avoid calling the horrible method directly.


Windows is known for having some rather long API names, such as RtlWriteDecodedUcsDataIntoSmartLBlobUcsWritingContext or EapHostPeerQueryUIBlobFromInteractiveUIInputFields. More examples at:

http://ashutoshmehra.net/blog/2010/02/long-function-names/


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.


> 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.


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.


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.


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


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.


> 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.


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.


To be fair, Android has a hugely disproportionate number of API WTFs to choose from. It's an absolute mess.


there's Apple. It is using Android as an example. I am pretty sure a lot of libraries do the same. To be more precise, the 6th is more likely for any GUI building toolkit out there. pretty much every single one of them end up a dozen of lines just to build a single thing.


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


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.


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.


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.


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


> 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.


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).


> 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.


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.


> Not with APIs we've shipped.

To be fair to allengeorge's analogy, writers also rarely edit written works that have already been published.


.net's standard library assemblies are generally excellent. A little verbose, perhaps. And very occassionnally a "what were they thinking?" moment (like WebClient throwing an exception for a 404 response-- fixed in HttpClient.) But overall, excellent.


Agreed for the most part. My only gripe with the .NET world, and Microsoft's ecosystem in general, is the love for XML (#7 in the article).


They've generally dropped said love in the newer framework versions.

Also - don't judge MS' love of XML too much, without it, we wouldn't have gotten XMLHttpRequest. :)


Good to hear. What are they using for configuration in the newer frameworks instead?

True, XMLHttpRequest was good for the world. My distaste for XML generally stems from some particularly bad experiences I have had working with XML configuration files meant for humans to modify and some particularly poorly-implemented tools for working with said files. :)


The Python "Requests" library is known for having a well-designed API, standing on the shoulders of API mistakes made by urllib[123]. :)

http://docs.python-requests.org/


Stripe is decent.


Qt


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)


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


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.


> 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.


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.


I'll just put this here: phpsadness.com


"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.


> 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.


Version X.1 is not X+1. X.1 should contain no breaking changes. Otherwise your versioning is useless. If any change to the version number implies breaking changes, then you could replace the version with Rand() and it would do the same. If you're shipping versions like X.Y.Z for 3rd parties to consume, you should learn to use those minor and patch versions meaningfully.


He's saying that APIs not providing backwards compatibility is annoying.

So yes, it's annoying when the next android release is out just as you're finishing your app, your code no longer works and you'll have to rewrite parts just because, while not receiving much benefit.

It's annoying as your application now likely have to support multiple versions of the API as well.


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.


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?


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


I have never needed a Kardashian for an API call.


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?


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?


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.


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.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: