Savas, Chris, Jacek have a side-threadgoing about MEST and message-passing (ignore the pub/sub thing, that's a different matter). What's been most interesting about these threads have been the comments they've attracted. There are two themes which these comments are strung out along: that message-passing and procedure calls are equivalent; and that ProcessMessage is too low-level. Both of these are inaccurate and unhelpful:
Message-passing is the same thing as procedure calls.
Certainly most distributed computing platforms (including older Web Services platforms) have abstracted away the passing of messages across the network and the associated marshalling/unmarshalling of message content into parameters for procedure calls, on the understanding that such abstraction is useful since it hides a whole bunch of boring and error-prone stuff away from the developer. We've gotten away with this because our distributed applications to-date haven't been really large scale. If you've a fast, reliable, low latency network then you can get away with making remote objects look like local objects because they pretty much are. Now OK, we all know from Waldo et al's seminal paper that we probably shouldn't do this, but it works so we do.
This house of cards collapses when we start thinking about applications that span arbitrary domains. The networks are latent, messages get lost, transmission speed is variable, and asynchronous delivery of messages is normal. What, for instance, should happen when a message gets lost somewhere on the Internet? Does my RPC stub dutifully sit and wait, perhaps timing out later? What if the remote service that I'm interacting with crashes - how does my RPC facade tell me that and let me sort things out gracefully? It doesn't - RPC is a terrible metaphor for larger-than-intranet scale distributed computing. And don't get me going on "you can throw a MessageLostException..."
The fact of the matter is that a service implementation can only be resilient to such failures if it is developed specifically to deal with them. RPC sweeps everything under the rug, and leaves us believing that WS-InsertYourFlavourOfReliableMessagingHere will smooth out the lumps (it will usually, but eventually something will happen which it can't deal with, and we're back to square one - services that aren't tolerant of their deployment environment). Focussing on messages rather than procedure calls is a fine way to conceptualise and build services which are able to deal with the truth on the wire. The truth is ugly, messy, tempremental, and a pain - but it must be dealt with not ignored.
ProcessMessage is too Low-Level
The MEST architectural style advocates dealing with the truth on the wire by promoting messages to be first-class citizens in the architecture, and in the implementation. Service implementations don't use stubs to "invoke" other services, they use programmatic representations of messages as their communication mechanism (see this PowerPoint presentation for more details). This approach yields a bunch of good stuff:
- A degree of decoupling from its consumers since as long as the right messages go up and down its stack everything is fine - there's no need to even worry about what's going on outside of the service boundaries;
- Services are made robust since the truth has to be dealt with explicitly by developers who are dealing directly with the sending and receiving of messages - messages aren't hidden in stubs and skeletons anymore, the SOAP processing model is embraced by service implementations.
Certainly there's a trade-off here. To work at a lower level of abstraction (at least in the absence of tools which can automate this pattern), is harder work. To think in terms of message exchanges and partial failures and all the other nasty gotchas of distributed computing, and to design solutions which are graceful in their presence is also hard. But isn't this effort worthwhile?
To paraphrase, "You want loose-coupling? Well loose-coupling costs, and here's where you start paying - in code."