The Message Bus pattern is a pattern of enterprise application architecture that deals with the integration of systems. It consists of several components that facilitate the exchange of messages between the various systems in order to achieve some shared purpose. When done properly, messaging is one of the lowest forms of coupling that can be achieved in a software system. For this reason, it has become commonplace to use a message bus to decouple the components within a single logical application as well. This use of the message bus pattern is so specialized that it is worthy of its own pattern name: the application bus.
What is a message bus?
A message bus is a component that enables systems to communicate (often asynchronously) by passing messages indirectly to one another. Examples of true message buses are NServiceBus, Rhino Service Bus, MassTransit, MSMQ, etc. Note that these buses facilitate distributed communication across both logical and physical boundaries: messages may pass from process to process, from machine to machine, or perhaps even from network to network. Most buses support two-way, synchronous messaging, but they are more commonly used in a one-way, asynchronous way. Asynchronous one-way messaging can create systems that are a bit harder to understand (at least at first), but they are typically easier to scale, and they are easier to maintain due to the decrease in coupling (message passing is one of the lowest forms of coupling that can be achieved).
A recent trend, especially in the .NET community, is to custom build smaller-scale buses that facilitate the exchange of messages within a process boundary. Instead of passing messages from system to system, buses are being used to pass messages from one instance of a class to another. A common example may look something like this:
//Classes send messages to the bus through this interface...
public interface IBus
/// Sends a message that doesn't require a response.
/// <param name="message"></param>
/// <typeparam name="TMessage"></typeparam>
void Send<TMessage>(TMessage message);
/// Sends a message and gets the reply.
/// <typeparam name="TRequest"></typeparam>
/// <typeparam name="TReply"></typeparam>
/// <param name="request"></param>
TReply RequestReply<TRequest, TReply>(TRequest request);
//Consumers implement one of these interfaces and are automatically
//registered with the bus, who then sends messages to the implementor
//as they arrive.
public interface IOneWayHandler<in TMessage>
void Handle(TMessage message);
public interface ITwoWayHandler<in TRequest, out TReply>
TReply Handle(TRequest request);
It is this later use that has become so specialized that it warrants its own pattern. Unlike a typical message bus, these small-scale application buses often only support two-way, synchronous messaging and do not support sending messages across logical or physical boundaries. They are often implemented by leveraging the capabilities of Inversion of Control (IoC) frameworks such as StructureMap or Ninject. There are two consumers of the application bus’s services: message publishers, who create and send messages to the bus, and message consumers, who subscribe to handle messages based on message type. This subscription is often handled by conventions configured through the IoC container.
The Pattern, Defined
In order to be a true Software Design Pattern, the design pattern must meet a few requirements: it must solve a common design problem, it must be generally reusable, and it must be defined so as to be transformed easily into code. The application bus definitely meets these requirements:
Problem: An application contains many classes that need to work together cohesively to achieve a shared goal. How can these classes work together without succumbing to coupling problems?
Solution: Create an application service that enables the classes to work together by exchanging messages.
In the next post, I’ll show you how I implemented the application bus that powers the social networking application called RageFeed.