10 ms·
The Worst API Ever Made?
- hyperliner 12y ago"ALWAYS start by writing some code as if you were a user trying to do the thing that the API is supposed to do." It still amazes me how many times junior devs ignore this. They will spend a lot of time walking through the UX scenarios, mocking it up, etc. But when designing the API layer, they just start creating end points instead of focusing on the "DX" scenarios (developer experience, not theirs, but devs using the API). I remember reading Cwalina's "Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries" and really learning what that means. It is a book focused on .NET but I wish many of my colleagues in the open source world would get over that and just read it. It would change their view on API design. And that is just the first chapter.
- voltagex_ 12y agoThe second edition of the Framework Design Guidelines book was written in 2008 and seems (from a 10 minute browse of the first chapter) to be pretty up to date still. It's ISBN 9780321545671 if anyone's looking for it (it's on Safari Books Online, too)
- walterbell 12y agoFirst chapter is included in the free preview: http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development-ebook/dp/B0017SWPNO/ref=sr_1_1_title_1_kin?s=books&ie=UTF8&qid=1407386835&sr=1-1&keywords=9780321545619#reader_B0017SWPNO http://www.amazon.com/Framework-Design-Guidelines-Convention...
- Rapzid 12y agoYeah, when I make API's or configs(or whatever) I usually start with the message(or config) format that I would want to use myself, then go from there. I should think for people wanting to use their own API's that would be pretty natural though.
- sbilstein 12y agoYea unfortunately, this is one of those things one really end up learning by experience. Once you've been writing code for long enough (and especially in a codebase that's been highly) is when the developer experience starts to be a thing that really occupies your mind when building.
- hcarvalhoalves 12y agoDesigning decent APIs is a good use case for TDD. You start writing what makes sense from the client/problem domain perspective.
- specialist 12y agoWriting code from the outside in. It's more iterative, experimental than TDD. TDD is fine when you have a pretty good idea of what you're doing. Alas, most of the time, I'm just winging it.
- LnxPrgr3 12y agoI do a modified version of this, mostly because I find if I start by writing code calling a "magical" API I sacrifice too much in the implementation to make the API exactly match my design. I do start by writing code to solve my problem without an API, then work from there to derive a sane API. Usually something reasonable falls out from that, without forcing the machine to bend over backwards to support what I'm doing. I don't think this is a bad principle—APIs ought to make common needs trivial to meet. I do think it's an over-simplification that's worth refining. (As an aside, I'm becoming more and more convinced that libraries implementing network protocols should pass network transport duties to the caller, at least in C-family languages. It seems worse for the caller, but trying to work e.g. a WebSockets library into a project with its own I/O event loop is its own exercise in pointless frustration.)
- lmm 12y agoHmm, my experience was the other way around; the junior devs who'd read their Agile books always did this, it was the senior devs (or architects) who would produce baroque APIs that exposed all the possible options but didn't help you with any use cases.
- wfunction 12y ago"The API is simple because the problem it’s solving is trivial." I beg to differ -- as ridiculous as the API interface may be, the problem it's solving is most certainly not even close to being trivial. High-performance logging for something as low-level as the thread scheduler is not something you can write in your sleep.
- kabdib 12y agoWell, the API in question (which I've used, and it was indeed an unpleasant experience) might not be solving something trivial, but it's certainly not well designed. My all-time worse API is SetupAPI, which despite its name is how you get access to USB devices on Windows. It's . . . pretty miserable. Runner-up is the COM-based stuff that manages the Windows firewall, which is not well specified and has 'interesting' timing issues. I have mercifully lost most of my memory of the Java stuff I was doing 15 years ago. That stuff made me hate life.
- zyb09 12y agoMy award goes to Extended MAPI. It took me weeks of trial and error just to read and send email messages through an Exchange Server. I remember people were selling 3rd party wrappers for the API, because it was so horrible.
- 12y ago
- mwww 12y agoCan anyone recommend any resources about API design?
- elbenshira 12y agoClassic: http://www.slideshare.net/guestbe92f4/how-to-design-a-good-a-p-i-and-why-it-matters-g-o-o-g-l-e http://www.slideshare.net/guestbe92f4/how-to-design-a-good-a... RESTful Web APIs (http://shop.oreilly.com/product/0636920028468.do http://shop.oreilly.com/product/0636920028468.do) was a good starting point for understanding RESTful HTTP APIs.
- _pmf_ 12y agoFor a very deep, thorough and painful treatment instead of feel-good books, read "Practical API Design" by Jaroslav Tulach. Yes, it's Java, but it exemplifies the fundamental tradeoff that the feel-good books ignore: the more powerful you make your API for users, the less potential for evolution and long-term maintenance your API retains.
- monksy 12y agoThat is on my queue of books to buy. [Which is below my queue of books to read]. So shouldn't there be a way to balance these requirements? It seems like we've ignored the ability to batch jobs, do async tasks etc. It sucks... but an API is out of my control.
- JoshTriplett 12y agoRead Rusty Russell's "easy to use versus hard to misuse": http://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html http://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html and http://ozlabs.org/~rusty/index.cgi/tech/2008-04-01.html http://ozlabs.org/~rusty/index.cgi/tech/2008-04-01.html
- johns 12y agohttps://www.youtube.com/watch?v=aAb7hSCtvGw https://www.youtube.com/watch?v=aAb7hSCtvGw
- ahelwer 12y agoI thought the standard way to use ETW is by generating code from a manifest file with Message Compiler. Presumably it takes care of all this boilerplate? You're right though, that's a weird API. It'd be interesting to learn the process behind its design.
- MaulingMonkey 12y agoThis is the way I've done it. Which boils the problem down to an init call and a call per event. I dislike the code generated bindings though - is there a more... data driven alternative that's good? I've got a simple event API where I have an event type identifier, and some basic data. Which I then need to pipe to some third party junk that listens to ETW events. To do this, I have to: 1) Manually map hundreds of event types to code generated ones, and update this mapping every time new events are added... or do a massive N:1 mapping... which is totally against the grain of the intended usage of the third party junk (although appears workable for the moment.) 2) Wrap every ETW event type with callbacks, and the init macro with a stub to allow callbacks, such that I may target the two "identically" configured endpoints... each with their own manifest and autogenerated header. 3) Wrap every ETW invoke with #ifdef s to limit them to the 1 of my 3 platforms they work on. It's quite ugly compared to the equivalents of the other 2 platforms.
- zvrba 12y agoAs somebody who tried to use ETW, I can say that the OP didn't do his homework. Everything you need to know about ETW is described here: http://msdn.microsoft.com/en-us/library/windows/desktop/bb968803(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/windows/desktop/bb96... ETW is much more than a simple logging system; the description says "Use ETW when you want to instrument your application, log user or kernel events to a log file, and consume events from a log file or in real time. ". It allows broadcast (multiple consumers), structured binary data, filtering based on data structure, etc. It is an immensely powerful system (See manifest-based events above). In addition to everything it does, it is also designed for performance and for not using too much space. Re my attempt to use ETW: I began to drool when reading the docs; it would be immensely useful in my project. However, the product must also work on Linux, and building a cross-platform layer for something like ETW (even if the Linux counterpart is a no-op) would be an overkill. I might return to it one day.
- klodolph 12y agoSo, "as somebody who tried to use ETW", you think that the author, who did in fact actually use ETW, didn't do his homework? Read the criticisms. They are not shallow.
- zvrba 12y agoFrom the article: "It is a logging system, and it is used to record performance and debugging information by everything from the kernel upwards." It's apparent that he did not do his homework. ETW is much closer to DTrace than to syslog (e.g., you can turn on and off certain events in a running application w/o disruption). EDIT: It seems that the author uses ETW as an excuse for writing a rant about how an API should be designed according to his taste. Powerful, low-level APIs are difficult to use. Simple as that.
- vl 12y agoI claim MS Crypto API is even worse (I used both Crypto and ETW on the same project, it's by far not as bad, good luck tuning it not to lose buffers under load though): I was implementing TLS/SSL in one of the services working at MS. I couldn't figure out many things from MSDN and samples - they would not cover error and some variations code paths, and there was just no way to figure it out. And recovery would be something like "in third buffer there will be value x, you have to it pass to other function". And there was a need to do it correctly for obvious reasons, really. So finally I requested access to IIS sources to see how it's done correctly, and discovered couple thousand lines of code with comments like this "xxx told us that buffer X will contain value bla if condition Z is met, and this is why we are doing it here". I had no choice but to cut-n-paste it to my service. I can tell you for sure, nobody outside MS, without access to internal sources? can implement TLS/SSL correctly by using MS Crypto APIs.
- klodolph 12y agoI think it has to be the sheer number of APIs that Microsoft has developed: they just don't have the resources to care about very many of them. It stems from Microsoft's extremely insular culture in the 1990s and 2000s, where being a "Microsoft developer" meant that you just didn't read code for open-source projects, didn't look at competing APIs, just did everything your own way. Apple had its own bad APIs, and blew a bunch of them away when OS X came along. So you want TLS/SSL on OS X, the typical way to do it was to just use OpenSSL. OpenSSL has tons of problems, but at least they're well-understood problems, with source code and documentation.
- rossjudson 12y agoI thought this was going to be link-bait crap until I actually read through the damn thing. My god. He could be right.
- malkia 12y agoNothing beats up the P4 C++ Api :) While I love perforce, their constantly changing C++ api with it's namespace wasting, bad error handling API is the worst out there...
- erikb 12y agoIf you feel the pain of public APIs you should definitely go and try some internal APIs companies write for themselves. Somehow they can really get worse than what people used to write for Programming 101 homeworks.
- aaronem 12y agoApparently the worst API ever made is this guy: http://i.imgur.com/EtWh3QZ.jpg http://i.imgur.com/EtWh3QZ.jpg Might want to see to the stylesheet.
- perlgeek 12y agoAnother "fun" API is the one from MUMPS (matrix processing stuff) in Fortran. See http://mumps.enseeiht.fr/doc/userguide_4.10.0.pdf http://mumps.enseeiht.fr/doc/userguide_4.10.0.pdf , for example page 10. It has lot of numbered "ICNTL" (input control) variables as well as named struct fields, and some of those struct fields are only valid if, for example ICNTL(26) has the values 0, 1 or 2. ICNTL is actually an array with 40 elements, though "only" 1-33 are currently in use. And then there's CNTL (float control parameters), INFOG, RINFOG and what not. Also, the number of calls you must do to the actual processing function depends on some combination of those magic variables. Needless to say that there are no named constants for all those magic variables, because the code must be backwards compatiable with Fortran 77, where the behavior of code with identifiers longer than 8 characters is undefined, and differs from compiler to compiler (some truncate, some allow them, some error out). So names are actually in short supply.
- akx 12y agoWonder what it is about the name MUMPS that makes software called that so terrible...
- bitroliest 12y agoI had amazing "fun" with Amazon's marketplace API. Highlights include: - rejection without error messages - multiple hours before the successful call showed up as successful - broken XML schemas along with conflicting versioning and My favorite: - error messages from the API asking me to call customer service to perform that action.
- winestock 12y agoAccording to Eric S. Raymond's version of the Jargon File, people used to joke that MS-DOS system calls delivered "same-day service." Now that we're living in the future, that joke has become literally true.
- pwilson_gorge 12y agoI offer a simple API decision which has condemned generations of programmers to useless toil. The decision in .Net to not map database NULL to programming language null. Perhaps there was some higher level philosophical distinction being drawn which mere mortals are not capable of understanding.
- Someone1234 12y ago> The decision in .Net to not map database NULL to programming language null. What specific API in the .Net framework does this (or doesn't do this)? Definitely hasn't been my experience but I am using Entity Framework so... It goes so far as to mark null-able database types as (bool?) (nullable bool) which is super helpful and you can use == null for comparisons.
- Hakeashar 12y agoADO.NET uses DBNull: http://msdn.microsoft.com/en-us/library/system.dbnull(v=vs.110).aspx http://msdn.microsoft.com/en-us/library/system.dbnull(v=vs.1... There's one valid (if obscure) use case for it, other than that it is pretty much redundant: http://stackoverflow.com/q/4488727/1180426 http://stackoverflow.com/q/4488727/1180426 All modern (micro)ORMs, even if they're just a thin wrapper over ADO.NET like Dapper, work just fine with regular nulls.
- asveikau 12y agoPoster has not worked very deeply with Win32, is unaware of its conventions. Film at 11. For example: > Yes, that’s right, every user of the Event Tracing for Windows API has to do the arithmetic and layout of the packed structure format themselves. These represent very common idioms in Windows. One common idiom is about binary compatibility. Microsoft can change the length of the structure in a future rev of the SDK. Old callers can still work because they are specifying sizes and offsets - the library can look at these and know what to do. The other common idiom (very common in the NT kernel for example) is similar to what C99 introduced for structures with variable-length members, something C definitely didn't do for you and even today with it standardized still gets pretty clumsy. The author lost all credibility when he wrote this: > StringCbCopy((LPSTR)((char * )pSessionProperties + pSessionProperties->LoggerNameOffset), sizeof(KERNEL_LOGGER_NAME), KERNEL_LOGGER_NAME); Why on earth would you say (LPSTR)(char * ) ? That is literally saying (char * ) (char * ). To me a "bad" API enters into questions like: * How does it handle errors? Consistency is good. Swallowing them to the caller is bad. * Does it give the caller the right level of detail about what is going on? It's especially common for it to be a black box and completely fail under some condition that the author did not envision. Some kind of escape hook that exposes implementation details makes library maintanence difficult but sometimes it's needed. I haven't looked too deeply at etw but I don't suspect it fails at these. Maybe it errs too much on one extreme on the 2nd bullet.
- markbnj 12y agoHa, was my first thought as well: you could write this same article about essentially every aspect of the Win32 API.
- BugBrother 12y agoTo be fair -- I am certainly not the only one that opened that page scared of seeing my own name. :-) >> It’s a great time in the history of computing to be writing an article about bad APIs (which is another way of saying it’s a terrible time to actually have to program for a living). It is hard to make good APIs. And for complex subjects it is probably impossible without iterating. But you would think the guys that did the 2nd generation of VMS were smarter and more experienced than me? But OK, there weren't much event driven programming in VMS, I assume. My vote for worst API I ever read: I remember reading the "Inside Macintosh" (pre Mac OS X) about simple file IO and it took me multiple readings to realize that you just set some of the parameters to get all the different functionality... (The rewrite of the Inside books were really good.)
- outworlder 12y agoI was half expecting the rant to be about TAPI. From memory, I remember at least one instance where it returns a void* pointer, with a few integers telling the offset of the information you need to get. But at least the function calls made sense. This is much worse.
- clockworkelf 12y agoWhat about COM? That was pretty bad.
- amaks 12y agoA funny anecdote on the topic. When I worked in WinFS team, folks tried to add new flags in CreateFile API. Turns out, all 32 bits in dwFlagsAndAttributes were already taken, including the hidden usages inside the Win32 subsystem implementation.