1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2025-08-10 21:51:42 +02:00

Proofreading

This commit is contained in:
Sergey Konstantinov
2023-06-17 17:10:04 +03:00
parent 4616abc3fb
commit 1539171ae3
2 changed files with 27 additions and 29 deletions

View File

@@ -1,26 +1,24 @@
### [On the Waterline of the Iceberg][back-compat-iceberg-waterline]
Before we start talking about extensible API design, we should discuss the hygienic minimum. A huge number of problems would have never happened if API vendors had paid more attention to marking their area of responsibility.
Before we start talking about extensible API design, we should discuss the hygienic minimum. Many problems would have never occurred if API vendors had paid more attention to clearly marking their area of responsibility.
##### Provide a Minimal Amount of Functionality
At any moment in its lifetime, your API is like an iceberg: it comprises an observable (i.e., documented) part and a hidden one, undocumented. If the API is designed properly, these two parts correspond to each other just like the above-water and under-water parts of a real iceberg do, i.e. one to ten. Why so? Because of two obvious reasons.
At any given moment, your API is like an iceberg: it comprises an observable (i.e., documented) part and a hidden undocumented one. If the API is properly designed, these two parts correspond to each other just like the above-water and under-water parts of a real iceberg do, i.e. one to ten. Why so? Because of two obvious reasons.
* Computers exist to make complicated things easy, not the other way around. The code that developers write using your API should describe a complicated problem's solution in neat and straightforward sentences. If developers have to write more code than the API itself comprises, then there is something rotten here. It's possible that this API isn't needed at all.
* Revoking API functionality causes losses. If you have promised to provide certain functionality, you will have to do so “forever” (or at least until the maintenance period for that API version is over). Pronouncing some functionality as deprecated can be tricky and may alienate your customers.
* Computers exist to make complicated things easy, not vice versa. The code developers write upon your API must describe a complicated problem's solution in neat and straightforward sentences. If developers have to write more code than the API itself comprises, then there is something rotten here. Probably, this API simply isn't needed at all.
* Revoking the API functionality causes losses. If you've promised to provide some functionality, you will have to do so “forever” (until this API version's maintenance period is over). Pronouncing some functionality deprecated is a tricky thing, potentially alienating your customers.
A rule of thumb is very simple: if some functionality might be withheld — then never expose it until you really need to. It might be reformulated like this: every entity, every field, and every public API method is a *product decision*. There must be solid *product* reasons why some functionality is exposed.
The rule of thumb is very simple: if some functionality might be withheld, then never expose it until you really need to. It might be reformulated as follows: every entity, every field, and every public API method is a *product decision*. There must be solid *product* reasons why certain functionality is exposed.
##### Avoid Gray Zones and Ambiguities
Your obligations to maintain some functionality must be stated as clearly as possible, especially regarding those environments and platforms where no native capability to restrict access to undocumented functionality exists. Unfortunately, developers tend to consider some private features they found to be eligible for use, thus presuming the API vendor shall maintain them intact. The policy on such “findings” must be articulated explicitly. At the very least, in the case of such non-authorized usage of undocumented functionality, you might refer to the docs and be within your rights in the eyes of the community.
Your obligations to maintain some functionality must be stated as clearly as possible, especially when provided in environments and platforms where there is no native capability to restrict access to undocumented functionality. Unfortunately, developers often consider some private features they “discover” as eligible for use, assuming the API vendor shall maintain them intact. The policy regarding such “findings” must be explicitly articulated. At the very least, in the case of unauthorized usage of undocumented functionality, you can refer to the documentation and be within your rights in the eyes of the community.
However, API developers often legitimize such gray zones themselves, for example, by:
However, API developers often legitimize these gray zones themselves. For example, by:
* Returning undocumented fields in endpoint responses
* Using private functionality in code samples in the docs, while responding to support messages, in conference talks, etc.
* Using private functionality in code samples: in the documentation, responses to support inquiries, conference talks, etc.
One cannot make a partial commitment. Either you guarantee this code will always work or do not slip the slightest note such functionality exists.
One cannot make a partial commitment. Either you guarantee that the code will always work or do not slip the slightest note that such functionality exists.
##### Codify Implicit Agreements
@@ -126,7 +124,7 @@ GET /v1/orders/{id}/events/history
Suppose at some moment we decided to allow trustworthy clients to get their coffee in advance before the payment is confirmed. So an order will jump straight to `"preparing_started"` or even `"ready"` without a `"payment_approved"` event being emitted. It might appear to you that this modification *is* backward-compatible since you've never really promised any specific event order being maintained, but it is not.
Let's assume that a developer (probably your company's business partner) wrote some code implementing some valuable business procedures, for example, gathering income and expenses analytics. It's quite logical to expect this code operates a state machine that switches from one state to another depending on specific events. This analytical code will be broken if the event order changes. In the best-case scenario, a developer will get some exceptions and will have to cope with the error's cause. In the worst case, partners will operate the incorrect statistics for an indefinite period of time until they find the issue.
Let's assume that a developer (probably your company's business partner) wrote some code implementing valuable business procedures, for example, gathering income and expenses analytics. It's quite logical to expect this code operates a state machine that switches from one state to another depending on specific events. This analytical code will be broken if the event order changes. In the best-case scenario, a developer will get some exceptions and will have to cope with the error's cause. In the worst case, partners will operate incorrect statistics for an indefinite period of time until they find the issue.
A proper decision would be, first, documenting the event order and the allowed states; second, continuing to generate the "payment_approved" event before the "preparing_started" one (since you're making a decision to prepare that order, so you're in fact approving the payment) and add extended payment information.
@@ -134,7 +132,7 @@ This example leads us to the last rule.
##### Product Logic Must Be Backward-Compatible as Well
State transition graph, event order, possible causes of status changes, etc. — such critical things must be documented. However, not every piece of business logic can be defined in the form of a programmable contract; some cannot be represented in a machine-readable form at all.
The state transition graph, event order, possible causes of status changes, etc. — such critical things must be documented. However, not every piece of business logic can be defined in the form of a programmable contract; some cannot be represented in a machine-readable form at all.
Imagine that one day you start taking phone calls. A client may contact the call center to cancel an order. You might even make this functionality *technically* backward-compatible by introducing new fields to the “order” entity. But the end-user might simply *know* the number and call it even if the app wasn't suggesting anything like that. The partner's business analytical code might be broken as well or start displaying weather on Mars since it was written without knowing about the possibility of canceling orders in circumvention of the partner's systems.