I've been taking my car to the same mechanic for years. I never sit in the waiting room. I watch. And every single time, I end up thinking about software.

Specifically, I think about interfaces. You will never — not once — see a mechanic pull out a welding torch to replace a brake pad. The caliper doesn't care who made the pad. The spark plug doesn't care if it's a Bosch or an NGK. Everything has a defined connection point. Everything communicates through a known contract. You swap the part, tighten the bolt, and the car works. Software developers wrote five principles about this. Car manufacturers just built the car.

Nothing gets welded

The thing that strikes me every time I'm in that garage: nothing in an engine is permanently joined to something it doesn't need to be joined to. The alternator bolts to a bracket. The battery cables clip to terminals. The oil filter threads on — specifically so you can thread it off three months later without special tools that haven't been invented yet.

Every connection is intentional. Every connection is reversible. And every part communicates with adjacent parts through a known contract: thread pitch, connector type, voltage spec, fluid port size. When a mechanic replaces the water pump, he doesn't need to understand how the fuel injection system works. The parts don't know about each other. They know about their interfaces.

This isn't clever engineering. It's the only way to build something that can be maintained. The alternative — welding everything together — produces a machine that works fine until the first thing breaks, at which point you don't fix it, you replace the whole thing.

SOLID in steel and rubber

Software developers formalized this in 1995 as the SOLID principles. Car manufacturers were doing it decades earlier, out of pure necessity. Here's what it looks like in the garage:

Single Responsibility. The alternator charges the battery. The radiator cools the engine. The fuel pump moves fuel. Nothing does two jobs. The second you find a component that "also handles" something adjacent, you've found the thing that will fail in a way nobody predicted — and fail loudly, taking something unrelated down with it.

Open/Closed. You can fit performance brake pads without touching the engine. The braking system is open to improvement — better pads, upgraded rotors, larger calipers — but the interface doesn't change. The car doesn't need to know you upgraded anything. Nothing downstream breaks. That's a system that's open for extension and closed for modification.

Liskov Substitution. Any battery that meets the spec fits. 12V, correct terminal placement, correct cold-cranking amps. The car doesn't interrogate the manufacturer. Swap a Varta for a Bosch — same result. The contract is what matters, not who fulfilled it.

Interface Segregation. The ECU communicates with what it needs to communicate with. The seat heater doesn't need to know the engine temperature. The headlights don't need access to the gearbox. Every component talks to what it needs — nothing more. Nobody asked the fuel pump to also report on tire pressure.

Dependency Inversion. Modern cars don't depend on specific component brands. They depend on interfaces — injector specs, sensor protocols, connector standards. Toyota doesn't care if your O2 sensor is a Bosch or a Denso, as long as it matches the protocol. The system is built against the abstraction, not the implementation.

Car manufacturers didn't read Robert Martin. They just knew that a machine nobody can service isn't a product — it's a liability.

What software gets wrong

We weld things.

Functions that do three things — we'll refactor later. Modules that reach into other modules' internals because it was faster to write it that way. Components tied so tightly to their data source that changing the database means rewriting the UI. A change in one service breaks something two layers away that had no business depending on it in the first place.

Red flag If your code review conversations include the phrase "we'll deal with that later," you're making a weld. Not today, maybe not next month. But that component is on its way to being something nobody wants to touch.

Car manufacturers solved this problem in the physical world because the cost of welding was immediate and obvious. A car that can't be serviced doesn't sell. In software, the cost of tight coupling arrives later — six months into the project, when adding a feature requires changing eight files you didn't expect to change, and the developer who wrote them has left the company.

The principles aren't academic. They're engineering. Every experienced engineer — mechanical, electrical, or software — eventually arrives at the same place: define clean interfaces, separate responsibilities, build against abstractions. The software community named it and wrote papers about it. Mechanics just built the car and moved on.

💡
First step: Pick one function or module in your current codebase and draw its connections — what it knows about, what knows about it. If the diagram looks like a circuit board instead of a bolt and socket, you've found where to start. Then ask: would I weld these two parts together in an engine? If the answer is obviously no, you have your answer.