SOA Design Patterns: Service Governance Patterns
- Compatible Change
- Version Identification
- Termination Notification
- Service Refactoring
- Service Decomposition
- Proxy Capability
- Decomposed Capability
- Distributed Capability
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.
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.