Designing an Interface to Call
Add, Migrate, Then Remove
Last timeWork That Takes Too Long
Every interface has to change and every change has somebody depending on the old behaviour. The work is classifying the change honestly and sequencing it so both sides can move alone.
What callers actually depend on
The first mistake is believing you know what callers depend on. You know what
you documented. They depend on what they observed.
The list is longer than the documentation. Field names and their types. The
set of error codes, including the ones you never wrote down. The ordering of
a list you never promised to order. The default applied when an optional
value is omitted. What counts as valid input, which they discovered by
sending things until something worked. The format of an identifier, which
somebody is parsing to extract a date. Whether a field is ever absent, which
decides whether their code checks for it.
Much of that was never a promise. It is a promise now, because software was
written against it, and the distinction between a promise you made and a
behaviour somebody noticed is invisible from their side.
The changes that are safe
A small set of changes is reliably safe, and the test is whether code
written against the old behaviour still works unchanged.
Adding a new optional field to a response is safe, provided callers ignore
fields they do not recognise, which is worth stating in your documentation as
an obligation on them rather than hoping. Adding a new operation is safe,
since nobody is calling it. Accepting an input you previously refused is
safe. Making an optional input genuinely optional is safe.
Everything that removes, renames, narrows or reorders is not safe, however
reasonable it is. And two look safe and are not: adding a value to an output
set, which breaks callers who wrote an exhaustive branch over the values they
saw, and adding a required input, which breaks every existing caller
immediately.
| compatible | breaking | breaks strict parsers | needs the three-step seq | |
|---|---|---|---|---|
| add an optional response | 1 | 0 | 0 | 0 |
| add a new operation | 1 | 0 | 0 | 0 |
| rename a field for clari | 0 | 1 | 1 | 1 |
| remove a field nobody se | 0 | 1 | 1 | 1 |
| make an optional input r | 0 | 1 | 1 | 1 |
| change a default from 20 | 0 | 1 | 0 | 1 |
| narrow an accepted range | 0 | 1 | 1 | 1 |
| add a value to a state s | 1 | 0 | 1 | 0 |
Doing a breaking change anyway
Sometimes the change has to happen. A field is genuinely wrong, a default is
genuinely harmful, an operation has to be withdrawn. The question is not
whether but how, and the answer is to split it into three steps that can
happen months apart.
The lesson stops here
2 more paragraphs to go
You have read the opening. The rest of the argument, the problems that check whether it landed, and the lines worth keeping at the end all come with a plan.
The first lesson of every course in the library reads the whole way through, free, so you can see exactly what the rest of them are.
See the planThe contentsThis is the reading half
Starting the course gives you your own copy of it. Every idea on every page has problems standing under it, marked with a reason rather than a tick, and any sentence you do not believe can be opened and argued with. None of that can happen on a page nobody owns.
The contents