Wednesday, April 2, 2008

Avoid Command Messages

According to Hohpe and Wolfe in their book Enterprise Integration Patterns, they state that there are three basic types of messages at a semantic level - command messages, document messages, and event messages.

When discriminating between these message types, we are concerned with the semantics of the message name. So for example, a CancelPolicyRequest message is a command message, as it is instructing the service to cancel a policy. A Policy message is a document message, as it contains information about a business document without any context as to what should be done when it is received. And a PolicyCancelledNotification message is an event message as it informs the receiving service that a policy was cancelled, but does not specify what action the receiving service should take in response to the event.

Although command messages do not constitute an RPC interaction, they introduce coupling between services where the other two message types do not. When Service A sends a command message to Service B, Service A is making a decision on behalf of Service B as to what Service B should do in the context of Service A's activities.

The fact that Service A is instructing Service B what to do means that Service A determines what shall be done, whereas Service B decides how it shall be done. This is a subtle but important form of coupling.

Because Service B is performing an operation for Service A, as Service A evolves we may find that Service B is no longer able to meet the needs of Service A. Now we must update Service B due to a change in the needs of Service A. This is the essence of coupling.

The root of the problem here is that Service B's behaviour is being governed by Service A. Service A is making an assumption regarding Service B's behaviour, introducing a dependency.

Moreover, Service B cannot make up its own mind what to do in response to Service A's activities, it must be instructed by Service A.

Consider the case where Service C now must perform some action in the context of Service A's activities. We now need to update Service A to send a command message to Service C as well. Imagine how the complexity here can grow when we have a large number of services!

The solution is to use message types that do not involve instructing a service how to behave. This leaves us with the document and event message types. The document message type tends to appear mostly with the REST style of architecture (which I will discuss in a future post).

With SOA, the preference is to use event messages. In the previous example, Service A would publish an event (such as InvoicePastDueNotification) to which Service B would be subscribed. Upon receipt of the notification, Service B would then make the decision locally as to how to respond to this event; in this case, cancelling the policy. Service B would then very likely publish a PolicyCancelledNotification message, in case other services needed to respond in some way to this event. If the need arose in the future for Service B to respond differently, this would involve only a change in Service B.

If Service C then needed to perform some action (say claw back commissions) in response to the InvoicePastDueNotification message published by Service A, we would simply need to subscribe Service C to the relevant event topic, and then update Service C to behave as needed. Again we have not needed to make a change in Service A.

Here we can see a business workflow occurring that spans multiple services, where the decisions as to how each service contributes to the process are handled locally within each service.

As always however there is a catch. What if in order for Service B to decide how to respond to the event published by Service A, there is insufficient data in the event message? This would mean we would need to update Service A to include more data in the event message - once again we have coupling.

As such, we need to be careful when designing our event messages such that all relevant information regarding the event is included in the message. The needs of the subscribers are not known in advance, so we cannot just include the minimum information in the event message to satisfy the existing intended subscribers.

So in conclusion, prefer the use of event messages over command messages at the service boundary where possible; but take care in the design of your event messages to make sure all relevant information is included.

3 comments:

Robert said...

Consider the example where the user, via a web UI looks at his policy and decides to cancel it by clicking the Cancel Policy button.

This seems like a textbook case where a command message would apply.

Your thoughts.

Bill said...

Hi Robert,

In this particular example your service has a Web UI, which means that clicking the Cancel Policy button may not actually involve sending a message to a back end component. The Web application may handle the button click entirely itself locally.

However in the case where you have a separate UI tier (such as with a smart client application), you ineed would need to send a command message to the application tier housing your business logic.

Note however that the application tier is housing distributed components, not business services.

The boundary of a business service contains the back end components, the user interface and the users.

As such, the endpoint that receives the command message is not on the public service contract. It should not be used by any other services. It exists only to serve the UI tier within that business service.

This is described in more detail here.

Bill

Colin Jack said...

Newcomer to your blog and really enjoying it. Got two comments:

"The document message type tends to appear mostly with the REST style of architecture (which I will discuss in a future post)."

Do you mean in terms of PUT, be very interested in reading more on your views on this.


"As such, we need to be careful when designing our event messages such that all relevant information regarding the event is included in the message."

I've heard debates about this a few times, including around Jack van Hoof's blog posts and Steve Jones' ideas (http://service-architecture.blogspot.com/2006/08/single-canonical-form-not-for-soa.html). Be very interested in reading more about this topic anyway.