ContentsThe library

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.

FIG 1Where breaking changes came from on one interface over two years
Not one of these was intended as a breaking change. Every one was somebody improving the interface. The first two together are over half, and both are removals: a rename is a removal and an addition performed at the same instant, which is the worst possible sequencing.

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.

FIG 2Eight proposed changes, classified
compatiblebreakingbreaks strict parsersneeds the three-step seq
add an optional response1000
add a new operation1000
rename a field for clari0111
remove a field nobody se0111
make an optional input r0111
change a default from 200101
narrow an accepted range0111
add a value to a state s1010
The two marked cells are the instructive ones. A rename is marked breaking because it is a removal, regardless of how much clearer the new name is. Adding a state value is marked compatible because old code keeps working, yet it still breaks anybody who wrote an exhaustive branch, which is why it has its own column.

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 contents

This 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

The rest of this course

  1. 01Every Awkward Interface You Have Ever Used Was Awkward for the Same Reason, and the Reason Was Decided in the First Half Hour
  2. 02There Are Only Two Questions Worth Asking About Any Operation, and Neither of Them Is What It Is Calledopening only
  3. 03Your Error Message Is Read by a Program First and a Human Second, and Almost Every Interface Gets That Order Backwardsopening only
  4. 04The Second Call Is Not a Mistakeopening only
  5. 05Counting From the Start Versus Remembering the Placeopening only
  6. 06A Limit Is Only Useful If Somebody Can Obey Itopening only
  7. 07Hand Back a Receipt, Not an Answeropening only
  8. 08Add, Migrate, Then Removeyou are here

Read alongside