Much of the confusion between "message passing" and "event based" has to do with architectural vs. implementation details. I have seen (and written) event driven systems that actually use OS provided messages for their implementation. I am guessing you are really referring to architectural ideas.
As many people have already pointed out "message passing" and "event based" aren't really good enough terms to avoid ambiguity.
What are the relative merits of a "message passing" system vs an "event based" system.
I'm going to start out by guessing that when you say a "message passing" system, you are talking about a system which one object spends a message to a specific other object. When I think of a system based based on this paradigm, I more generally think of a system where an object that detects something knows who needs to be told about something. (I'm not specifying how it knows, just that it knows.)
This type of architecture is very good for systems where the producers and consumers are well known. Either the producer of a message knows who must receive it, or the consumer must know from who to get the message from.
If you are writing a banking application, one would expect you really want to know who you are sending your transactions to and who they are coming from.
The other system I believe you are thinking about when you say an "event based" system is one where an object raises an "event" without knowing who (if anyone) will respond to it.
This type of event driven architecture is very good for systems where the producer does not care about who consumes the event or where the consumer doesn't really care about who produced the event.
In general, these systems are great where you do no know the relationship between consumers and producers, and where you expect the relationship to be dynamic.
One system I have used this in was a system where the application was actually composed of dynamically configured modules (plug-ins) that were loaded at run time. When a module was loaded, it would register for the events it cared about. The result was a system in which it was very easy to extend the functionality.
For instance, let's say condition A raised Event EA which normally caused response RA. The object that caused response RA simply registered to receive event EA and acted on it when it arrived. Now, let's say we want to add a new response to EA, called RA_1. To do this, we simply add a new object that looks for EA and generates response RA_1.
Here are a couple of examples (using your terminology):
- "message passing": Your boss tells you to fill out your time sheet.
- "event driven": The department secretary sends out an email to
everyone reminding them that their time sheets are due today.