Object-orientation, according to Alan Kay, is:
"OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.", Alan Kay
Let me simplify and focus:
Unidirectional data flow between objects
State private to objects
This means objects don't call one another for services; they are independent. This includes responsibility for any resources they might need to do their job, the simplest resource being memory to maintain state across processing different messages.
Encapsulating logic within an object by drawing a boundary around it is easily achieved by wrapping it in a function.
Messaging is easily established by preventing these functions from calling each other, instead arranging calls to them in a sequence and passing data downstream through parameters.
But how do we enable objects to maintain private state? How do we make data private to them?
Here's a small scenario to explore different ways to accomplish this: a program to sum and average numbers entered by the user one after another.
The objects that make up the implementation are straightforward: portals for user interaction and domain logic.
Since the program repeatedly prompts the user for another number to add, the flow between objects must execute multiple times. The small "rotating arrow" on the left indicates this repetition.
The portals are connected to external state — the environment for reading data from and writing data to the console.
In this design, the domain logic also requires state to track and update the sum and average. The specific form of this state — whether it's a list of numbers or updated results — is up to the object. Its state is local, private, and irrelevant to other objects.
How can we implement this while honoring the requirements of Radical Object-Orientation in general and this design in particular?
A trivial but “incorrect” solution would be:
This is “incorrect” because the state isn't private to the domain logic. All other functions could access it equally, making it global state. This is one of the problems with code from the 1960s that Alan Kay sought to eliminate.
In C/C++, this could be accomplished with variables local to the function:
However, this approach is limited to a few languages. A more general approach would be to place the function inside a module:
This hides the variables behind the module's interface, which only makes the function accessible.
From the perspective of understandability and reuse, this is excellent. However, testability remains lacking (as with the C/C++ solution): module state cannot be easily reset. The module is initialized only once when loaded. If this happens only once during a test framework run with multiple tests checking the domain logic, test runs would depend on one another, creating headaches.
How else can we link state to a function in a general and more testable way? Closures can help:
No global variables exist; they are encapsulated in the factory function createUpdateSummaries, which returns the function to be called in the data flow.
This is testable because each time the factory function produces a new updateSummaries function, a new set of state variables is also created.
Since many languages now support these Functional Programming (FP) techniques, it's a legitimate way to implement stateful objects. However, this approach may compromise understandability. Closures — here: a function creating another function and equipping it with a context — can be confusing. Not all developers are familiar with them, even though they are a very old programming concept.
However, they are a low-level pragmatic solution. This has long been recognized and is the motivation behind classes. Classes can be understood as abstractions of this pattern; they are syntactic sugar for the closure solution.1
Ah, finally! Yes, this is easy to understand and easy to test. That’s what you had in mind right from the start.
So, why the detour? I wanted to make it clear that Alan Kay wasn't concerned with classes. He invented object-orientation, not class-orientation. In his own words:
"[Object-orientation] is not even about classes. I'm sorry that I long ago coined the term 'objects' for this topic because it gets many people to focus on the lesser idea.", Alan Kay
He was concerned with building software from independent "processing units," each a black box fully responsible for a set of tasks, whether that required state or not. No details of how this purpose is accomplished must be visible to their environment or to other black boxes.
Classes are just optimizations that came later, and they came with their own set of problems. I'm even inclined to say they obliterated Alan Kay's original idea and caused a lot of harm. But I don't want to start a rant...
Modules, more specifically classes, are the way to encapsulate state with logic wrapped in functions. Who would have thought, right? But please look closely: even though the means don't change much — Radical Object-Orientation uses the same language constructs as mainstream object-orientation — the spirit changes. The mindset is different. Radical Object-Orientation comes from a different angle. It uses established means in a different, "restricted" way. Radical Object-Orientation constrains itself to achieve what Alan Kay had in mind: higher understandability, easier-to-reason-about code, increased reusability, and increased testability.
This might not be obvious with the limited examples I've provided, but trust me, we'll get there.
For now, let me represent the class as the container for both logic and state in the data flow diagram:
The state is moved inside the class's box and is accessible to all functions (now called "methods") of that class.
Please note two things:
Only the domain function became a method, i.e., moved into a class. The sole reason for this is to encapsulate a detail of its workings: its dependence on state. The method is still public and can be used from the outside, but the state is not. The environment isn't concerned with the state and doesn't care whether, where, or how it exists; it's only interested in the object's proper behavior. All other functions are still "floating around" and aren't put into a container because there's no reason to. To achieve what Alan Kay had in mind — messages flowing between black boxes working on messages — modules/classes aren't necessary. The "big idea" is primarily about encapsulating and decoupling logic. That goal is achieved by putting it in functions and making them functionally independent.
No function calls any other function. Neither is the Domain class dependent on a UI function, nor vice versa. This results from applying the PoMO principle of Radical Object-Orientation.
So much for the basic implementation of the concepts of Radical Object-Orientation. It's not difficult. What looked quite alien at the beginning — biological cells as an analogy for code — can readily be translated with the means of all mainstream OO languages.
What makes Radical Object-Orientation so different, though, is its focus on functions. It's functions first, classes second. Modeling software starts with "functional units" woven into data flows, which later get mapped to functions and methods. Classes are (almost) an afterthought and need to be justified.
And that's what we're going to look at next: why, when, and how to use classes.
In reality this is not how classes were first implemented, but it’s close enough for my purpose here, I’d say.












I read all your previous posts, and let me say this is outstanding work you're providing to us! I was planning to do the same; I'm working on a newsletter based on anything related to object orientation, and you're a source of inspiration. Definitely! Thank you!