Asynchronous Message Exchange Pattern Terminology

In software development, it can be quite difficult to give a good name to a component or coding artefact (such as a variable, method or class).

If you do not intentionally put effort into searching for a good name, then you are probably increasing technical debt and ongoing maintenance pain with terminology that causes confusion for other developers - or for yourself the following day when your memory has faded!

A good name for a coding artefact typically fulfils the following criteria:

  • is as simple as possible;
  • is descriptive and intention revealing - it conveys the purpose or [single] responsibility of the artefact;
  • clearly differentiates its purpose from other artefacts;
  • is intuitive for other team members to understand; and
  • uses the accepted, ubiquitous terminology of the domain.

The last thing anyone wants is to be confused by a name that is ambiguous and overlaps with or overloads the name of other artefacts.

Deficiencies in the expressiveness of the English language itself can be a common cause of the difficulties we have. For instance, the Greek language distinguishes between at least four different ways of describing the one English word for “love”. Take that you imprecise and insufficient English language!

And so now we come to the word “asynchronous” when describing service call and message exchange patterns. Within the world of software, and especially in the integration, messaging or service-oriented architecture space, the word “asynchronous” is too overloaded.

Below is a list of the different types or usages of the word “asynchronous” that I am commonly communicating about and distinguishing between:

  1. A client can perform an asynchronous, non-blocking call to a service operation - e.g. from a background thread.
  2. A service operation may be called synchronously from a client, but the operation may return a response early to the caller and continue operating asynchronously in the background. For instance, this is possible with an Enterprise Service Bus / BizTalk orchestration.
  3. A service operation may be called synchronously from a client, but the client may perform the call using a synchronous-over-asynchronous messaging pattern. For instance, the client sends an asynchronous request message to a queue or service bus. The client then subscribes and waits for a correlated response message. To the end user, the entire interaction appears synchronous, none the wiser that asynchronous messages were used instead of typical web service calls.
  4. There might be a requirement for a service operation to be invokable both synchronously via a web service endpoint and also asynchronously via a message placed on a queue or service bus.

The word “asynchronous” is insufficient to clearly describe and distinguish between each of the points above.

So, borrowing concepts from both BizTalk ports and Command and Query Separation (CQRS), I am currently satisfied with using the following terminology:

  • I only use the word “asynchronous” when a unit of work is performed in the background - where there is no caller waiting for a response message on the same channel it used to make the call in the first place. Please note that there is a difference between a response message and the ACK/NACK that is returned to the caller to acknowledge successful receipt (or not) of the message.
  • A “Publish Message Command” pattern - where a caller sends/publishes a message to a queue or message bus and there may be multiple subscribers listening for that message.
  • A “One-Way [Asynchronous] Command” pattern - where a caller sends a message to a queue or message bus, and a unit of work is performed in the background.
  • A “One-Way [Asynchronous] Command with an Asynchronous Response” pattern (also known as a “Synchronous-over-Asynchronous Command / Query”) - where a caller sends a message to a queue or message bus and also subscribes to a corresponding/correlated response message that it waits for. Meanwhile, a unit of work is performed in the background and that unit of work publishes the corresponding/correlated response message to be received by the waiting original caller.

The terminology “One-Way” explicitly refers to the endpoint receiving a request and never sending a response message back to the caller (once again, the ACK/NACK is not considered a response message).

“Two-Way” however explicitly refers to the service endpoint receiving a request message and the service returning a response message back to the caller.

If we were to extend a similar style of terminology into the world of synchronous patterns, we would have:

  • A “Two-Way Command” pattern for a synchronous service operation - where the caller waits for a response; and
  • A “Two-Way Query” pattern for a synchronous service operation that is typically read only with no side effects (except perhaps for writing security audits).

To make things more interesting, different technologies may enable or prevent certain patterns from being implemented. For instance, in .NET, a “One-Way [Synchronous] Command” pattern can be implemented in WCF. In this case, the .NET method signature would have a “void” return type, operate synchronously and then at the end of the operation would return the typical ACK/NACK. This communication pattern however is not applicable in the world of BizTalk.

This WCF version of a “One-Way [Synchronous] Command” pattern is the only reason why I included the text “[Asynchronous]” in the name of the One-Way asynchronous patterns above - in order to clearly differentiate between them.

With this terminology, I have found that I can more quickly and clearly discuss message exchange patterns with my team. I hope it does the same for you!

Thoughts on the Naming of SOA Services and Operations

Recently I was having some discussions on the naming of Service-Oriented Architecture (SOA) services and their operations. There were some differing opinions on the length of the names and concerns about the duplication of some words in both the service name and operation names.

Naming Principles

As a general set of principles, I prefer to use names that are: intuitive, understandable, more readable in typical English, discoverable and allow for extensibility.

Microsoft has some useful naming conventions and guidelines for .NET that are reasonably mature and generally can be applied to SOA service names.

Service Names

As an example, let us assume that in a domain we have products/stock/inventory that is acquired and sold. We could say that there should be a service for the management of inventory items.

We therefore could propose an “Inventory Management” service to record the addition and removal of stock. A valid alternative name also could be “Inventory” service. “Inventory” as a service name obviously is shorter than “Inventory Management”. So is that better?

One could at this point perhaps flip a coin and naively settle on either option. But I wouldn’t recommend that…

Do those service names comply with the above-stated principles? Maybe - it depends on the domain.

Let me now give you some more possible information about the domain. When inventory is sold or moved to another department, there are typically corresponding accounting entries that need to be recorded. We therefore could propose an “Inventory Movement” service to encapsulate this.

So now in this domain, we optionally could have the following:

  1. “Inventory” and “Inventory Movement” services, or
  2. “Inventory Management” and “Inventory Movement” services.

For me, seeing the juxtaposition of both service names in option (1) makes me feel uneasy, highlights ambiguity and causes me confusion. Since there is “Inventory Movement”, what is the role of “Inventory”?

Additionally, “Inventory” sounds very much like a data entity that one might perform CRUD operations on - as opposed to a Business Service.

Option (2) however is more intuitive, less ambiguous and causes me less confusion. “Inventory Management” intuitively sounds like it could be related to the management of inventory items (whatever that may be…). Overall for me, this makes more common sense than option (1).

So now, if you agree, we can see that the more specific service name of “Inventory Management” (even though it is longer and slightly more annoying to repeatedly type) better allows for business changes within a domain. In other words, more specific service names allow for future extensibility of the domain with less ambiguity. Having said this, we do need to remain vigilant and be careful that we are not overtly specific with our service names such that we make our services to narrowly focused…

Ok, let’s now look at the operation names.

Operation Names

As an example, let us assume that we have an “Order Management” service. In this service we need to have operations for adding new orders to the system. We might therefore have an operation named “Add Order”. Alternatively, we could have an operation just named “Add”. “Add” is obviously shorter than “Add Order”, and does not repeat the word “Order” - which you know from the service name. So is that better?

One could at this point perhaps flip a coin and naively settle on either option. But I wouldn’t recommend that…

Do those operation names comply with the above-stated principles? Maybe - it depends on the service.

Let me now give you some more possible information about the service. Existing orders may need to be adjusted. In fact, there might be a need to add new order items to an existing order. We therefore could propose another operation named “Add Order Item” or “Add Item”.

So now in this service, we optionally could have the following:

  1. “Add” and “Add Item” operations, or
  2. “Add Order” and “Add Order Item” operations.

Again, for me, seeing the juxtaposition of both operations names in option (1) makes me feel uneasy, highlights ambiguity and causes me confusion. Since there is “Add Item”, what does the operation “Add” actually add?

Option (2) however is more intuitive, less ambiguous and causes me less confusion. Overall for me, this makes more common sense than option (1), and provides extensibility to allow for other operations in the future with less ambiguity.

Summary

I recommend erring on the safe side and selecting names that remain intuitive when taken out of the context of its grouping/category, and be carefully explicit with names - because you don’t know how the business is going to change and how that could affect the domain. This is especially true if your team is operating in an agile fashion and developing and evolving the services and operations as you go.

The length of names and duplication of words in operation and service names should be less of a concern than using names that are intuitive and allow for change with less ambiguity. If you are not explicit enough, then you increase the risk of future services or operations making your existing names ambiguous. Alternatively, if you are too explicit, you could narrow the scope too much and reduce extensibility in other ways.