13 January 2014
Identifying the sources of system coupling in service orientated architectures
Every system has some level of coupling. After all, systems need to collaborate and in doing so they will inevitably share some characteristics of language and behaviour. It’s important to recognise where coupling occurs and the impact it has on stability and flexibility.
Many systems are described as “loosely coupled” when in reality they are based on a complex network of dependencies. These are generally two-way dependencies in that a system has out-going dependencies from its processes as well as incoming dependencies from processes owned by other systems. Genuine loose coupling can be surprisingly difficult to maintain as system dependencies tend to creep in from a number of different directions.
If components share responsibilities for business processes then they will inevitably be coupled in a behavioural sense. In this case, the sender of any message is likely to know something about how the receiver will respond to the message. It may even go so far as to provide instructions as to how the receiver should process the request.
This kind of intimacy is implies poor separation of responsibilities between systems. There should be clear boundaries where crossing from one system to another is an explicit act. A high level of behavioural coupling implies that systems are not sufficiently autonomous so that a change in one will directly affect others.
The style of communication between systems is relevant. Services that send command-style messages tend to be more closely coupled as one service is making a decision on behalf of another by telling it to do something. Lower behavioural coupling is often associated with an event-based messaging style where notifications are broadcast in response to something that has happened. Any systems receiving these event message can freely choose how to respond rather than being expected to act on them in a particular way. This freedom to interpret an incoming message tends to imply a more loosely coupled relationship.
Although behavioural coupling is the most widely referenced type of system coupling though it is by no means the only source. Components are not necessarily “loosely coupled” just because they happen to be collaborating between a well-defined set of event-based interfaces or using event-based messaging.
Components can be connected to each other in time. If a sender needs a response before it can carry on with any further processing then it is closely coupled in a temporal sense. Temporal coupling also arises in processes based on sequential steps, each of which depends on data that is carried forwards. If one part of the chain fails then subsequent activities cannot continue.
Typically you see temporal coupling with layered architecture, particularly when it’s based on synchronous communication. It’s also associated with web services as they tend to give rise to the kind of request\response patterns that require somebody to be listening on the other end.
Event-based messaging tends to lower temporal coupling as information is broadcast without any expectations over how it will be treated. The systems that send events don’t know when they will be consumed and the systems that receive events don’t know when they will be sent.
Temporal coupling presents particular difficulties for transactions. Asynchronous messaging makes it challenging to share transactions across system boundaries as they are likely to be left hanging without any idea of when they will be able to complete. Ideally you should not be sharing transactions in this way as autonomous services shouldn’t be allowing their resources to be locked by another system.
Collaborating systems should only be sharing schemas and contracts, not classes or implementation detail. This requires a special concern for interoperability as you are unlikely to keep an entire system within a single narrow platform ecosystem such as .Net.
If you use any platform-specific protocols your systems will become coupled in a platform sense as the collaboration becomes dependent on a platform-specific mechanism. They are no longer just sharing a schema, they are also sharing an implementation of a platform technology.
An example of this kind of inadvertent platform coupling is passing .Net specific objects through services implemented with WCF. A non-WCF client will have trouble interpreting a DataSet object and be unable to use the service. This kind of platform coupling can be reduced by using fully platform-agnostic, standards-based mechanisms for system communications.
An application shouldn’t need to know where its collaborating systems are physically located before it can communicate with them. If a service is dependent on a particular address then the communication will break down if this remote location changes. In this case the service is dependent on the implementation details of another external system.
This dependency on the address of an external resource creates a kind of location-based coupling. It undermines the logical nature of system architecture by creating physically coupled components. This can often give rise to complex, distributed configuration files that are inherently fragile. A change to any service location can become a major operation as it causes configuration changes to ripple throughout the infrastructure.
Ideally this can be solved by abstracting away the location of services to a broker service. Locations become logical destinations and the details of where they really live are concealed from the participating systems. If a message type can be mapped directly to a service location by this broker then the participating applications can be wholly spare the detail of where participating systems are based.
This final type of coupling is less concerned with participating systems. It happens when you have not defined clear enough responsibilities so individual systems can start to take on too may distinct responsibilities. This creates a kind of internal process coupling where numerous logical processes are joined together in a single implementation.
Customer Relationship Management (CRM) systems such as Salesforce and Siebel are common sources of process coupling. They are often introduced into an organisation to fulfil the core role of managing accounts but their innate flexibility allows them to expand into numerous areas of the eCommerce landscape such as licensing, product catalogue and even help desk management. The end result can be a “monster” system that conflates unrelated processes and data.