An Inter-Service Coupling Index for Lossless Exchanges
By Jeff Schneider
Copyright, Momentum Software Inc.
This paper is not an academic, proof-oriented paper. Rather it is a practioners view on the state of coupling in a distributed computing world. The formulas in this paper are designed to convey potential impacts and should be viewed as conceptual guidelines only.
Coupling is a term that is used to describe the breadth and depth of dependencies between two entities. A significant amount of effort has been applied to determining the attributes that couple software entities. The computer software community has been striving to create packages of highly cohesive modules that communicate between themselves in a loosely coupled fashion. Much of the recent work has focused on coupling within object-oriented systems, usually relating to a single application written in a homogenous environment. Thus measurements related to 'class coupling', 'inheritance coupling' and the like were prominent. Web Services and the contract-based programming model have pushed the level of abstraction and offer one potential answer to the ongoing coupling dilemma.
This index has been created with web services and service oriented architectures in mind and thus will likely have biases towards measuring those types of systems. The creation of a quantitative index for capturing what most scientists believe is a qualitative attribute may likely be an academic exercise. However, my goal is to call out that certain variables will affect the coupling of systems and should be given attention during the design phase. In addition, a fundamental belief that I hold is that 'intermediaries', if introduce-able at runtime, have the potential of bringing a coupling index to an unprecedented low level. This concept is conveyed via 'Intermediary Decoupling’; where-by, other coupling concerns are mitigated by the use of one or more 'intermediaries'.
All formulas mention hereafter are introduced only to convey one potential way of capturing a coupling factor and by no means should be considered a firm rule for the quantitative measurement of coupling. Rather, they should serve as a new starting point for others to consider, revise and extend upon.
The Service Coupling Index
Coupling can be viewed from many angles. This paper pays extra attention along three dimensions: 1. Design-Time Issues vs. Run-Time 2. Code-base Issues vs. Use Case Based and 3. Consumer Side vs. Producer Side
To date, coupling metrics have largely focused on 'design time' issues. That is, the measurement of dependency is observed by statically analyzing the code. In this instance, the code 'states' what it can and does communicate with. However, this type of metric becomes less important in a service and message based architecture. Services have the ability to send out messages, which can be altered, translated or re-routed. This switches the focus from 'what the code says it does' to 'what the network can make it do'. Thus, the level of coupling in software componentry is directly affected by the intelligence of the service network in which it resides. In an intelligent service network, a consumer and producer can dynamically resolve their differences by introducing new services that act as intermediaries to resolve disputes.
The second issue of coupling deals with the scope in which we care to measure the coupling. To date, most of the efforts have taken a static analysis of all dependencies (or calls) between two software entities (taking into account the entire code base). Although this is a fair scope, I believe that an equally insightful measurement can be taken by reducing the scope from 'all the code' interactions to 'only the code utilized to fulfill a use-case'. With a use-case approach, we can more accurately look at coupling based on fulfilling some intent.
The third issue focuses on 'where' the coupling takes place. Can a service be designed in a way where it invites tight coupling? Can a consumer be written in such a manner as to increase the coupling on a specific service? My belief is, "yes" on both accounts. Although coupling usually occurs as an instance of a collaboration path between systems, it is possible to identify some of the design time problems that invite tight coupling without ever looking at the producer/consumer relationship or at the runtime message instances.
In order to determine the coupling level between two entities, consider the following formula. Where, 'User Weight' is a value defined by the user of the system to weight the influence of that piece of the architectural concern.
For a given use case (or intent), determine:
((Intermediary Decoupling * Standards Coupling * User Weight1) +
(Intermediary Decoupling * Granularity Coupling * User Weight2) +
(Intermediary Decoupling * Contract Coupling * User Weight3) +
(Intermediary Decoupling * Abusive Coupling * User Weight4))
where a lower score = more loosely coupled
Granularity Coupling is concerned with the ability for a service to have an efficient conversation in both local and distributed mode. Historically, modules were optimized to either be a local call with a fine-grained interface or a remote call with a coarse grained interface. With the introduction of services and their potential to be relocated closer to each other, it becomes important for a service not to be designed with a single granularity design. By offering both coarse and fine-grained interfaces, the service can become more tolerant to the latency issue. The assumption is that the granularity design of the service is made with no knowledge of latency between itself and other dependent services. The producer-consumer relationship has the responsibility of performing run-time negotiation on which granularity level to use. It can be successfully argued that some services will only have one 'correct' coupling level and in such cases, only the appropriate offering should be provided and from an index perspective no points should be deducted.
For Each Potentially Bi-Granular Operation, calculate:
(2 - (a coarse grained interface? Yes =1, No = 0) -
(a fine grained interface? Yes = 1, No = 0))
Note: Agreeing on what is fine grained and what is coarse grain is yet another issue. One rule of thumb is to only consider calls with primitive data types as examples of fine-grained calls.
Web Services, as well as most modern distributed computing techniques, have become significantly dependant on the use of protocols or standards to enable the communications between heterogeneous participants. As the number of required protocols or standards increases, so does the coupling. However, the increase in coupling is also related to the ubiquity of the protocol implementations or the ease in which a substitute can be located. As an example, communication via the WS-I basic profile may require a handful of protocols or standards (e.g., tcp/ip, dns, http, url, soap 1.1, wsdl 1.1., uddi 2.0, XML Schema 1.0, etc.) Many of these protocols / standards are very ubiquitous (tcp, dns, etc.) Conversely, an implementation may require more advanced protocols (ws-reliableMessaging, ws-atomicTransaction, ws-PolicyAttachment, ws-PolicyAssertion, etc.) In these cases, the installed implementations between communicating partners may be less ubiquitous. In addition to base transmission protocols, one must consider the other standards that may be used in the communications. This will include potential parameter values (passing in SQL, XQuery, XPath, etc.) Another form of standards coupling deals with language or platform assumptions (e.g., two systems are coupled if they demand using the same language or the same platform).
For Each Standard, find the lesser value:
(1- (the ubiquity of the standard within a community, percent of participants (0 : 1) *
(How standardized is the standard?, percent of standardization (0 : 1))) OR
(Repeat: Standards Coupling (a valid substitution)))
Note: At first it may appear difficult to determine the ubiquity of a given standard or protocol. However, the tools and techniques to create an inventory of the capabilities of the services (standards, protocols, versions, etc.) will be required to make loose coupling in service networks plausible. During the incline of the web era, programmers built crawlers to scan capabilities of web servers; the same concept will likely be applied to the web services world. The only difference is that the results of the 'ubiquity crawlers' will likely be provided as a service and feed intermediaries information on how to provide dynamic resolutions.
Contract Coupling is concerned with the interface encapsulation of the service. The interface between the service and the consumer of the service is a contract - and not all contracts are created equally. Services that require information to be passed in which is difficult to obtain increases the coupling level. Conversely, a service that can be called without internal knowledge of the system enables looser coupling. If a service were to require some piece of unknown information (e.g., a foreign key) and no means to obtain the information (e.g., a foriegn key lookup), then the coupling is increased. If a service were to provide 'helper operations' to retrieve the hidden information, then the coupling is decreased. The essence of Contract Coupling deals with the constraints related to the parameters of the call. If a parameter has an enumerated set of valid options, they should be communicated. If the acceptable parameter values are based on other parameter values, than that should be conveyed. Failure to convey information related to a successful invocation leads to increase coupling. Currently, a significant amount of information about a web service contract is published in the WSDL, the message schema or extensions like a policy. However, these facilities do not ensure loose coupling, rather they just provide the means to do so; the responsibility of correct utilization falls on the service designer.
For Each Required Operation, sum (Ability to ascertain parameter call information), where:
(Fully reflective or interrogate-able through contract = 0,
human ascertainable = .5,
unobtainable without knowledge of internal system = 1)
Note: Change weights as appropriate (0-1)
In addition to the regular coupling issues that deal with contract (both functional and non-functional), there are a number of issues that directly affect system performance. Even though the interface between consumer and producer are clean (or loose), it is still possible to misuse the contract. There are five well-known abuses in contract-oriented programming that should be considered:
1. Chatty Conversations - Chattiness is a measurement of the breadth of the message exchanges. It can be viewed as the number of calls between XY, from X to Y, or Y to X to fulfill some intent. In lossless exchanges, it is possible to define message exchange patterns that are so verbose that they increase the coupling between the entities. Previous work defined this measurement by counting inbound or outbound function calls.
2. Fatty Messages - Fatty messages are those messages with too much information being passed between participants. Prior work referred to this concept as ‘Stamp Coupling’ and places it as a primary concern. Today, I believe less emphasis is placed on fatty messages for two reasons: 1. The introduction and ubiquitous spread of grammars like XML enable systems to pass fatty schemas without the other party having to be fully informed on those portions of the schema in which they may not be interested. 2. System (network, cpu, disk) performance appears to be increasing at a rate greater than the increase in the fat of the messages. The issue that remains is that of increasing complexity and programmer error. Thus, fatty messages often reveal too much information, making the consumer of the message confused on which information they should be working with and which information should be ignored.
3. Time Bound Conversations (synchronous) - Time Bound Conversations are those that demand a specific synchronization scheme. That is, they demand for the messaging to be either synchronous, or asynchronous. In many cases, a service could be designed to have both synch and asynch capability (a bi-synchronous service), however, most designers will choose one or the other - thus limiting the flexibility of the system. I've fought on many occasions to throw out the issue of time bound conversations as an issue of coupling. However, the fact is that the issue remains just that, a real issue. My belief is that time-bound conversations have the potential to be remedied via an intermediary (and often are). However, the vast majority of system communication architectures do not deploy this as part of their base patterns. Thus, I am including it as part of 'abusive coupling'.
4. Interface Fragility - Inteface Fragility deals with the impact of extending or modifying the interface so that the consumers of the interface will have minimal impact. In modern programming models, a software consumer is coupled to the interface of the producer. The impact of the coupling changes based on the ability to absorb interface changes. Thus, if even a small change in an interface (like an extension) causes the entire interface to break, the interface would be considered very fragile.
5. Fixed Invocation Models - The Fixed Invocation Model issue is a consumer-side problem. By programming to a specific and perhaps limited invocation model, the coupling is increased. For instance, if a program were to specify the use of JMS to send messages, certain assumptions about the synchronicity or platform may be implied. These implications may limit the flexibility of the calling structure and increase the dependence on specific API's. As an alternative, an invocation-meta-model is a preferred method of overcoming fixed call structures. Here, the invocation model is described as runtime metadata and the invocation is assembled at runtime.
For Each Operation, calculate:
((Chattiness * Weight1) + (Fatty * Weight2) +
(Time Bound * Weight3) + (Fragility * Weight4)
(Fixed Invocation Model * Weight 5) / 5)
Where: Chattiness is, 1 call = 0, 2 calls = .33, 3 calls = .66, 4 or more calls = 1
Fatty is, (1 - percent of (0 : 1) of the message document that is actually needed in the communication)
Time Bound: Bi-synchronous services with both asynch and synch implementations available = 0
Bi-synchronous services with only 1 implementation available = 1
Uni- synchronous services with the correct implementation = 1
Uni- synchronous services with the incorrect implementation = 0
Fragility is the percent of the consumers that will be adversely effected by a random, yet valid change in the interface (0 : 1)
Fixed Invocation Model: (1 –
(# of the permutations in the community covered by the invocation model) /
(# of permutations of standards found in the community) )
A significant number of tools and techniques are used and often standardized in modern distributed computing. A non-exhaustive list to consider includes, encryption, hashing, signing, windowing, addressing, reliability, transactional capability, message encoding, enveloping, negotiation capability, self-morph-ability, inspect-ability, compression, streaming, caching, etc. As previously mentioned, Standards Coupling relates to the aggressive use of standards to create an effective communication path. It doesn't concern itself with the 'failed scenario'. Intermediary Decoupling deals with the ability to swap out a protocol or standard on the fly (at run-time, not design time). Thus, if two parties wish to communicate and their predetermined protocol matching fails, they have the ability to introduce an intermediary (translator, fail over service, proxy, etc.) to fulfill the original communication requirements.
For Each Call, sum(ability to dynamically resolve the communication conflict)
Note: Intermediary Decoupling will likely rely on the use of a dynamic addressing scheme to route information at runtime. This includes return paths or callbacks.
This paper looks at coupling as it relates to web services and service oriented architectures. It acknowledges the concepts of modern architectures like common grammars for schemas, network protocols, services, interface definition languages, dynamic policies and the like as potential decoupling devices. It also promotes the use of 'intermediaries' to remedy many of the coupling issues related to the growing number of protocols and standards that are now required to communicate in a 'loose' fashion.
On a personal note, it is my belief that just as educated software intermediaries can help reduce Standards Coupling, additional automated intermediaries will be able to mitigate the effects of Abusive Coupling, Granularity Coupling and Contract Coupling. And through 'educated networks', software modules will be able to automatically refactor themselves across the network to loosen or tighten their relationship as needed. It is my opinion that the software community should place increasing attention on methods to enable the dynamic structuring of software across a network, with the structure of that software controlled by the network, not the programmer.
This paper has limited the focus on ‘recipe based’ programming. That is to say that additional decoupling can likely be found by reducing the amount of ‘recipe information’ (the ‘how’ aspect), rather than the intent or goal of the communications. Modern programming languages tend to focus more on the set of calls necessary to fulfill some use case. Advances in intentional and generative programming make offer a new level of decoupling.
In addition, this paper was limited to ‘lossless exchanges’. These are message exchanges where both parties agree to only communicate as long as the syntax of the conversation is fully agreed upon in advance. The belief is that this type of ‘all or nothing’ contract will reduce the potential for miscommunications. However, most biological exchanges are not ‘lossless’ rather they are ‘lossy’. In this manner, if two parties fail to understand a conversation, they ask for clarification or bring in a third party to resolve misunderstandings. In addition, the guarantee of syntactic agreement does not imply the guarantee of semantic agreement. Which, could be argued is actually more important. Advances in ‘lossy exchanges’ will likely take decoupling to a whole new level.
I'd like to thank the following people for providing valuable feedback: James Iry, Sean McCullough, Doug Kaye and David Orchard. In addition, much of this work was influenced by the book, "The Practical Guide to Structured Systems Design" by Meilir Page-Jones which built upon many of the concepts of "Structured Design" (Yourdan and Constantine).