Hacker News new | ask | show | jobs
by andai 903 days ago
>Few languages utilize message passing

Yet most of them call themselves object-oriented!

I'm reminded of the Alan Kay quote, "I invented the term object-oriented, and I can tell you that C++ wasn't what I had in mind."

2 comments

Unfortunately, 30+ years on he's never managed to explain to more than a handful of people what it was that he did have in mind.
Is Smalltalk’s message passing really all that different from methods from other OOP languages? Seems like quite an arbitrary distinction to me.
All OOP languages use message passing, but perhaps you mean languages with objects that are not oriented?

While not completely identical to Smalltalk's message passing design, the Qt project once went to all the trouble of building their own compiler just to be able to graft message passing onto C++. I think that goes to show that there really is a difference – otherwise, why not use the standard constructs C++ offered?

Whether or not that difference makes for better software is debatable. It does seem that at one time it did lend itself exceptionally well to GUI programming. NeXTSTEP/macOS/iOS also would never have been what they are without OOP. But we've also learned some programming tricks along the way, so it may not even shine there anymore. Swift, for example, has given up on OOP (except where @objc mode is enabled) and it seems like it manages to do quite well with GUIs (granted, having @objc mode to fall back on clouds that somewhat).

I mean that, to me, the difference between message passing and method calling is not significant enough to say that these languages are following different programming paradigms - like you say OOP vs languages with objects.

Afaict the difference between Smalltalk and Objective-C style message passing and Java and C# style method calling is purely syntactic.

> Afaict the difference between Smalltalk and Objective-C style message passing and Java and C# style method calling is purely syntactic.

doesNotUnderstand:/forwardInvocation: isn't different? That is not just syntactical. How would you even begin to orient your objects without like functionality?

I agree that if you squint really hard they look the same. But if we say "they are all the same", what are you trying to communicate when you say OOP? Virtually all programming languages we use have objects. You may as well drop the OO and just use "programming". It would communicate the same intent.

>doesNotUnderstand:/forwardInvocation: isn't different? That is not just syntactical. How would you even begin to orient your objects without like functionality?

Not sure what you mean. Could you please elaborate?

> what are you trying to communicate when you say OOP?

The idea of using dynamic dispatch as a means of taming complexity.

> Not sure what you mean. Could you please elaborate?

I'm not sure where your understanding falls short. Which part are you unsure of?

> The idea of using dynamic dispatch as a means of taming complexity.

Erlang utilizes the idea of dynamic dispatch as a means of taming complexity. What is it in particular about its dynamic dispatch mechanisms that you want me to know when you call attention to its OOP properties?

C++ also utilizes the idea of dynamic dispatch. When you call attention to its OOP properties, are the particulars being pointed to the same as in Erlang, or does it mean something different in the context of that language?

Yeah, the callee doesn’t have to have the method defined for it to be called and Smalltalk objects have a default you can use to do things with messages you don’t handle for example forward them on to another object.
You can definitely do that in Java too. This is how, e.g., Spring framework handles transactional behavior. It injects a proxy for each bean that is marked as @Transactional and the proxy object handles the coordination with the transaction manager and passes all the arguments to the real object.
Right but it’s not a core part of the language, anything Turing complete can implement this sort of thing. The comment I was replying to was asking about the difference between method calls and message passing.
I don't think ability to forward arbitrary messages is any more a core part of Smalltalk than it is of Java.
It’s the basis of the design of Smalltalk (see http://lists.squeakfoundation.org/pipermail/squeak-dev/1998-...) and needs scaffolding in Java to work which does seem significant.
It's a little different, and a little better. But not that much. In fact, right after that famous quote, Alan goes on to say: "I have many of the same feelings about Smalltalk".

https://www.youtube.com/watch?v=oKg1hTOQXoY&t=653s

(go back a little for the original quote)

For me, the problem with OO as is is that it really is just a Better Old Thing, not an actual New Thing, as the "object" part is quite underdeveloped.

When you have an object-oriented system, it is objects that are connected (somehow) and that then communicate (somehow).

But our object-oriented languages really only still have algorithms (procedures) and data structures. We do get to group and scope those procedures with the data structures, but that's not really too different from what we do in procedural coding.

So when we build a true OO system, we don't have any language support with it, so the program we write is a meta program that constructs the OO system procedurally. The system is not visible in the program text, it is created as a side effect of running the procedures and remains invisible, unless we develop tooling to make it visible.

And when that OO system runs, after you've built it procedurally, how is the communication between object mediate? Also procedures. Again, if there are other communication patterns, they can only be implemented using procedures in the language, they cannot be expressed in the language.

So with current programming languages (even OO ones), a good OO system will, by necessity, be highly indirect compared to the program text. A good OO system will also have sufficient benefits that this trade-off is very much worthwhile, but it is a significant trade-off. And when systems are not good the trade-off is not worth it. What's worse, people get confused and see the indirection not as the trade-off, but as the point of OO. I think those are the examples that people who are extremely jaded by OO have been exposed to: layers upon layers of indirection without a point. Indirection for indirection's sake.

And so they say that this is all BS and you should just not use OO. And they have a point, though they are not correct. Good OO developers handle this tradeoff by getting the benefits of OO with the minimum amount of indirection needed. Tooling like that found in modern Smalltalk systems can help you interact with the OO system that is not visible in the program text.

My approach to the tradeoff is to remove the indirection in the program text by making it possible to directly express components, connectors and systems in the program text, rather than having to build them all procedurally.

https://objective.st

> so the program we write is a meta program that constructs the OO system procedurally. The system is not visible in the program text, it is created as a side effect of running the procedures and remains invisible,

Great way of stating it! Most people who cargo-cult "OO is bad" don't get this.

> a good OO system will, by necessity, be highly indirect compared to the program text. A good OO system will also have sufficient benefits that this trade-off is very much worthwhile,

Very true. This is the reason OOD/OOP has been a great success that has led to the explosion of software that we take for granted today.

> My approach to the tradeoff is to remove the indirection in the program text by making it possible to directly express components, connectors and systems in the program text, rather than having to build them all procedurally.

At language source level (eg. DSL) or binary component level (needs runtime support a la COM) ?

> Most people who cargo-cult "OO is bad" don't get this [that OO programs are meta programs that build the system].

Alas, many people who advocate OO don't get this either, and in particular they don't see this as a problem to be solved.

Having to do things indirectly is not a good state of affairs. See "goto statement considered harmful". [1]

It is similar to the way we had to work with text editors made for printing terminals: "...requires a mental skill like that of blindfold chess; the user must keep a mental image of the text he is editing, which he cannot easily see, and calculate how each of his editing command `moves' changes it." [2]

> OOD/OOP has been a great success that has led to the explosion of software that we take for granted today.

Yes, people forget that the problems we are now having are the ones that are due to OO success.

> At language source level (eg. DSL) or binary component level (needs runtime support a la COM)

Language level. At the systems level we know how to build these types of system (COM, Smalltalk, Objective-C, Unix pipes and filter, REST, notification systems, ...), what we lack is the ability to express them in the program text: https://objective.st/

[1] https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.p...

[2] https://www.gnu.org/software/emacs/emacs-paper.html

> Having to do things indirectly is not a good state of affairs.

One key point to note here is that "Indirection" is often the mechanism used to design and express an "Abstraction". Given that Abstraction is the key to taming complexity and building large Systems they often go together i.e. Indirection becomes a key element in the design of Abstractions. It is only the non-designer of the Abstraction/Indirection who finds it hard to understand the System in the absence of Documentation/Communication.

Yes and no.

Yes, indirection in the source "abstraction" is the way to get to a new abstraction.

However, the result has to be an actual abstraction for that to work, and it often isn't. Often it's just indirection. And once you have the new abstraction, you have to be able to express yourself using that abstraction with little or no leakage.

For example, the "procedure" abstraction works that way, we really and truly don't have to care how it is constructed from assembly language instructions roughly 99.999% of the time.

But here's the kicker: since the actual abstraction mechanism in our languages is procedural, we can only create essentially procedural abstractions. For all other kinds of abstractions, the leakage is close to 100% and we are left with just indirection.

In the code.

Which means we need to take our abstractions and hand-compile them to fit our procedural languages, which we do with varying degrees of deftness. And then mechanisms of communicating the actual but mostly implicit "source" program become crucial, as you point out.

I'd rather be able to create and express those abstractions in the code itself. And then be able to program with those abstractions, rather than having to program in the target language of the human compiler.

So what are the benefits? (I'm assuming you mean benefits to Smalltalk, not Java.)