> If you’re building an abstraction-heavy API, be prepared to think hard before adding new features. If you’re building an abstraction-light API, commit to it and resist the temptation to add abstractions when it comes along. You could always do both. Provide a low-level abstraction-light API that allows fine control but requires deep expertise, and write a higher-level abstraction-rich API on top of it that maps to…
I'm particularly fond of this pattern when you can implement the high level API that you want outside the library , which ensures that your low level API is sufficiently flexible and means you're dogfooding your own stuff as a user. It's far too easy to get used to the internal side of a tool you're building, and forget how people actually use it.
No Abstractions: our API design principle
111–120 of 141 posts
Re: No Abstractions: our API design principle
#112The title of the concept is misleading, "No Abstractions" here doesn't literally mean "no abstractions" but instead "we use this specific set of abstractions, and not others". And the specific subset they describe is worth discussing! But it's of course a set of abstractions.
E.g.
> For example, the parameters we expose when making an ACH transfer via our API are named after fields in the Nacha specification
A specification is an abstraction.
> Similar to how we use network nomenclature, we try to model our resources after real-world events like an action taken or a message sent. This results in more of our API resources being immutable [...] and group them together under a state machine “lifecycle object”.
Immutability (in this sense) and "lifecycle objects" are abstractions.
> If, for a given API resource, the set of actions a user can take on different instances of the resource varies a lot, we tend to split it into multiple resources.
Another abstraction, just splitting at a different level than the Stripe API.
This is a set of design decisions and abstractions. Definitely not a "no abstractions" principle. I would say the most important decision they seem to have made is to generalize as little as possible -- and generalization is indeed a kind of abstraction. Maybe "Fewer Generalizations" would have been a more accurate title?
Re: No Abstractions: our API design principle
#113Earlier quoted context omitted.
It doesn't double the security surface area if the abstracted API goes through the low-level API. The outer one is just chrome, and so the risks of screwing something up there is far lower. Unless you're using a trash language where even simple wrappers could buffer underrun or something.
Isn't there the issue of modifying the state enough through the low-level API such that it breaks the assumptions of the high-level one?
The high-level API needs to handle that case, if nothing better than having internal assertions that throw if it hits a case it's not designed to accommodate.
(also I'm annoyed with myself that I wrote buffer underrun in my first post instead of buffer overflow and now it's too late to edit).
Re: No Abstractions: our API design principle
#114Earlier quoted context omitted.
In this case, a HTTP API is the abstraction. Integrating with ACH and other payment rails requires a lengthy integration process. Sometime you have to send binary files using FTP!
The article says “no abstractions”, but HTTP is often exactly that: an abstraction over lower-level protocols.
The API being implemented with JSON over HTTP isn't related to the domain of processing payments, so I don't see it as a contradiction to the article's title.
Re: No Abstractions: our API design principle
#115Earlier quoted context omitted.
The article says “no abstractions”, but HTTP is often exactly that: an abstraction over lower-level protocols.
I guess the phrase "no abstractions" is specifically valuable to us when designing our REST API resources - our whole stack is certainly an abstraction of sorts, but we don't want to add yet another abstraction in that specific layer.
Re: No Abstractions: our API design principle
#116So they say parts of the API structure are based 1-1 on externally controlled specifications. What happens if those specifications evolve or change? New API?
A versioned API. Which means more APIs to maintain, until they are removed.
Re: No Abstractions: our API design principle
#117> If you’re building an abstraction-heavy API, be prepared to think hard before adding new features. If you’re building an abstraction-light API, commit to it and resist the temptation to add abstractions when it comes along. You could always do both. Provide a low-level abstraction-light API that allows fine control but requires deep expertise, and write a higher-level abstraction-rich API on top of it that maps to…
Re: No Abstractions: our API design principle
#118> If you’re building an abstraction-heavy API, be prepared to think hard before adding new features. If you’re building an abstraction-light API, commit to it and resist the temptation to add abstractions when it comes along. You could always do both. Provide a low-level abstraction-light API that allows fine control but requires deep expertise, and write a higher-level abstraction-rich API on top of it that maps to…
Re: No Abstractions: our API design principle
#119> If you’re building an abstraction-heavy API, be prepared to think hard before adding new features. If you’re building an abstraction-light API, commit to it and resist the temptation to add abstractions when it comes along. You could always do both. Provide a low-level abstraction-light API that allows fine control but requires deep expertise, and write a higher-level abstraction-rich API on top of it that maps to…
Agreed. We have a rich API to build complex pipelines, but a lot of times, users do simple mappings. So there is an API for that common use case, which has a much simpler syntax, but internally uses the rich API
Re: No Abstractions: our API design principle
#120> If you’re building an abstraction-heavy API, be prepared to think hard before adding new features. If you’re building an abstraction-light API, commit to it and resist the temptation to add abstractions when it comes along. You could always do both. Provide a low-level abstraction-light API that allows fine control but requires deep expertise, and write a higher-level abstraction-rich API on top of it that maps to…
I’m genuinely curious as to what an abstraction-rich api would look like and why it would be useful. I’ve mainly worked in enterprise organisations or in startups transitioning into enterprise which is sort of where my expertise lies. I’ve never seen an API that wasn’t similar to the examples in this case. I mean… I have… but they wouldn’t be labelled as high-abstraction api’s. If they needed a label it would be terr…
Or (as others have pointed out) the various `git` "porcelain" commands (checkout/add/commit/branch) compared to the primitive operations for dealing with various object types. Even just `git pull` as a combination of `git fetch` and `git merge`.
Or how a filesystem API of open/read/write/close/unlink is a very simple abstraction over block allocation and (in the old days) moving a disk head and waiting for the platter to spin under it in order to access the right sector. Not to mention the "directory" and "subdirectory" abstraction, instead of just having one giant table of inode numbers.
Edit: Or compare HTML with abstractions like "headings" and "paragraphs" to a raw typesetting language like troff or TeX.