Published on

What a Light Socket Promises

Authors

Screw a bulb into a lamp and it lights up.

That is because the socket makes three promises, and it has kept them for decades. Every public method I write makes the same three promises. I just do not think about them as often.

The socket as a picture of an interface is not my idea. Many people have used a wall outlet the same way, Mike Bland among them. I just want to follow it a bit further than usual.

Here is how the picture maps to code. The lamp is the caller. The bulb is the implementation. The socket is the public method between them. The lamp and the bulb do not know each other. They only know the socket.

Promise One: This Is the Shape

The socket promises a thread and two contacts. Nothing more. So the bulb was free to change. Filament, halogen, LED, and now bulbs with wifi in them. No lamp had to be rewired, because the thread and the two contacts stayed the same.

A class works the same way. Keep the public methods the same shape, and I can change everything behind them. New algorithm, new database, new library. No caller needs to know.

A good shape also says what does not fit. Code is often not that strict. A method that takes a customer ID and an order ID, both as plain integers, will happily accept them in the wrong order. The compiler is happy. The bug is found in production. Give each ID its own type, and each argument only fits in one place. If it should not fit, it should not go in.

Promise Two: This Is What It Means

Fitting is not enough. The thing also has to mean something to the person using it.

An old radiator has a knob from 1 to 5. The number means how far the valve is open. That is all it means. So I am cold and turn it to 5. An hour later the room is too warm, so I turn it to 2. By evening I am cold again. The knob told me about the valve. I never wanted to know about the valve. I wanted the room to be warm.

A thermostat asks a different question: what temperature do you want? I say 21 degrees, and it works out the valve for me.

The work of turning "I am cold" into "open the valve this much" did not go away. It moved from me into the thermostat. That is what promise two is about. If a method talks about the mechanism, every caller has to do the translation. If it talks about what the caller wants, I do it once. There is one of me and many callers.

So before I write a public method, I ask: what is the caller trying to do? Writing two lines of the calling code first is the fastest way to find out.

When I get this wrong, there is always a sign. A method called Process with a comment explaining what it processes. A wiki page reminding everyone not to pass null. The comment is there because the method did not say it.

Promise Three: It Is Not Going to Change

The first two promises are mine to fix. That stops the moment somebody depends on them.

With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.

— Hyrum's Law, after Hyrum Wright

That is an observation, not an instruction. It does not tell me to keep every behaviour. It tells me I do not get to choose which ones people lean on. The tempting conclusion is to change nothing, ever, but that is paralysis: if every behaviour is depended on by somebody, then every bug fix breaks somebody. What I do get to choose is which behaviours I call the promise. I decide, I write it down, and I test it. That part I do not break. The rest I change when I need to, knowing somebody out there may be standing on it anyway.

Adding is usually safe. Changing or removing almost never is. Somewhere out there is code that has worked for three years, written by somebody who has left, and the day my harmless little fix ships is the day it stops working.

Final thought

Buy a bulb today and it fits a lamp from 1960. The socket promised very little, and then it kept the promise.

The first two promises are design. I can still change my mind while I am writing the code. The third starts the moment someone depends on me. After that, whatever I wrote down, I do not change.