Concurrent Contracts
How can a service facilitate multi-consumer
coupling requirements and abstraction concerns at the same time?
|
Problem
A services contract may
not be suitable or applicable for all of the services potential consumers.
|
|
Solution
Multiple contracts can be
created for a single service, each targeted at a specific type of consumer.
|
|
Application
This pattern is ideally
applied together with the Service Faade pattern to support new contracts as
required.
|
Impacts
Each new contract can
effectively add a new service endpoint to an inventory from the service
consumers perspective, increasing corresponding governance effort.
|
|
Principles
Standardized Service Contract,
Service Loose Coupling,
Service Reusability
|
Architecture
Service
|
Table 8.1 – Profile summary for the Concurrent
Contracts pattern.
Problem
By default, a service has a contract that expresses the full
range of its abilities. However, it can be challenging to design this contract
in such a manner that it accommodates different types of service consumers.
For example, the service contract may need to incorporate
special processing extensions (such as policy assertions) no supported by all
consumer programs. Or, the service may need to be made available to semi- or
non-trusted consumers that could potentially abuse some of its capabilities.
Having one contract support a range of consumer types is
challenging both from design and governance perspectives, and can ultimately
lead to security concerns and constraints that limit the services overall
effectiveness.

Figure 8.1 – It can be undesirable to expose a service
contract to all potential consumers, especially when some are less trusted than
others. For example, exposing the full Invoice service contract to consumers
that should only have access to a subset of its capabilities introduces the
risk that consumers will access other capabilities anyway.
Solution
To accommodate different types of consumers, separate
service contracts can be created for the same underlying service
implementation. Unlike additional contracts that are introduced to represent
new service versions, these contracts are hosted and supported concurrently for
the same service version.
Even though this introduces redundancy in functional
representation, it allows each contract to be extended and governed
individually. It also provides the option of exposing a subset of the service
capabilities to specific consumers.

Figure 8.2 – Separate contracts are created for the
three service consumer categories. In some environments this may require the
further qualification of the service name; for example, the three contracts may
be named Invoice Admin, Invoice Reporting, Invoice Vendor.
Application
This pattern needs to be applied with care and moderation.
Introducing multiple contracts leads to increased governance complexity and
effort, as explained shortly in the Impacts section.
Often additional contracts are not considered necessary until
well after the deployment of the service and its original contract. Therefore,
it is recommended that new contracts not be created too reactively. Instead,
each new consumer base (a group of related types of service consumer programs)
should be well defined so that it is confirmed that a new contract is warranted
and so that the nature of its expressed capabilities is clearly thought out.
The application of this pattern in general is more easily
carried out if the service was originally designed according to the Service
Faade pattern. A separate faade can actually be created for each new
contract, as shown in Figure 8.x.

Figure 8.3 – Multiple service contracts can be
implemented with the support of the Service Faade pattern, which allows for
contract-specific abstraction from the core underlying logic. This is
especially relevant when contracts need to vary in terms of data representation
support and security requirements.
There will be a natural tendency to want to modify the
validation of contracts for different consumers. This also needs to be
carefully assessed. Ideally, the contracts remain in alignment in how they
express their respective capability sets. However, certain policies and
security constraints may be applicable only to certain types of consumers
(especially when having to facilitate both internal and external consumer
bases).
Therefore, as a rule of thumb, it is best to limit the
variation in validation logic to access control only. Validation logic based on
underlying service business logic should remain the same across all contracts
for the single service implementation. If different business rules or business
constraints apply to different types of consumers, that decision logic may be
best embedded within the underlying service logic (as per the Validation
Abstraction design pattern).
Impacts
Adding new contracts for the same service introduces similar
governance requirements as when new contracts are added to support new service
versions. In fact, the governance overhead of this pattern is more significant
because the concurrent contracts will need to be maintained for an indefinite
period of time (as opposed to versioned contracts where an outdated contract
version will usually have a limited lifespan).
Relationships
For Concurrent Contracts to be applied, the service contract
itself should be fully decoupled from the underlying service logic (as per the
Decoupled Contract pattern), and the Service Faade pattern should be applied
to provide a faade component in order to support multiple contracts without
the need for redundant service logic.
By limiting service access to its contract(s), the contracts
produced by this pattern remain official entry points via the consistent
application of the Contract Centralization pattern.
Both Contract Denormalization and Validation Abstraction
patterns are employed to help optimize service contracts in support of the
Service Abstraction design principle and also to facilitate different types of
service consumers. The Concurrent Contracts pattern allows for different levels
of these two patterns to be applied to different contracts, all for the same
service. However, it could turn out that there is less of a need for Contract
Denormalization since denormalized capabilities could simply exist in a
different contract.

Figure 8.4 – The Concurrent Contracts pattern relates
to other contract-related patterns that help support or are affected by the
creation of multiple contracts for a single service.
Case Study Example
Case study content is not available on this Web site.