Warning: no actual answers are given in this post 🙂
For a long time I’ve been fascinated what object-oriented programming is really all about. I’ve never talked to someone who could give me a closed definition, or could even give me the reasons why OOP is a good (or bad) idea. Lately I’ve been doing quite a lot of research, which led me to things as The early history of Smalltak, Smalltalk itself, a lot of work from Alan Kay, the Viewpoints Research Institute, Lisp, COLAs, Meta II and a lot more stuff. Very interesting, I can tell you, but while I learned a lot, I still don’t have the answers. Nevertheless, I thought it would be time to write down my results/thoughts so far.
For a lot of people, OOP is mostly about classes, inheritance, polymorphism and modelling nouns from the real world. When you go back in history, however, you’ll find that the term object-oriented programming was first used by Alan Kay, and he doesn’t seem to mean the aforementioned things at all. Instead, he says the most important idea about OOP is messaging, and that the term OOP was actually not that well chosen since it puts the focus on objects instead. He also says:
OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.
I’m specifically interested in this “definition”. Why? If a visionary like Alan Kay finds this important, it probably is. And I like to know important stuff 🙂 So what do these 3 things mean, what problems do they solve and how does OOP relate to them. Spoiler: I don’t have (all) the answers yet. Let’s visit these three concepts, and how I understand them at the moment.
Messaging. Communication between objects is done through messaging only. Each object decides how to interpret and act on a message themselves. Objects need to decide how messaging works up front.
Local retention and protection and hiding of state-process. An object has private memory which no other object can access. If another objects wants access to some of the data of an object, this needs to happen through a message. An object itself is in control of actually granting that request.
Extreme late-binding of all the things. This is the one I have the most trouble with grasping the consequences. The idea is to bind everything to concrete stuff as late as possible. For example: compiling to bytecode binds your code to a particular machine later than compiling directly to machine code. The main idea here is that you can delay important choices until you have better understanding. In C# a lot of decisions are already made for you (everything is an object, no multiple inheritance, etc) and we bind early to those decisions since there is no way to change them later. If we later find out multiple-inheritance would help in some part of our code, we have no way to do that. The same goes for selecting which method is gonna interpret a message, in C# this is determined compile time which forces you to do all kinds of weird stuff should you actually want to do that runtime.
From a software development point of view, I’ve seen all three things being helpful in one context or another: it feels logical that combining them indeed yields a very powerful programming model. Why Alan Kay thinks these 3 specifically are that important, however, I’m still not sure. At one point, he talks about Real Computers All The Way Down (RCATWD), meaning that every object can represent anything. That’s powerful, and I currently think it’s related to that, but I’m not exactly sure in what way yet.
One thing I noticed on reviewing this post is that at no point I’m talking about programming languages. That’s probably not coincidental, in the sense that OOP is not tied to any particular language; you can actually do OOP in a non-OOP language, and you can program in a non-OO style in OO languages.
So what is OOP? It seems safe to say that fundamental elements of this programming style are at least objects and messages, where objects communicate with each other through the messages. Objects have a private memory to store the data they need to carry out their computation. And that’s where things get messy: does everything need to be an object? If it is, how do you actually represent data (something like church numerals?)? If it’s not, where do you draw the line? Does it really matter, or is it fine to do just parts of your system OOP? How does functional relate to OOP?
All kind of questions I don’t really have an answer to at the moment, but I’ll get back to you if I find out..