Join the discussion
Write your take first — we'll ask for email only when you're ready to publish.
- Hacker News
- For most developers OOP seems to be just a handful of memes they are vaguely aware of and a kind of generally irritating sense of things not quite working in Java. No amount of writing, discussions, examples and history will change this.by romaniv
- I felt this way for years until I decided (for fun) to work through the extremely excellent and recommended Pharo "MOOC" (https://mooc.pharo.org/) to learn Smalltalk.
I'm now OO pilled and feel it has really improved my Python and my golang.
by ElevenLathe - There was a Soviet philosopher, Evald Ilyenkov, whose books taught me about a "minimal working model". I'll explain it in my own words.
People do not think with words: people think with things. Words serve merely as pointers to things. Some things are easy to point at; Ilyenkov talks about a cow. Some things are much harder to point at; Ilyenkov, being a Marxist, wanted to point to private property, we need to point to an object. Usually we try to talk about them using definitions, that is some sequences of words that are supposed to describe a thing. Such discussions are notoriously unproductive. The reason is that words are not really good as pointers: we have much more things than we have words and we have to reuse the same words to point to different things in different contexts. Yet in a phrase words look same so we tend to conflate these different things. As a result we get lost and go around in circles.
So instead of definitions Ilyenkov talks about a notion. Notion is something that reliably points to a thing that is hard to point at. It does not have to be an abstract thing: for example, we cannot point to radio. We can point to a household radio apparat but it has way too many parts completely unrelated to radio as a principle. So instead we build a minimal radio that has like three or four parts yet is capable of emitting or receiving radio waves.
We can do the same with abstract things too using the same approach. Let's build a minimal working model of a thing. "Working" so that the model indeed has the quality we are after; and "minimal" so that if we lose a single part, the quality is gone. Since the thing is abstract the model will also be abstract, that is it will be a sequence of words too, very much like a definition, but not quite.
(The same principle is widely used in parables: they describe some situation and thus try to guide your attention to certain qualities of it, hoping to trigger understanding. Sometimes it is hard to even name the thing they are pointing at, yet their pointing power is palpable. I myself often think about the parable about seven blind people and an elephant. You see I'm not naming the thing it points at: I don't have a good name for it.)
So let's go back to object oriented programming. What would be a minimal working thing that we can reliably call an object?
Here is what cannot be there. First, there must be no inheritance. If inheritance were required, then the first thing we build wouldn't be an object as it would have nothing to inherit from. Only the second thing would be an object and only because it inherited from the first. But this does not seem right. Second, there must be no polymorphism on the same grounds.
But at the same time if we do this:
then it is too minimal. It is hard to say how it is different from a function. It is not an object at all. Yet; there is a missing part that would turn this into a true object, but what the part is could be somewhat surprising.class Aaaa method bbbb(): ... - don't say "apparat" when you can say "device".
side note, when first transistor-based portable radios showed up (as opposed to large lamp-based stationary devices), they were called "transistor". you would take not your portable radio with you, it was your transistor.
by watt - That's super interesting. Thank you for that.
I believe what's missing is not just data. That'd only grant it capabilities that upgrade it to a "record" type of entity. I believe an OOP object is more than a record. It's missing behavior triggered by messages. For an object to pass or receive a message we need to have a model of a message and that requires the notion of a sender and receiver, both objects again. Seems circular, but I'm sure it could be made to work if you properly define everything. Anyway, to my mind perhaps the minimal model of an object is not at all _one object_ but a _relation_ between two or more objects showcasing the minimal "message passing" semantics.
Weird take, but inheritance could be included if you accept something can inherit from itself. A is a type of A, I mean it doesn't strike me as wrong, but it is unconventional.
- Another commenter pointed it out already but might as well stress the point: objects are bundles of data and behavior. Your example is missing data.
- Your example lacks data. An object is the combination of data and code manipulating the data with some syntactic sugar on topby usrnm
- Thank you Mikhail. I'm reading a lot of metaphysics, and thinking hard about the nature of programming and object orientation, so I appreciate your philosophical approach to the problem. I wasn't aware of Ilyenkov.
To answer your question:
> What would be a minimal working thing that we can reliably call an object?
You might enjoy this paper a lot: https://piumarta.com/software/id-objmodel/objmodel2.pdf
Also check out the primary author's work on COLA as well for mind-bending possibilities this would unlock.
> First, there must be no inheritance.
The paper uses inheritance, but I've been exploring the same concepts WITHOUT it, and it works as well, if not better. Composition and delegation are more flexible. My current working theory is that inheritance is overrated at best, and too dangerous in the hands of common mortals, because it makes you think on the level of idealized categories rather than concrete things.
As further reading, your explanation of things vs words reminded me of prototypes vs classes, so I'll recommend this article by Henry Lieberman: https://web.media.mit.edu/~lieber/Lieberary/OOP/Delegation/D...
by sph - Alan Kay's definition of OOP is my favourite one, though I actually extended it a bit; for instance, erlang/elixir kind of have "failsafe, reliable objects". Now, barely anyone would call these languages OOP, but IMO it follows just logically similar to Alan Kay's definition. Probably a new language may be required, which is hard to do (make it a succes, that is hard), but along those lines of having a wider definition of OOP. What I definitely hate is the limitation towards C++ and Java. Those two languages really messed up the OOP term, and then we had clown languages such as PHP just copy/pasting that definition and not understanding what OOP is really all about.by shevy-java
- That's the Smalltalk school of OOP. There is also the Simula school. It is kind of unfortunate that they use the same name.by ahartmetz
- > OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.
How does Simula differ here?
by mycall - > That's the Smalltalk school of OOP
In particular the "Smalltalk-72 school" which had indeed something like "message passing" (though still synchronously). Starting from Smalltalk-76, and particularly in Smalltalk-80, which is the Smalltalk we know today, the object model pretty much corresponds to Simula-67, with compiled methods dipatched via virtual method tables. The only difference is, that in Smalltalk, the dispatch goes via the internalized string address of the selector (vs. method index as e.g. in Simula-67, C++ or Java). See e.g. https://dl.acm.org/doi/10.1145/3386335.
by Rochus - > OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.
This sounds a lot like microservice architecture.
by _pdp_ - Taken to an extreme. It's not feasible with current microservice architecture to, for example, represent every Boolean in the program as a service.by Twey
- I too think that microservices and REST are Kay OOP, although through a network boundary of course
The separation of objects and usage of network protocols naturally forces interaction via communication and not data sharing, so perhaps as an emergent phenomenon it converges on Kay OOP. Although no doubt Netflix Microservice OG engineers were influenced by both Kay and Java.
by TZubiri - Very similar, yes.
Except that Kay did not envision the distinct computers communicating via REST.
https://blog.metaobject.com/2019/11/what-alan-kay-got-wrong-...
Also: microservices currently require at least process and frequently even VM/Container/Machine boundaries.
In-Process REST scales that down:
https://link.springer.com/chapter/10.1007/978-1-4614-9299-3_...
Language support for In-Process REST:
by mpweiher - Foundational source nowadays. Cited by wikipedia on the topic of OOP
I have personally taken to calling OOP either Kay OOP or Java OOP to differentiate between the original more philosophical meaning, and the later language imposed features.
by TZubiri - I think the actor model comes closest to Kay's objects.
An object holds it's own state and might change that state based on messages it receives.
Today you can find this in, for example, Elixir and Microsoft Orleans.
by paolfs - Actors are great, but it’s just making objects large enough so one thinks carefully before architecting a whole hierarchy of them to solve a simple problem.
As someone else said in this thread, OOP is fine for modularity, the problem is people don’t know how modular a problem should be and are driven to overcomplicate the design of any application.
by sph - > I think the actor model comes closest to Kay's objects.
It's rather the other way round. There is no pre-Hewitt implemented semantics matching Kay's later 2001 claims; Smalltalk-72 was a synchronous token-stream interpreter rather than a system of independently active message-driven agents; FLEX shows processes, scheduling and quasi-parallel control, not objects, not messaging, not actor-style autonomous entities.
by Rochus - IMO, the most important philosophy in all of software engineering is "Separation of responsibilities." The best way to achieve it is through the principle of "High cohesion, loose coupling."
OOP is just another layer of philosophy which builds on top of that. It's more specific, imposes additional guardrails. It requires objects with state encapsulation (locality) and message-passing as the mechanism for components to interact with each other; each component is responsible for changing a subset of the state of the system. Each component is responsible for handling messages (calls to action) by performing local state changes and potentially also sending messages to other components which have more specific sub-responsibilities.
OOP without "High cohesion, loose coupling" is almost worthless IMO. It must build on top.
I think were most people fail with OOP is that they think coming up with good separation of concerns, good abstractions is easy. They just start implementing the first idea which comes out of their heads and then figure out the scope of responsibilities as they go.
The test for good separation of concerns is that you should be able to explain your architecture to someone with the intellect of a 9 year old child who happens to understand the business domain. I'm not exaggerating. It has to be that obvious or else you will not be able to maintain clean separation... You will not be able to maintain alignment in your team.
If the responsibilities of a specific object are somewhat vague, what will happen is that the scope of responsibilities between objects will soon blur and the messages between objects will start to look increasingly elaborate; your system will look like a bunch of horrible incompetent managers trying to micromanage junior employees using long, convoluted instructions and occasionally throwing chairs at them...
If your system is passing around object references all over the place; that's usually a sign of poor separation of concerns; passing around complex objects by reference is tight coupling, by definition. Each object, each person should be able to fulfill their responsibilities and finish the job using communication only.
- This resonates strongly with me, which is why I find more important having some form of namespacing than anything else.
OOP has been muddied so much too, it would be interesting if we taught only the "separation of responsibilities" part and principles related to that.
Often it comes up: who has write authority, that's something we don't teach as part of OOP, yet realizing that only one thing should do writing improves the code dramatically.
Now that you see it, seems so obvious
- I agree "high cohesion, loose coupling" is a good architectural property to strive for, but OOP is terrible at it and there's no reason to use it for this.
Trying to achieve "high cohesion, loose coupling" in OOP has led to the creation of (supposedly) best practice recommendations like the SOLID principles, and the development of monstrosities like dependency injection frameworks.
If OOP was actually good at "high cohesion, loose coupling", you wouldn't need them.
- People are going to come out of the woodwork to argue about OO specifically, and I'd probably join in, but the higher-level view that I've come to over the years is that one programming paradigm is not the best in all situations. It really helps to work on a lot of different systems that are not all in the same class and look at a lot of code written by people of all skill levels. It's not possible to really talk about all programs, but I will say that the OO way of thinking can very easily be overdone and end up a giant mess. Similarly, the FP way of thinking can also be very easily be overdone and end up a giant mess. The old-style procedural programming (C with a pile of global variables) can easily be overdone and end up a giant mess. Yet all three of those can actually work out great at the right scale on the right problem!
I think the problem is that we can't really architect a program well until after it works and fulfills all of its design requirements. Those are usually in flux and then we have to engineer dimensions of extensibility to prevent committing to the wrong architecture in the beginning. Those extra dimensions of extensibility come at some cost too, as they often mean indirection and cognitive overhead.
We often don't write the same program twice, or even three times, unless it's a really important program or a we just like doing it. Contrast to other fields, e.g. building houses, where we have lots and lots of examples of how to do it and they started to form archetypes. We try to call those design patterns in programming, but they're actually pretty vague and low-level. Can you imagine going to build a house and thinking "yeah, I think I need to use the wood-and-nails design pattern here, and I think I'll do rafters-and-shingles there, with some brick-and-mortar there." Yeah, real specific ideas on how to do it.
by titzer - I actually do wonder whether we're going to see more of a prevalence of people building one off software due to an increasing use of LLM's which makes the house building model you're describing more common in softwareby Folcon
- I think the underlying error - is the assumption that everyones model is going to be equal when looking on the world, as a world of objects. That holds up- for a surprisingly small number of objects we all interact with.
Then it breaks down- depending on how deep your abstraction level goes (A car has 4 tires. 4 tires are made of: xyz). It also breaks down, with the abstraction in the real world above the modeler. Some think in organization, some in physics, some in tribalist constructs, some imagine a god object above them some don't. It was communicated as a tool using "shared" state as a communication helper.
But we do not share as much state as expected.
by 21asdffdsa12 - I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages
It was originablly conceived as a simulation of a distributed system.
Distributed systems can be useful but does anyone really believe that they are simpler or easier to develop and maintain?
The amazing part to me is that so many were trained and convinced to accept that adopting this simulation could make all programming easier or somehow "better". As if adding complexity would magically lead to simplification.
by jqpabc123 - > Distributed systems can be useful but does anyone really believe that they are simpler or easier to develop and maintain?
Dinosaur. Whale.
I think these were success stories for a long time. So, it is possible to develop and maintain complex systems.
by shevy-java - Just a guess, it may be that he understood distribution more as the static distribution of meaning in fine grain entities (objects) to allow a wide range of context, flexibility. Not necessarily the time aspect of distribution.by agumonkey
- >Distributed systems can be useful but does anyone really believe that they are simpler or easier to develop and maintain?
If you try to maintain a decentralized system, it will be hard yes.
However if you see the nirvana and try to maintain the parts of the system, it will be easier.
by TZubiri