A Contract Vocabulary: Part 2
In my last post I described Consumer-Driven Contracts as an attempt at a contract vocabulary with three core terms: provider contracts, consumer contracts and consumer-driven contracts. In this post I’ll flesh out each of those terms.
These are the contracts with which many of us imbued with service-oriented concepts will be most familiar. They’re the contracts identified in that hoary old tenet, “Services share schemas and contracts, not classes and types.” Provider contracts mark services as king of their own domain – “this is what I am, what I offer, take it or leave it.” They’re the first-line defence in the struggle to preserve service autonomy. As I suggested in my previous post, in the WS-* world provider contracts typically comprise some or all of WSDL plus XML Schema plus WS-Policy.
These kinds of contract are really a private affair, particular to a specific consumer – to the way in which that consumer uses a service. In short, a consumer contract is a description of the parts of the service in which the consumer is really interested, the parts upon which it really depends. These might be interfaces, parts of an interface, operations, schemas, parts of schemas, quality-of-service characteristics, etc.: all those things I cheerfully labelled “a logical set of exportable business function elements.” More often than not, these specific usage characteristics remain implicit, and can be gleaned only be diving into the implementation of the consumer.
Some consumers need everything a provider exports: schemas, operations, endpoints, policies, and so on. More often than not, however, a consumer really only needs a subset of what the provider offers. Some consumers import only what is absolutely necessary, and ignore or tolerate changes in all the rest, but others will import or bind to everything, irrespective of its usefulness. Binding to everything might be appropriate in some circumstances, but at other times it’s a real barrier to evolution.
Oddly enough, I get the feeling that when people refer to consumer-driven contracts, they’re actually talking about consumer contracts. Most of the practical work in the area of service evolution seeks to reduce the amount of knowledge a consumer must have of a provider, whether it’s knowledge of a provider’s implementation (almost always a bad idea), or knowledge of parts of a provider contract that really have no bearing on the consumer. After all, knowledge is a dependency, isn’t it? Reduce the consumer’s knowledge of the provider – limit the scope of the consumer contract – and so achieve just enough coupling, no more.
I suggest it’s useful for consumers to know what their consumer contracts are.
In the original article I also called these derived contracts, but I don’t often use that term: “consumer-driven contracts” was suggested to me by Robin Shorrock, and I much prefer it – though if you’ve been test-, behaviour-, budget- and whatnot- driven to a frenzy, you might prefer “derived.”
Consumer-driven contracts bring the contractual forces back home to the provider. Assume for a moment that you could identify all the current consumers of your service; assume also that for each consumer you could know its consumer contract. A consumer-driven contract is the aggregate of all these consumer contracts. It’s a snapshot of existing contractual relations: it’s what the provider has to do to really satisfy existing dependencies, as opposed to what it started off offering. On the one hand, the provider offers a provider contract – “all that I am” – on the other, based on some set of current consumer expectations, it’s obliged to maintain only some portion of this contract. (Note that in some cases this “some portion” might in fact be everything that a provider offers under its provider contract, in which case its provider and consumer-driven contract look similar.)
Whilst we can say that a weak form of consumer-driven contract is implicit in all provider-consumer relations, Consumer-Driven Contracts took the idea a little further, suggesting that consumers might wish to import their consumer contracts into the provider, thereby surfacing an explicit consumer-driven contract.
Now the thorny question is: should you really seek to identify a provider’s “real” contractual obligations? After all, isn’t this extra knowledge, and isn’t extra knowledge an extra dependency, a tightening of the coupling screw?
My first response is to point out that these consumer expectations, and the provider’s obligation to satisfy them, exist whether we like it or not. Change something upon which a consumer currently depends, and you might very well break that consumer. Wouldn’t it be useful to know what you can and can’t change about a provider’s exported functionality, its provider contract, based on a “current” view of consumer relations? Wouldn’t this perhaps help you plan and govern the evolution of your service in response to changing business requirements?
I suggest that in many cases it’s useful for a provider to know what its consumer-driven contract is.