Temporal and Behavioural Coupling

April 27th, 2009  |  Published in REST, SOA by Ian Robinson  |  13 Comments

I’ve many times worked with developers and architects to help them understand the nature and implications of their distributed systems design choices. One of the ways I’ve found of framing a useful discussion is to look at coupling issues – particularly those arising as a result of temporal and behavioural coupling.

Every apostate technician on his or her descent to whiteboard irrelevancy ought produce at least one “magic quadrant” diagram. This is mine: the coupling matrix. Whilst sadly not a career-making architectural silver bullet, this diagram may help you characterize the several parts of your extant solutions, envision direction for future initiatives, and understand the constraints – both legitimate and inadvertent – that in part determine the design options available to you.

Temporal and behavioural coupling

First, a brief overview of these two types of coupling:

Temporal coupling

Temporal coupling refers to the degree to which the sending and handling of a message are connected in time. If a sender is dependent on a receiver being available when a message is sent, we have high temporal coupling: if the provider is not available, the interaction fails. Processes whose activities are strictly ordered or whose results carry forward, leaving subsequent activities unable to start until a response to a prior request has been received, are similarly temporally coupled. In situations of high temporal coupling, the time taken to handle the message and return a response increases the processing time on the sender side.

Behavioral coupling

Behavioral coupling refers to the degree to which parties share assumptions regarding behaviors, more specifically, to the implications of assigning the twin responsibilities for determining what action to execute and how to execute that action to the parties in a distributed interaction. In systems that exhibit an extremely high degree of behavioral coupling, the sender of a message determines what to do, and also knows something of how the receiver ought satisfy its request. Such coupling is typically evinced by, for example, database foreign keys and/or platform-dependent artifacts such as collection types leaking into messages and operations. If a sender determines what to do, and a receiver determines how to satisfy the sender’s request, the participants similarly exhibit a high degree of behavioral coupling. If a receiver alone determines both what to do and how to do it in reaction to a received message, the sender and receiver have low behavioral coupling. High behavioral coupling requires a provider to evolve its service offerings in response to changed consumer requirements.

And then some sketchy characterizations of each of the quadrants:

Distributed 3-layer

Traditional 3-layer application architecture blown up to distributed proportions. Characterized by call stack-like, imperative behaviour (high temporal and behavioural coupling) and synchronous request-response interactions. Includes systems that layer synchronous interactions on top of asynchronous message exchanges. Senders tell receivers what to do; receivers execute the sender’s orders. Sender and all intermediaries block until the call stack unwinds, effectively locking and/or consuming system resources further up the call chain. This blocking behaviour undermines the autonomy of upstream components and at the same time increases the availability requirements of downstream components. As Michael Nygard’s Release It! reminds us, in these circumstances the availability of the overall system can be no more than that of the least available participant, and the probability of failure is the joint probability of failure in any component or service.

Command-oriented

“Good”, “orthodox” SOA. Low degree of temporal coupling characterised by asynchronous interactions, deferred state and a resumable programming model (process or activity instances are dehydrated between remote invocations in order to conserve resources, and then rehydrated based on correlated responses). Senders typically determine what needs to be done, but rely on receivers to determine how to execute their instructions. This behavioural coupling can require providers to evolve (message formats, supported operations) in lockstep with changing consumer demands.

Event-oriented

Low temporal and behavioural coupling. Receivers determine both what needs to be done and how to do it based on the content of received messages. Resumable programming model: processes are suspended or dehydrated, waiting for events. Can be difficult to trace the execution path of an end-to-end transaction or activity. Exposing an ExtinguishFire operation is a command-oriented way of executing a business process; acting on FireStarted notifications an event-oriented approach.

Emergency services

So called because you tell them what happened, and they decide what to do, but if there’s no one to take your call, you’re hosed. Low behavioural coupling, which allows for the independent evolution of system components, but a degree of temporal coupling, impacting availability requirements of participants. Many RESTful solutions occupy this quadrant. URI-templated solutions have a higher degree of behavioural coupling than hypermedia-driven solutions (where servers constrain and guide what a client can do next, and determine how best to satisfy requests); client polling and caching can mitigate some of these temporal coupling issues.

Endnote

These coupling issues are well understood by many developers and architects – to the extent they comprise a general base of knowledge without specific authority or provenance. I would, however, like to draw your attention to one of very many excellent posts by Bill Poole, Avoid Command Messages, that some time ago helped bring behavioural coupling into focus for me.

13 Comments  |  Atom   RSS 2.0   Email

Responses

  1. Thomas Rischbeck says:

    April 27th, 2009 at 2:57 pm (#)

    Hi Ian, I love your first stab at a magic quadrant! And i’m also a enthusiastic follower of Bill Poole’s blog. Unfortunately, most architectures I encounter are in the lower-left (“distributed 3-layer”) quadrant — using command messages with RPC semantics. I still think that this is a fault of the tools (that laud the “your preferred language” –> WSDL translation tool as a feature).

    I’ve once worked on a large SOA that was built completely around asynchronous, reliable messaging between services. More details here: http://thomasrischbeck.blogspot.com/2009/04/soa-based-on-asynchronous-reliable.html

  2. Jean-Jacques Dubray says:

    April 27th, 2009 at 8:33 pm (#)

    Ian,

    I am a bit skeptical of general comments such as “Avoid Command Messages” taken completely out of context. If you are in an EAI context, where a system of record “talks” directly to another system of record, I would generally agree. EAI, which heavily relies on synchronization and replication interactions, has long avoided using command messages for that purpose.

    If you are in a “Composite Application” context with a well defined service interface (independent of the systems of record that will be impacted by the command request), I am a bit more negative to this type of recommendation. As we have talked last year, what most people don’t take into account is the lifecycle of resources and a command here is simply a request for the policy (resource) to transition from “active” to “canceled”. This command could result in many interactions with different systems of record as well as a message event “Policy Canceled”, which might be consumed by other resources that need to align their state with the one of the policy.

    At this point, I am not sure why developers and architects are always finding a way to avoid surfacing resource lifecycles and the corresponding actions that enable transitions from one state to another. Making resource lifecycles and the corresponding actions explicit is by far the single most important factor that our industry could come up with to dramatically improve developer productivity and business agility.

    Isn’t what HATEOAS is all about? And even there, people would rather CRUD than making resource lifecycles and actions explicit.

  3. Saul Caganoff says:

    April 28th, 2009 at 1:07 pm (#)

    Hi Ian, I too run into an awful lot of tightly coupled n-tier applications which are mistakenly labeled “service-oriented”. I therefore appreciate your use of coupling “dimensions” to help people understand the consequences of their architectural choices.

    But I started wondering where document-oriented messages fit into your diagram. The answer is longer than can fit in this comment, so I wrote about it here.

  4. iansrobinson says:

    April 28th, 2009 at 9:09 pm (#)

    Hi Jean-Jacques

    Thank you very much for your comments.

    I’d be tempted to generalize your wariness of comments that lack context: advice, guidance and critical thought always has a context – it’s perhaps part of our mutual responsibility to the technical community to surface that context, rather than suppress it in favour of “golden rule” pronouncements.

    (I’d note that Bill Poole’s advice regarding not using command messages isn’t without nuance or contextual understanding: he qualifies his advice here: http://bill-poole.blogspot.com/2008/04/when-event-messages-are-not-ideal.html)

    Oddly enough, my notes for a follow up post discussing how one might use such a simple matrix as the one described in this post emphasize the importance of context. One can, for example, assign individual interactions, services, even entire systems, to some place on the diagram so as better to understand the context – that set of intrinsic and accidental constraints – that has driven design decisions and led us to wherever we are today. By separating out more or less intrinsic constraints – the business environment at large, incumbent platform and infrastructure constraints, business process invariants – from the accidental – poor design decisions, for example – we might better understand what opportunities are available to us for improving our lot, where improvement would come down to reducing coupling along one or both axes. Of course, the opportunities available to us for reducing, say, temporal coupling in this or that instance must be contextualized with reference to our business goals, any identified risks and threats, and the effort and costs involved in realizing such opportunities.

    One of the ways I choose between a command and an event semantic for any particular interaction is to take the consumer or client point of view and ask: does the proposed provider activity contribute an invariant to this client or consumer activity? If I promise that in the course of executing some activity customer policies will be cancelled, I as a consumer of some policy canceling functionality might wish to issue a CancelPolicy command, rather than trust than one of an anonymous group of event listeners will execute the necessary action on my behalf. On the other hand, incidental activities that don’t contribute to the contract I offer my clients are more readily amenable to event-driven semantics.

    As for surfacing resource lifecycles and the capabilities or actions that transition a resource through its lifecycle: I’m very much in favour of this approach. (Soliciting agreement and finding opportunity when faced with the immediate constraints of an incumbent “architecture” is another matter…) My understanding is that you’d prefer these semantics to be first-class constructs of a distributed programming model: my experience has been of a rather more modest road that identifies such lifecycles and actions during analysis and seeks then to implement the same by projecting bounded context-specific representations of entities and operations onto service boundaries. In the absence of an explicit programming model, the integrity of the overall design is maintained in a relatively ad hoc fashion – through tests, lightweight documentation, and by way of a (fragile) oral culture.

    Kind regards

    ian

  5. Jean-Jacques Dubray says:

    April 30th, 2009 at 3:50 am (#)

    Ian:

    thanks for your response, I guess I am still bit uneasy about your recommendation for two reasons:
    a) As I understand it, you seem to assume that temporal and behavioral coupling is homogeneous over a given connected system or (large) parts of the system (SOA, EDA, 3-tier are nearly exclusive architectures). If I agree that it is important to consider temporal and behavioral coupling when designing a particular interaction, you may admit that interactions, in a connected system are quite varied and all kinds of temporal and behavioral coupling might be represented and should be supported within the architecture of your connected system.

    b) If we consider that an event is the occurence of a state (I believe this is the official definition), once an action is executed (regardless of temporal coupling), a message event should follow to represent the occurence of the new state. In particular every occurence of a state should emit a message event.

    Then I would disagree with the content of this paragraph:

    “One of the ways I choose between a command and an event semantic … On the other hand, incidental activities that don’t contribute to the contract I offer my clients are more readily amenable to event-driven semantics”

    Actions and events are not chosen based on some temporal or behavioral rules: you invoke an action when you need to transition from one state to another and you publish an event to notify the occurence of a new state, regardless of temporal or behavioral coupling.

  6. Jean-Jacques Dubray says:

    April 30th, 2009 at 2:12 pm (#)

    I have added some comments here: http://www.ebpml.org/blog/190.htm

  7. iansrobinson says:

    April 30th, 2009 at 2:22 pm (#)

    Hi Saul

    Thanks for the comments and the follow-up post.

    The reason I didn’t include document-oriented messages on the matrix was because I was interested more in explaining two types of coupling than three types of message. I assigned the names “command-oriented” and “event-oriented” to two parts of the matrix so as to stereotype those quadrants, but these terms refer more to command- and event-oriented messaging, not message types. The distinction is perhaps subtle and not overly significant, but it may be worth pursuing a bit.

    Message type is a bit of a fluid beast. Command, document and event messages appear as such to us because we tend to interpret their semantic connotations with cheerful good faith:

    <ExtinguishFire>
        ...
    </ExtinguishFire>

    Command – surely.

    <FireStarted>
        ...
    </FireStarted>

    Event – no issues.

    But what about <T7EBE47A-34C6-11DE-9410-ACBE55D89593/> ?

    (There, I’ve wasted another GUID)

    A command message only succeeds if a service exhibits command messaging behaviour. This behaviour may very well be driven by the service interrogating some kind of contextual element, whether it be the root node name or the contents of a header (such as the WS-Addressing:Action header), but finally, we can only really say that the service has acted on our command if it exhibits the kind of behaviour we would expect to see as a result of our issuing a command. The result is in many ways more important than the form of the stimulus: “Is it cold in here?” (ostensibly a query) and “It’s gotten cold in here” (a notification/event) are, in certain contexts, commands or requests to close the window.

    Looked at from a messaging as opposed to message type perspective, the issue comes down to expectations/intent and behaviour/results. This allows us to say that system X, for example, functions in an event-oriented manner, even though to our eyes its messages look more like commands. (We might also say that it also exhibits a high degree of semantic/behavioural dissonance – that it’s broken – but to the illiterate observer, the alien interloper who sees only opaque tokens, it’s the result that counts.)

    (I wrote this yesterday – oddly enough, my focus here on intent and exhibited behaviours somewhat confounds JJ’s claim that I do not “take into account the ability to decouple the contract from the implementation”.)

  8. Jean-Jacques Dubray says:

    April 30th, 2009 at 9:49 pm (#)

    Perhaps you could sort commands and events more cleaning by introducing the notion of “state”: asking to transition from one state to another is a command and reaching a particular state is an event.

    Your statement:
    >> the issue comes down to expectations/intent and
    >> behaviour/results.
    confirms the validity of my question, why would intent and achievement be related to temporal and behavioral coupling?

    In 3-tier architecture intents and achievements are private to the system (no other system can express an intent or “see” an achievement). Hence a synchronous exchange does the job since no other “connected” agent can be involved.

    However, in “connected systems” Intent and Achievement are complementary. They must be “open” and available to any agent in the connected system. The way a particular intent is implemented can exhibit a strong coupling with a given system of record or in a loosely coupled manner (pick your favorite LC technology). As I see it, the problem is the coupling between the system of record and the intent, not between the consumer and the intent. Advising people to establish very weak or unclear intent (i.e. it is only clear because of out-of-band agreement between the consumer and the system of record), is IMHO an anti-pattern.

  9. Herbjörn Wilhelmsen says:

    May 1st, 2009 at 12:11 pm (#)

    I wonder if you could describe in more detail the differences between Emergency services and other services. I don’t really get this kind of service. Your description
    “So called because you tell them what happened, and they decide what to do, but if there’s no one to take your call, you’re hosed.” Doesn’t really give me a clear picture in my head. It sounds like an event that may or may not have a subscriber?

    Also I think that JJ has a good point: Clearly stating intent tend to be a good thing.

    /Herbjörn

  10. Herbjörn Wilhelmsen says:

    May 1st, 2009 at 1:09 pm (#)

    Maybe JJ’s concerns around intent has to do with granularity of services. For Event-oriented services to work well they must be self-sufficient to such a degree that they do not need to express intent to another service.

    /Herbjörn

  11. iansrobinson says:

    May 1st, 2009 at 1:58 pm (#)

    Hi Herbjörn

    I too think making explicit intent or expectation is a good thing – one of the drivers for consumer-driven contracts. But event producers evidence little intent because they don’t expect anything in particular to happen when they publish an event – they don’t overly care. (Of course, from an overall systems perspective one might care very much that certain things happen when an event occurs.) On the other hand, if in the course of satisfying my contract to my consumers I depend on some other service to exhibit a behaviour, I’m likely to send that dependent service or application a command (I expect it, in JJ’s terms, to transition the state of a resource it controls).

    The names attached to each quadrant are there to characterize an aspect of design and implementation – whether it be of an individual operation or interaction, a service, or an entire system. I don’t favour picking one quadrant and forcing your entire solution to fit a context-free architectural preference.

    Emergency service describes the kind of interaction whereby I send you something and you decide what the appropriate action is, but in the context of a reasonably high degree of temporal coupling. Hence: I dial 999 and tell the operator my house is on fire; they decide what action to take; if the operator isn’t available there and then, my home’s hosed (or not – which is worse).

    Kind regards

    ian

  12. Guy Pardon says:

    May 5th, 2009 at 6:58 pm (#)

    Hi,

    Assuming a ‘FireStarted’ event assumes in turn that you are able to _decide_ on the fire being started or not.

    This decision in itself is – especially in SOA – often an act of distributed agreement – unless the fire is only limited to one service (so to speak).

    The bottom line: IMHO events, commands and all other styles are complementary – there will always be a core process of distribution complexity N (N being the number of distributed services involved). The rest can be events if appropriate.

    Put another way: coupling distributed parts (either way) may be a bad idea, but for some processes it is the best solution. If all else fails, you can always make requests retry-able like this:

    -queue the request
    -execute the coupled process
    -cancel if any problems arise -> this will re-queue the request
    -use a transaction monitor to cancel the process on failure
    -retry until success

    Does this mean tight coupling? Maybe, but where needed and beneficial (i.e., where you need replies anyway).

    This is (among other things) what we do at Atomikos.

    Cheers

    Guy
    http://www.atomikos.com
    Reliability Through Atomicity

  13. Saul Caganoff says:

    May 6th, 2009 at 12:19 pm (#)

    Hi Ian and JJ,

    Ian, I agree with you that message type is somewhat fluid – coupled with the fact that there are multiple facets to a message type. The facets include; the message representation (e.g. SOAP rpc encoding versus SOAP doc encoding to take a concrete example), the message intent, the message exchange pattern and potentially the transport. I feel that in practice not all of these facets are as orthogonal as they are meant to be.

    I am intrigued by JJ’s characterisation of a command message and its relationship to an event message. And its actually a bit of a blast from the past. It reminds me of a “pattern” we in TIBCO used to use many years ago before EAI became a dirty word, before JMS existed and we had only multicast messages (TIBCO Rendezvous). Multicast was just so cool that you had to show it off in the following manner: an initial message would update an entity in your system of record. Then a event message from the system of record would notify any “copies” out there of the update. The copy systems would take the responsibility of updating their copy – or at least setting a dirty flag. This was a kind of “event driven integration”. Used only occasionally, but quite powerful. No reason why it still wouldn’t be as effective, but it seems to have disappeared from the lexicon.

    Cheers,
    Saul