Cells exchanging messages through their membranes

Alan Kay invented the term object oriented programming. He also spent decades telling everyone that we got it wrong. There is a famous line from him, something like: I made up the term object oriented, and I can tell you I did not have C++ in mind.

Most of us learned OOP as a catalog of class tricks. Inheritance, polymorphism, abstract classes, design patterns stacked like Lego. I taught it that way too, years ago, and I now think we were teaching the furniture and missing the house.

Kay’s original vision came from biology. He was thinking about cells. A cell is a small, complete thing. It has a membrane. Nothing outside can reach in and poke its internals. The only way to interact with a cell is to send it chemical signals, and the cell decides for itself how to respond. Scale that up and you get an organism, billions of cells, cooperating only through messages, no cell reading another cell’s private state.

That was the idea. Objects as little independent machines. The important part was never the class hierarchy. The important part was the messaging, and the wall.

Why this matters for money, not philosophy

I do not care much about purity debates. After years in this, including eleven running my own company, I judge ideas by one question: does this make change cheaper? Because change is where the money goes. Writing the first version of a system is the cheap part. The expensive part is the next ten years of changing it while it runs.

Here is the connection. When objects interact only through messages, with their internals hidden, you can rewrite the inside of one object without touching anything else. The membrane protects the rest of the system from your change. Cost of change stays local.

When objects share internals, when class A reaches into class B’s fields, when a deep inheritance tree means a change in the parent shakes every child, the membrane is broken. Now a small change has a blast radius. You touch one thing and three distant things break. Estimates become fiction. Every feature costs more than the last one. The team slows down and nobody can point at the single reason, because the reason is spread across the whole codebase.

This is what coupling means in practice. Not an abstract sin. A multiplier on the price of every future change.

Robert Martin has hammered this point for years, and the SOLID principles, when you squint, are mostly different angles on the same instruction: depend on the message, not on the guts. Program against an interface, against a contract, against the question you are asking, never against the private answer machinery.

The funny part: microservices rediscovered the same idea

Now zoom out and look at what the industry did at the architecture level. Microservices, when done well, are Kay’s cells at another scale. Each service hides its database. Nobody reaches into another service’s tables. All interaction goes through messages, an API call, an event on a queue. The membrane is now a network boundary, but the principle is identical.

And the failure mode is identical too. A distributed system where service A queries service B’s database directly, or where every service must be deployed together because they share fragile contracts, is the same broken membrane, just with network latency added. People call it a distributed monolith. I call it inheritance hell with extra steps and a bigger cloud bill. Martin Fowler’s writing on microservices makes this point well, the boundary is only worth its cost if it is a real boundary.

This is why I tell younger developers on my team: do not learn microservices as a separate religion. Learn boundaries and messaging once, deeply. Then you will recognize the same shape everywhere. A well designed class, a well designed module, a well designed service, and a well designed public API are the same idea wearing different clothes. Something hidden inside, a small clear set of messages outside.

A practical test I use in reviews

When I review a design, I ask a simple question about each piece: if we had to rewrite the inside of this thing from scratch, who would notice?

If the answer is “only this thing’s own tests,” the boundary is good. Change here will always be cheap.

If the answer is “uh, let me check who uses these fields,” the boundary is decoration. You have one big organism pretending to be cells, and you will pay for the pretending later, with interest.

I also watch for a smell that Kay’s framing makes obvious: objects that are just bags of data, with the logic living somewhere else in a manager or service class that reaches in and manipulates them. That is procedural code wearing an OOP costume. The cell is dead, something outside is moving its organs around. Sometimes that is fine for simple cases, honestly. But for the core domain logic of a business, it usually means the rules about the data are far from the data, and every change requires archaeology.

In Brazil we have a saying about the dog and the owner looking alike. Codebases and team communication look alike too, which is basically Conway’s law. If your modules cannot send clean messages to each other, check how your teams are talking first.

So yes, Alan Kay was right, and being right early is almost the same as being wrong, because nobody listens. The good news is the idea survives in every layer of what we build today. Classes, modules, services, APIs. Hide the insides. Talk through messages. Keep the membrane intact.

It is not about elegance. It is about being able to change your system next year without fear, and fear, in software, is the most expensive thing on the balance sheet.

Pax et bonum.