Message Oriented Programming
spin.atomicobject.com
spin.atomicobject.com
Rank 1: Polymorphism. You can "send" a message to an object. You don't know or care exactly what the object does. Other than the polymorphism, the "message" behaves just like a function call. It will definitely be handled by your target object, and it will definitely return instantly with a response. The compiler might even be able to inline this function call.
As seen in: Pretty much every OOP language.
Rank 2: Messages as first-class values. It's possible to write a function that forwards all incoming messages to another object, based on some logic. The caller does not know what will happen to the message. However, the message can be expected to be handled instantly, and it may respond instantly (if it does have a response).
As seen in: Objective-C, Smalltalk
Rank 3: Asynchronous messaging. When sending an outgoing message, it might be placed in a queue and handled at a later date. The message does not return a result instantly, so agents must have some other mechanism (such as including a "reply to" address) to be able to talk back and forth. From the perspective of the caller, it's a bit like putting a message in a bottle and watching it drift off to sea.
As seen in: Erlang, message queueing libraries.
There are several others that support this though... Python and JavaScript spring to mind.
C++, for example, has no equivalent language facility for these scenarios; in fact they're nonsensical since they would both fail to compile.
You could build a similar system for C++ by making every object inherit from some base class that has a method performMethod( method, params) and replace all C++ method calls with your modified calls; but you're building a facility from scratch that comes out-of-the-box on Objective-C.
One thing people usually understand as part of "message passing" is "no shared state". How/where do you fit that in?
Good question, it seems like all definitions of message passing involve not sharing state. Even OOP emphasizes data hiding as a core practice.
When "passing a message" is a heavier operation syntactically than "calling a function" is, one thinks of the two as being more fundamentally different than they really are. I find that interesting because it's superficial yet influential.
Do Erlang programmers think of function calls as a kind of message passing? or as totally different things? How far apart are the two, psychologically? Is sync vs. async the more fundamental distinction?
Syntactic difference is big, but neither function call nor message send are heavy:
func({my, params, in, a tuple})
proc ! {my, params, in, a tuple}
The difference is that function call returns something, message send just happens and we have no guarantee at all what is going to happen with the message.We frequently write functions which send message and wait for reply for a certain amount of time, and then return this reply or error if no reply was sent.
So, in Erlang there is - I think - huge difference between functions and messages, but that is because it's functions are just that: functions.
The situation is quite different in Smalltalk, where you have no functions at all, only objects. Everything there already is a message being passed, and so the difference between asynchronous and synchronous message should be very minor. I don't know Smalltalk well enough, but I suspect there are libraries implementing async message passing in Smalltalk and that they are almost indistinguishable from normal Smalltalk code, if at all.
But this seems to confuse paulhodge's #2 and #3. Messages as first-class values don't give you asynchronous messaging for free. Or do you just mean that syntactically the async code would look like normal sync code? That's true of JS as well, of course, and it's a problem. Async vs. sync is a fundamental distinction for the programmer, and one wants help to keep track of what's going on. I suspect Erlang got it very right in having two lightweight but distinct notations for these two deeply distinct things. What other languages do that?
Edit: It occurred to me that you said something profound:
> For me, in Erlang code, function call is about 'here', while sending a message is about 'there'.
"Here" vs. "there" is a spatial distinction; "sync" vs. "async" is a temporal one. The temporal distinction is far harder to get one's (my) head around, perhaps because code itself is laid out spatially, so you constantly have to recreate its temporal model in your head when you read it, and that's taxing. It's far easier to think of code as divided up spatially. We build up a system by making repeated 'inner' vs 'outer' distinctions - i.e. modularity. That structure is static while the temporal structure is dynamic and unpredictable. To write good async code you have to get in the habit of thinking "who knows when". But you never have to think "who knows where". The code tells you where.
This makes me think that there is wisdom in Erlang's decision to identify the temporal distinction (sync vs. async) with a spatial one (inside a process vs. outside it) — thus guaranteeing a translation from the harder mental category to the easier one — and to provide distinct notations for there-and-async vs. here-and-sync, so you always know which is which. Total complexity seems greatly reduced this way compared to a model in which the two distinctions are orthogonal and can combine in arbitrary ways.
For Erlang to say that between objects (i.e. processes) things are async and pass messages, while within an object they are sync and call functions, is a major departure from the Smalltalkian "everything is the same everywhere" small-and-regular philosophy. I'm fond of small-and-regular designs, but sync vs. async is one of those distinctions that is so fundamental, it's folly not to have it in the core unless you intend to get away with pretending that everything is always synchronous.
MOP has upfront costs that you do not have to pay using OOP if your software system remains reasonably small. Many software systems start out with the limited goals that suggest it would not be worth the effort to implement a MOP architecture. As an aside, this partly a reflection of the fact that our software tools for OOP are much better than our software tools for MOP. A good MOP implementation still requires rolling a lot of your own infrastructure components.
However, MOP architectures scale much better than OOP architectures if you need them to. The clarity of resource boundaries implicit in MOP architectures eliminate a lot of coordination and decouple nominal dependencies. Even if you start out building a MOP design on a single computer, where every core has its own process and set of resources, the design leap to putting those components on different hardware or different computers is relatively small. The interface is the same, only the latency changes, and there are many methods for making that abstraction efficiently scale this way. This is the reason large-scale parallel and distributed computing systems are all based on message-oriented architectures.
Scalability is only one benefit. Testability is another. And my favorite, it's very easy and usually safe to do run-time hacks, as the need arises.
I am currently working on a wide-scale, multi-language MOP family of libraries that I hope will make this programming paradigm a lot more accessible.
"OOP, defined in the purest sense, is implemented by sending messages to objects." - http://www.inf.ufsc.br/poo/smalltalk/ibm/tutorial/oop.html
For varying reasons, people focused on inheritance. In my opinion, inheritance is bad (at least the over-use of).
That's not a criticism of Alan Kay. It's an observation that his saying a thing a long time ago didn't and doesn't change what actually was created, and what OO is today is not message passing.
The very, very core of what we call OO today, the feature without which you can not call yourself OO, is the binding together of a structure with associated "methods" for operating on it into a single unit. It's a way of structuring programs (note I do not say "language"; C can be programmed in OO, for instance) that chooses the OO answer to the Expression Problem: http://c2.com/cgi/wiki?ExpressionProblem There's other frippery... there's a LOT of other frippery, actually, tons and tons and tons... but that's the core.
It is not message passing. And the attempt to map one to the other is pretty klunky and generally lossy in both directions, another sign they really aren't the same thing. Alan Kay's description of message passing, when read in English rather than Smalltalk, always sounded a lot more like Erlang than Smalltalk to me, but I observe that Smalltalk is what he in fact created as the manifestation of his ideas, not Erlang. I think we can't ignore that fact.
We are only arguing pedantically about what OOP "means," and everyone has their own definition. Useless. My own definition associates OOP with object thinking, the deconstruction of your problem into interacting objects, and then the use of plumbing in your language that help you realize this deconstruction in a solution. What that plumbing is can vary greatly and involves some combination of methods, messaging, classes, interfaces traits, prototypes, constraints, behaviors, reactions, reflexes, patterns (beta style), state encapsulation, etc...
I like the idea of MOP, its like focusing on one aspect of the plumbing and fixating around it; I could never write a program using messages alone in my domain (like I couldn't really write a compiler using actors!). MOP and OOP are not orthogonal, they are describe completely different granularity.
And if you carefully read my post again, you'll see I didn't give a definition. I talked about the one element that I've seen that is common across all of them. I can name OO languages with no first-class support for inheritance, no classes, no interfaces, or any of the other things you name, but I can not name an OO language that does not have some first-class binding of a structure to the methods to operate on it, nor can I show you an OO program in a non-OO language that is missing that, because that's essentially a logical contradiction. That's the single core idea that is what OO is.
This dodges the "everybody has their own definition" problem entirely.
Message passing as a primary means of structuring your program and OO are incompatible. One's going to have to be meshed within the other. One's this fundamentally asynchronous, distributed way of programming, and one is an elaboration on structured programming. Someone's on top. You get the same thing between FP and OO; you can put OO in FP or you can put FP in OO (quite popular, Python/Ruby/etc. fit here), but one is going to have to be on top. They can't be peers, they have fundamentally different ideas about what is most important.
Incompatible or orthogonal? Message passing is primarily an issue of software architecture (using Garland's definition) while OOP is more of an issue of linguistic abstraction.
OOFP is definitely possible, like say Moby or OCAML. The distinction between OOP and FP is hardly as black and white as you think.
ThingLab is described by wikipedia as a programming environment implemented in SmallTalk. In both cases, I think you are describing environments to play around with user-created objects moreso than languages.
Do Sketchpad or ThingLab have grammars?
SketchPad is a language, just a very inexpressive one that is not targeted at traditional programmers. ThingLab defines new metaphors and such, programming in ThingLab is a distinct programming experience from Smalltalk. Heck, even Bad Piggies is defining an inexpressive language in the context of a game, or think scripting in LittleBigPlanet.
> They can't be peers, they have fundamentally different ideas about what is most important.
Actually no. Dan Ingalls made Smalltalk-80, which is probably the one you know. Kay never liked ST-80, but I'm not convinced Kay ever had a clear vision of what OO should be, only what it shouldn't. He knows enough to say he doesn't like anything that's available but why hasn't he just made a manifestation of his ideas? It's much easier to deal with "no, not like that, like this" then someone who just constantly says "no, that's not it either".
There were several previous versions of Smalltalk. Maybe he actually did make some of those. But they were dropped because they weren't powerful enough...
But I think it was clear before this. Message-passing between non-shared state actors is a fundamentally different animal than "traditional" shared-state programing, whereas what is commonly thought of as OOP (special method-call syntax, class-based coding) is just sugar on any other language without changing the way things work under the hood.
Certainly, using the word "object" was unfortunate because it distracted people whereas "message-passing" is more to the point, but if you see what it was supposed to achieve there really is only one thing it could mean.
More subtly, passing around objects at all couples the program to the object
system — the rules for looking up the objects’ data and behavior is an
implicit global context. If the modules communicate by passing around
self-contained textual data, or a simple structured format like JSON,
then they impose fewer assumptions on each other. Different parts can be
written using different platforms or languages, allowing access to far more
libraries. (They can also be on physically separate computers.)
I may be mis-reading this, but is the author advocating this sort of serialized message passing within local environments, not just between them?Passing around data bags within local systems seems kinda odd given they have to be deserialized and mapped to a local object anyway. At that point you introduce an overhead of converting objects in the sender context, sending the data bag, converting that message to a an object usable in the receiver context and reverse the process when the method returns.
If you are passing around literal values in strings, then this doesn't matter, but if you are passing around JSON in strings, you end up with a general container that probably has to be inspected and categorized which seems contrary to the whole point of the article.
This is like an American company opening offices in multiple foreign countries and then requiring english to be the only language that can be spoken in those offices.
I'm advocating breaking the system into modules with messaging between them, at a fairly course grain (i.e., between subsystems). Within the modules, do whatever you want, but I'm talking about decomposing a system into a service-oriented architecture, or multiple Erlang processes and applications, or Unix pipes, or whatever you want to call it. (Doing it at too fine a grain leads to lots of CPU churn from excess serialization, of course.)
JSON is a decent example of a neutral and lightweight protocol, but it's worth actually thinking long and hard about the shape those messages should take. (I prefer text or binary payloads, but I'm also doing embedded development and a real JSON library costs ROM.) Thinking hard about those interfaces/protocols between the pieces, and keeping them tight, is where the value comes from.
(Kind of a quick response because I'm at Clojure/Conj today, sorry if I'm missing part of your point.)
EDIT
Reading further, I guess it was the JSON bit that threw me off.
It seems that you'd want to have brokers at the edge of modules or in between them in this case. That's may seem architechty, but the reality is that you aren't coupling a module to any non native type representation. Objects go in, objects come out.
From Alan Kay, the inventor of Object-oriented programming:
> OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I’m not aware of them.[1]
[1] 2003. http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay...
It's a meditation on why Erlang feels more OO to me than (say) Java or C#.
I'm just pointing out how ridiculous it is that the actual father of object-oriented programming thinks that the only object-oriented languages are two which don't even fit this "new" definition!
http://varnull.adityamukerjee.net/post/32394239181/objects-p...
going meta for a bit...
When I see the number of comments here, I have optimism for the system that is distributing the important knowledge (the Internet and good online communities ( HN )). I don't think the ACM or any of the engineering related orgs are ahead of the curve on these things. Engineers need to share with engineers on this topic.
I just read the paper by Richard Gabriel on CLOS and Mixins. One of the tl;drs for that paper is that engineers are the driving most of the innovation in this field. (or at least as much as academia). This reinforces the point above.
In contrast, throughout the 80s,90s or even 00s, when I talked or asked about Smalltalk, Objects, and other interesting tech... I was usually told that those were failures. "Go with C++ or Java". Those languages are the very ones that made MOP and other interesting paradigms feel like you were going against the grain.
Even if you were following some usenet newsgroup that had good discussion. There was usually a bozo factor or too much religion (aka not much cross pollination)
So glad to be in the future and see positive discussion occurring!
... going un-meta
tl;dr - It is good to see people look at the existing paradigms with an open mind. just like functional programming. Overall the post linked to is not that interesting. It is the discussion in the comments here that is inspiring.
On a related note: I look forward to the new Intel Haswell architecture. Built in HW Transactional Memory!!! Hurray!
Slides from an ealier version of the talk here: http://www.slideshare.net/jamesalewis/java-microservices
link : https://plus.google.com/112678702228711889851/posts/eVeouesv...
Very good article by the way. Not very thorough, but that's what is good. It just remembered me about a state of enlightenment i have already felt, but forgotten since.
The biggest problem I have had so far is Java is just not as friendly for this kind of architecture compared to Scala.
My current work involves managing a range of different concurrency and multi-process systems. Focusing on clean, forgiving message channels as the foundation of the system has been a win in the last three very different problem spaces. Only thing missing is perhaps a nod to Communicating Sequential Processes.