The governance patterns in this chapter focus only on design-related governance issues that pertain to service architecture. The upcoming book SOA Governance as part of this book series will provide a collection of broader technical and organizational best practices and patterns.

Despite best efforts during analysis and modeling phases to deliver services with a broad range of capabilities, they will still be subjected to new situations and requirements that can challenge the scope of their original design. For this reason, several patterns have emerged to help evolve a service without compromising its responsibilities as an active member of a service inventory.

Compatible Change (465) and Version Identification (472) are focused on the versioning of service contracts. Similarly, Termination Notification (478) addresses the retirement of services or service contracts.

The most fundamental pattern in this chapter is Service Refactoring (484), which leverages a loosely (and ideally decoupled) contract to allow the underlying logic and implementation to be upgraded and improved.

The trio of Service Decomposition (489), Decomposed Capability (504), and Proxy Capability (497) establish techniques that allow coarser-grained services to be physically partitioned into multiple fine-grained services that can help further improve composition performance. Distributed Capability (510) also provides a specialized, refactoring-related design solution to help increase service scalability via internally distributed processing deferral.

Compatible Change

By David Orchard, Chris Riley

How can a service contract be modified without impacting consumers?

Table 16.1. Profile summary for the Compatible Change pattern.

Problem

Changing an already-published service contract can impact and invalidate existing consumer programs.

Solution

Some changes to the service contract can be backwards-compatible, thereby avoiding negative consumer impacts.

Application

Service contract changes can be accommodated via extension or by the loosening of existing constraints or by applying Concurrent Contracts (421).

Impacts

Compatible changes still introduce versioning governance effort, and the technique of loosening constraints can lead to vague contract designs.

Principles

Standardized Service Contract, Service Loose Coupling

Architecture

Service

Problem

After a service is initially deployed as part of an active service inventory, it will make its capabilities available as an enterprise resource. Consumers will be designed to invoke and interact with the service via its contract in order to leverage its capabilities for their own use. As a result, dependencies will naturally be formed between the service contract and those consumer programs. If the contract needs to be changed thereafter, that change can risk impacting existing consumers that were designed in accordance with the original, unchanged contract (Figure 16.1).

Figure 16.1 The name of a service capability is modified after version 1 of a service contract is already in use. As a result, version 2 of the contract is incompatible with Consumer A.

Solution

Wherever possible, changes to established service contracts can be made to preserve the contract's backwards compatibility with existing consumers. This allows the service contract to evolve as required, while avoiding negative impact on dependent compositions and consumer programs (Figure 16.2).

Figure 16.2 The existing capability is not renamed. Instead, a new capability with a new name is added alongside the original capability, thereby preserving compatibility with both Consumers A and B.

Application

There are a variety of techniques by which this pattern can be applied, depending on the nature of the required change to the contract. The fundamental purpose of this pattern is to avoid having to impose incompatible changes upon a service contract that do not preserve backwards compatibility and therefore risk breaking and invalidating existing service-consumer relationships.

Here is a collection of common changes for Web service contracts, along with descriptions of how (or to what extent) these changes can be applied in a backwards-compatible manner:

Adding a New Operation to a WSDL Definition– The operation can simply be appended to the existing definition, thereby acting as an extension of the contract without impacting any established contract content.

Renaming an Existing Operation– As explained in the previous diagrams, an operation can be renamed by adding a new operation with the new name alongside of the existing operation with the old name. This approach can be further supplemented with Termination Notification (478), if there is a requirement to eventually retire the original operation while allowing consumers dependent on that operation a grace period to be updated in support of the renamed operation.

Removing an Existing Operation– If an operation needs to be permanently deleted from the WSDL definition, there are no options for accomplishing this change in a compatible manner. Termination Notification (478) is highly recommended in this case in order to give consumer designers sufficient opportunity to transition their programs so that they are no longer using the to-be-terminated operation. Also, the technique of turning removed operations into functional stubs that respond with descriptive error data can also be employed to minimize impact on consumers that could not be transitioned.

Changing the MEP of an Existing Operation– To alter an operation's message exchange pattern requires that its input and output message definitions (and possibly its fault definition) be modified, which is normally an incompatible change. To still proceed with this change while preserving backwards compatibility requires that a new operation with the modified MEP be appended to the WSDL definition together with the original operation. As when renaming an operation in this manner, Termination Notification (478) can be used to assist an eventual transition.

Adding a Fault Message to an Existing Operation– The addition of a fault message (when considered separately from a change to the MEP) may often appear as a compatible change because the option of issuing a fault message does not affect the core functionality of an operation. However, because this addition augments the service behavior, it should be considered a change that can only be compatible when adding the fault message as part of a new operation altogether.

Adding a New Port Type– Because WSDL definitions allow for the existence of multiple port type definitions, the service contract can be extended by adding a new port type alongside an existing one. Although this represents a form of compatible change, it may be more desirable to simply issue a new version of the entire Web service contract.

Adding a New Message Schema Element or Attribute– New elements or attributes can be added to an existing message schema as a compatible change as long as they are optional. This way, their presence will not affect established service consumers that were designed prior to their existence.

Removing an Existing Message Schema Element or Attribute– Regardless of whether they are optional or required, if already established message schema elements or attributes need to be removed from the service contract, it will result in an incompatible change. Therefore, this pattern cannot be applied in this case.

Modifying the Constraint of an Existing Message Schema– The validation logic behind any given part of a message schema can be modified as part of Compatible Change, as long as the constraint granularity becomes coarser. In other words, if the restrictions are loosened, then message exchanges with existing consumers should remain unaffected.

Adding a New Policy– One or more WS-Policy statements can be added via Compatible Change by simply adding policy alternatives to the existing policy attachment point.

Adding Policy Assertions– A policy assertion can be added as per Compatible Change (465) to an existing policy as long as it is optional or added as part of a separate policy as a policy alternative.

Adding Ignorable Policy Assertions– Because ignorable policy assertions are often used to express behavioral characteristics of a service, this type of change is generally not considered compatible.

NOTE

This list of changes corresponds to a series of sections within Chapters 20, 21, and 22 in the book Web Service Contract Design and Versioning for SOA, which explores compatible and incompatible change scenarios with code examples.

Impacts

Each time an already published service contract is changed, versioning and governance effort is required to ensure that the change is represented as a new version of the contract and properly expressed and communicated to existing and new consumers. As explained in the upcoming Relationships section, this leads to a reliance upon Canonical Versioning (286) and Version Identification (472).

When applying Compatible Change in such a manner that it introduces redundancy or duplication into a contract (as explained in several of the scenarios from the Application section), this pattern can eventually result in bloated contracts that are more difficult to maintain. Furthermore, these techniques often lead to the need for Termination Notification (478), which can add to both the contract content and governance effort for service and consumer owners.

Finally, when the result of applying this pattern is a loosening of established contract constraints (as described in the Modifying the Constraint of an Existing Message Schema scenario from the Application section earlier), it can produce vague and overly coarse-grained contract content.

Relationships

To apply this pattern consistently across multiple services requires the presence of a formal versioning system, which is ideally standardized as per Canonical Versioning (286). Furthermore, this pattern is dependent upon Version Identification (472) to ensure that changes are properly expressed and may also require Termination Notification (478) to transition contract content and consumers from old to new versions.

Figure 16.3 Compatible Change relates to several other service governance patterns but also may depend on some contract design patterns.

Case Study Example

As described in the case study example for Contract Denormalization (414), the Officer service contract was recently extended by FRC architects to include a new UpdateLog operation.

Before the architects can release this contract into the production environment, it must go through a testing process and be approved by the quality assurance team. The first concern raised by this team is the fact that a change has been made to the technical interface of the service and that regression testing must be carried out to ensure that existing consumers are not negatively impacted.

The architects plead with the QA manager that these additional testing cycles are not necessary. They explain that the contract content was only appended by the addition of the UpdateLog operation, and none of the previously existing contract code was affected, as shown in the highlighted parts of this example:

Example 16.1. The WSDL definition from Example 14.1 is revisited to show how the change made during the application of Contract Denormalization (414) was backwards-compatible.

Because existing content was not changed and only new content was added, they claim that the contract is fully backwards-compatible. The QA manager agrees that this indicates a reduced risk but insists that the revised service be subjected to some testing to ensure that the addition of the new operation logic did not affect its overall behavior.