Design Patterns for .Net
  Articles, editorials, and presentations on the profession of software development
Printable Version
 
 

When Flexibility in Service Contracts Goes Awry

By: Rob Daigneau   Created: 9/9/2006   Last Update: 6/14/2007

One of the central themes in Service-Orientation (SO) is the idea of the contract. While this concept is not new (e.g. COM components developed in C++ described their contracts with Interface Definition Language, while the VB IDE hid the contract from developers), the way we document that contract is quite different when we use Service-Oriented principles. Most people probably know by now that web services, the most common way to implement the Service-Oriented style of design, uses XSD and WSDL to define these contracts.  One of the most interesting developments that I've seen is how people are viewing these contracts. Most people, for obvious reasons, seems to prefer contracts that are explicit and self-describing. Many people, even those who espouse the "Contract First" concept, also want contracts that can be unilaterally altered in some way. The hope is that none of the consuming applications will break when these changes are introduced "under the radar". Recently, when considering all of this, I found myself reflecting upon what I learned about contracts in the few law classes I took back in my college days a long long time ago.

The People's Court Phenomenon

What would you say is the most common reason that people wind up in small claims court? Usually the problem is that there was never a "meeting of the minds". In the world of contract law, this meeting of the minds can only be achieved when three elements are present ... the offer, the consideration, and the acceptance.

In the offer, the person proposing the contract presents the terms of a potential agreement that the parties would enter in to. The contract is not enforceable until the other party has a chance to consider what's being offered and accepts the terms, either explicitly or implicitly through their behavior. Therefore, with contract law, a contract does not exist without consideration and acceptance. Sometimes the contract is considered invalid if the accepting party doesn't understand the offer. This usually occurs when there is some ambiguity in the terms.

In the world of SOA, the offer occurs when a contract (e.g. described in WSDL when using web services) is formally published. It is at this point that the service provider is stating to all consumers, "These are the terms we're offering". The consumer may then consider if they want to work with the provider, and if there is some issue with the terms of the contract, the parties will hopefully be able to work out their differences in "meat space" (i.e. the real world of flesh and bones where people talk to each other). Once the consumer accepts the terms of the contract, either explicitly by communicating their intent to the provider, or implicitly by simply using the service, the contract is complete.

What happens when the service provider alters the contract unilaterally? Does the party that previously accepted the terms of the original offer have the opportunity to consider the new terms of the contract? If there is a close relationship between the parties, then the offeror may provide notice to the second party that a change to the contract may be forthcoming. This act provides the service consumer the opportunity to consider the change, and to alter their code to deal with the contract change if necessary.

Unfortunately, the service provider may have so many consumers that negotiating the contract change may not be feasible. What should the service provider do in this case? There probably isn’t a “one size fits all” answer for this; it really depends. If the provider decides to alter the contract without providing consumers the opportunity to consider and accept the changes, then has the contract been invalidated?

This is a tough question to answer. The typical approach to contract alterations is to extend the contract by adding "amendments" (e.g. adding data types to the end of a request message). When doing this, one should mark new attributes as optional, or if you're working with a new element, then you should set the minOccurs value to 0. One of the problems here is that the consumer must be aware that the contract they had previously accepted could change without their knowing it. In order to deal with such "flexible contracts", the consumer must validate the messages they receive in a way so that unknown elements or attributes are ignored (i.e. the consumer must suppress validation exceptions or bypass all data types that follow the last item in the contract they had originally opted in to). This doesn't seem like much of a contract to me. The consumer is forced to inspect the messages each time to see what may have changed.

Furthermore, what if the data provided in these contract amendments really is necessary to drive business logic back behind the service façade? Most would agree that, if this were the case, then a new contract should be offered. The question is, what then do you do about the old contract, and how do you go about deprecating it for consumers that are using it? While it is possible to alter the contract for a service provider without having to alter the consumer, bad things can and will continue to happen, just as they did back in the COM days.

Ambiguous Contracts

There are many techniques that have been used to provide extreme flexibility in contract evolution, all of which seem to defeat the purpose of contracts in the first place. If we want our contracts to be self-describing and explicit, all of these approaches won't help you much.

One of the most common approaches I've seen is to provide a single string argument to a service operation. In this approach, the parties define the structure of the XML document to be passed in this string either verbally or in writing. There is nothing in the contract definition of the service interface that enforces what they agree to. There is so much that can go wrong with this type of "contract", I don't know where to begin. Major structural differences in the XML document are allowed, and even minor differences in element or attribute names, including issues with capitalization, will be harder to catch. Additionally, common interoperable data types are left unspecified. Hopefully, both parties build their documents according to their verbal or written agreements and do a sufficient amount of testing. Any change thereafter must be carefully coordinated.

The use of XSD:Any isn't any better. This approach allows both the consumer and the provider to insert literally anything into the message. This is akin to letting both parties write their own terms for an agreement.  Imagine drafting a contract between two parties where each person has a blank page where they can unilaterally insert their own terms without negotiating with the other. This also seems to be a technique for achieving "loose coupling" that violates the principle of the contract.

Another technique that people use to provide flexibility in contracts are "Key/Value Pair Arrays" which occur as parameters to a service operation. This approach may be Ok if the provider at least places restrictions on the Key, the Value, or both. 

Conclusion

The morale of the story is that, while we can do creative things with XSD and WSDL when we define our service contracts, we may want to think twice. There are many who encourage us to think about SOA as a means to provide "business services" in addition to the more mundane goal of simply having an easier way to integrate applications or layers within applications. In cases where services are used between business partners, especially when service level agreements are involved, the consequences of changing a contract go beyond simple technical ramifications ... now we have business considerations to contemplate as well.

Related Articles

Principles of Service Design: Service Versioning

© 9/9/2006 Rob Daigneau, All rights reserved

Contact Me      Site Factoids