Skip navigation.
Arch2Arch Tab BEA.com

Achieving Loose Coupling

by David Orchard
02/02/2004

In this paper David Orchard shows that loose coupling is a qualitative measure of the dependency between two systems and that a variety of constraints can be performed to achieve loose coupling. Four major constraints that are undergoing development are described: Extensibility, Versioning, Early binding, and Asynchrony.

Question: How do you make two systems loosely coupled?
Answer: don't connect them.


This slightly pithy question is intended to focus your attention on how to attain loosely coupled systems. Any system that communicates is coupled to some degree. One definition of coupling [1] defines coupling as the degree to which components depend on one another. We try to minimize the coupling between the components in the system through good system and component design.

The article will provide a list of techniques that enable loose coupling, and describe a few of the techniques in more detail.

Now I'm an engineer by training and so I like to quantify things. It would be great if we could look at two components and measure how coupled they are. Imagine if we could say components A and B are coupled in the amount of five units. What is the "unit" of measurement?

In reality, we can't quantify coupling in software. It isn't amenable to a scientific measurement, belonging more in the "art" realm of subjective discussion. Yet we all want our systems to be loosely coupled. This leads us to examine what techniques produce loosely coupled software components.

It turns out - and this shouldn't be a surprise - that the techniques that lead to loose coupling are well-known and have been proven in software for decades. Indeed, the Web architecture optimizes for loose coupling very effectively.

The following well-known techniques engender loose coupling:
  1. Vendor and platform independent messages
  2. Coarse-grained, self-describing and self-contained messages.
  3. Well-defined interfaces
  4. Extensible Versionable interfaces
  5. Constrained interfaces
  6. Stateless messaging
  7. Human readable strings (URIs) for service and instance addresses
  8. Stateless messaging where possible and appropriate
  9. Humans controlling clients, called late-bound in this article, where possible and appropriate
  10. Asynchronous exchange patterns where possible and appropriate
Loose coupling typically results from the use of the techniques listed above. In Web architecture terminology, techniques are called good practices or constraints; so loose coupling is a property that results from the application of the constraints. The more constraints followed, the looser the coupling.

As an example, Web browsing is "mostly" loosely coupled because of extensibility in http/html, well-defined html and http vocabularies, stateless messaging, vendor/platform neutrality, humans controlling the client, use of URIs, etc..

Using Web service technologies will not automatically produce a loosely coupled system. Only through the application of the previously described constraints can one achieve loose coupling, in Web services or any other technology. However, the Web services community is trying to adopt constraints and guidelines that are more likely to produce loosely coupled systems. For example, the community is moving away from RPC encoding because it tends to surface platform dependent characteristics, the interface isn't as well defined as we'd like, it promotes fine-grained messages, and the interface is often not extensible.

Extensibility and Versioning


As I've talked with customers about Web service designs, it's been interesting to find out which constraints they are most comfortable with. Platform independence, coarse-grained messaging and well-defined interfaces seem readily used constraints. Constrained interfaces allow only a small number of operations. The Web is built upon a constrained interface described as REST (Representational State Transfer) and it is gaining some traction. But what I find astonishing is how few techniques are widely adopted and available to achieve extensibility and versioning.

I believe that one of the biggest reasons the Web succeeded was because it handled extensibility extremely well. [2] is an insightful article about the evolvability of the Web that makes for excellent reading material.

The reason to allow extensibility is to allow documents to evolve over time without forcing both sides into a "big bang" upgrade. Evolvability allows for compatible changes to clients or services. A special type of evolvability is versioning, which comes in two types: forward-/backward-compatible evolution and incompatible evolution. In the case of Web services, backwards compatibility means that a new version of a Web service receiver can be rolled out in such a manner as to not break existing senders. This means that a sender can send an old version of a Web service message to a receiver that understands the new version and still have the message successfully processed. Forwards compatibility means that an older version of a Web service receiver can consume newer messages and not break. Of course the older version will not implement any new behavior, but a sender can send a newer version of a Web service message and still have the message successfully processed.

Both HTML and HTTP have built in semantics that require receivers to ignore content they do not understand. That means adding new HTML tags or HTTP headers does not break a receiver that does not understand them, a crucial factor in allowing the independent deployment of clients and servers. It allows for browsers and the application protocol itself to evolve without forcing all servers and browsers to upgrade at the same time.

Very little discussion occurs about achieving extensibility and versioning. It's almost as if the community assumes that Web services simply inherit these aspects of the Web. In fact, the converse is true. Unless extensibility and versioning are explicitly designed into Web services interfaces then by default those interfaces will be neither extensible nor versionable.

Part of the problem seems to be that the Web architecture wasn't written down. Thankfully, the W3C Technical Architecture Group is now doing exactly that. Extensibility and versioning material is included in the Web Architecture document [3] as well as a TAG finding [4] devoted solely to the topic. These documents provide concrete guidance on how to design schemas and software for extensibility and how to design schemas for forwards and backwards compatible versioning. SOAP and WSDL have taken the Web extensibility and versioning models to heart, and provide a "Must Ignore" default as well as an innovative "Must Understand" model that allows runtime specification of mandatory extensions.

The need for early binding


We've seen a large number of Web services specifications released. It is important to understand why many of us see the need for these standards, particularly in order to use them appropriately. As I've said before [5], humans are pretty smart and can react to changes in ways that software hasn't - and probably won't be for quite some time - been able to mimic. In order to compensate for the lack of intelligence in machines it is necessary to introduce standards so that machines can tell when an interface has changed and how to re-act to that change. Effectively, Web pages are what we call "late-bound". This means the data and the understanding of it are handled at the time of the request. If anything changes in the interaction, such as login prompts moving, page flows changing, time-outs happening, then we humans can figure out what to do.

Software development has experienced a religious argument for years about the benefits of late-bound versus early-bound languages and systems. In early-bound languages, the data types are checked by a compiler, hence the term compile-time checking. In late-bound languages, the data types are checked at runtime by an application. But the debate about late-bound versus early-bound is different for distributed systems than it is for closed systems like a program.

When we talk about "binding" in the context of Web services, we are really talking about how much a component is programmed to understand about the type of data it is to handle. There are three different ways that the Web is both late and early-bound:
  1. The decision by a server as to what content to return in response to a request for a specific URI is late-bound. For example, a request to the same URI from a mobile and a fixed-line browser may return two completely different responses even though both systems asked for the same URI.
  2. Browser's ability to deal with different content types is early-bound, the browser either has the software it needs to process a particular type of content or it does not. More advanced browsers can detect when they don't have a needed handler and try to download it at run time but that behavior almost always depends on a human to help the browser discover and download the needed handler.
  3. The process of a person understanding the content that was downloaded in late-bound. It is a person reading the screen that understands the difference between a field asking for a name and a field asking for an address.
Effectively, the Web is late-bound on the server, early-bound for rendering on the client and late-bound for semantic understanding on the client

The nuance of semantic information being late-bound needs a bit more exploration. HTML information can be extremely expressive; a form with username and password fields is a good example. The form is early-bound to a browser because the browser knows how to render the form. But a human can distinguish between the username field and the password field. Thus the semantic meaning of the information in the Web is late-bound as it is "bound" in a person's head when they see the page.

On the other hand, an automated client will break if an application changes it's interface in any number of ways. Almost all screen-scraping applications cannot handle even the most rudimentary changes in the interface. The screen scraping software simply can't constrain the interface to "know" how to handle changes. A human, being late-bound, can look at a screen and understand that the password field has moved. But a screen scraper, being a dumb early-bound system, cannot.

Imagine a Purchase Order system. A sender sends Purchase Orders to a receiver, who responds with successful completion of the order or failures. The receiver must understand all the nuances and details of the purchase order messages. Any interface or type change - such as changing the authentication structures, changing the timing of the authentication step, changing the purchase order messages, etc - well require that the sender change. And that means a programmer must perform the change.

The model of semantic meaning being late-bound in the Web simply does not get us to where we want Web services to go. We need these tasks to be standardized so that we can re-use the semantics across our applications. Standards mean that the infrastructure portion of applications can be developed in a manner that is independent of the particular Web service. Standards will thereby enable us to develop software in an early-bound manner, and this reduces the coupling between the components.

Asynchrony


We've also been articulating a need for asynchrony for Web services for many years, exemplified by Adam Bosworth at [6]. Remembering our definition of coupling, asynchrony reduces the dependency between components by allowing a component to not "wait" for another component.

There is a trade-off between space and time with respect to coupling. Asynchrony allows one component be decoupled in time from another, but it does require that additional coupling in space. The coupling in space is that a sender, wanting to receive an asynchronous callback, must open up its address "space" to the callback sender. In many cases, such as the Web, the sender either doesn't do this - why much of the Web is synchronous - or the sender uses email to provide a space for subsequent callbacks. Much of Web services is about multiple complex servers communicating with each other, and so it is appropriate to move towards opening up the address space instead of being coupled in time.

BEA Systems did some early work on defining asynchronous headers for SOAP in SOAP-Conversation [7] and WS-Callback [8]. We're really excited to now see adoption of WS-Addressing [9]. WS-Addressing defines a "ReplyTo" SOAP header block for asynchronous messaging. We anticipate widespread deployment of WS-Addressing and it's asynchronous features.

Asynchrony is one of the final pieces in delivering loosely coupled components, and we are closing in on being able to repeatedly build systems using asynchrony.

Conclusion


This article shows that loose coupling is a qualitative measure of the dependency between two systems and that a variety of constraints can be performed to achieve loose coupling. Four major constraints that are undergoing development have been described: Extensibility, Versioning, Early binding, and Asynchrony.

[1] http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?query=coupling
[2] http://www.shirky.com/writings/evolve.html
[3] http://www.w3.org/TR/Webarch/#ext-version
[4] http://www.w3.org/2001/tag/doc/versioning-20031003
[5] http://dev2dev.bea.com/pub/a/2004/01/ws_orchard.html
[6] http://www.fawcette.com/Archives/premier/mgznarch/xml/2001/06jun01/ab0103/ab0103.asp
[7] http://dev2dev.bea.com/2002/06/SOAPConversation.html
[8] http://dev2dev.bea.com/webservices/WS-CallBack-0_9.csp
[9] http://dev2dev.bea.com/pub/a/2003/03/ws-addressing.html

Acknowledgements


The author thanks the many reviewers that have contributed to the article, particularly Yaron Goland and Mark Nottingham.

Article Tools

Email E-mail
Print Print
Blog Blog

Related Technologies

Bookmark Article

del.icio.us del.icio.us
Digg Digg
DZone DZone
Furl Furl
Reddit Reddit