The API I Kept Misusing Was My Own

For a long time I thought misusing an API was a sign you hadn’t read the docs. Then I spent a whole afternoon fighting a bug in my own code, in a module I had written myself only weeks earlier, and I finally understood that the problem wasn’t the reader. It was the interface.

The function took three boolean flags in a row. I had written it, I understood it, and I still passed them in the wrong order — because nothing stopped me. It compiled. It ran. It just did the wrong thing quietly. The design had left a trap in the open, and I’d walked into my own trap.

That was the day I stopped thinking of a good interface as one that’s documented well, and started thinking of it as one that’s hard to use wrong. Documentation asks the caller to be careful. A good shape doesn’t need them to be. It refuses the mistake at the door.

So I started reshaping things. Instead of three booleans, a small type whose name says what it means. Instead of an object you could construct half-built and then forget to finish, one that simply cannot exist in a broken state. Instead of returning null and mentioning it in a comment, returning the thing I actually promised. Each change removed a way for the next person to fall.

And the next person, again and again, turned out to be me. Every trap I left in an interface was a trap I eventually sprang myself, usually late, usually while chasing something unrelated. Designing for a careful stranger was really designing for my own tired future.

The best code I write now doesn’t rely on anyone reading the manual. It lets them do the obvious thing and quietly makes the obvious thing correct. I learned that not from a book, but from losing an afternoon to an interface I only had myself to blame for.

– Serguey Asael Shinder

Leave a comment