Any Good Pattern Language should be based on a well defined set of primitives (i.e. basic building blocks). Architectures and Design Patterns (referred in the GOF book as micro-architectures) require a clear definition of constraints to be of any real value. Roy Fielding when defines ReST in the context of constraints. In stark contrast, most SOA definitions that one can find, including the OASIS standard definition, fails to define the architectural constraints.
In previous posts I have formulated a set of attributes that provide the definition of Services. I further refined those to this current definition:
A Service Oriented approach satisfies the following:
- Decomposability – The approach helps in the task of decomposing a business problem into a small number of less complex subproblems, connected by a simple structure, and independent enough to allow further work to proceed independently on each item.
- Composability – The approach favors the production of Services which may then be freely combined with each other and produce new systems, possibly in an environment quite different from the one in which they were initially developed.
- Understandability – The approach helps produce software which a human reader can understand each Service without having to know the others, or, at worst, by having to examine only a few of the others.
- Continuity – The approach yields a software architecture that a small change in the problem specification will trigger a change of just one Service, or a small number of Services.
- Protection – The approach yields a software architecture in which the effect of an abnormal condition occurring at run time in a Service will remain confined to that Service, or at worst will only propagate to a few neighboring Services.
- Introspection – The approach yields an architecture that supports the search and inspection of data about Services (i.e. Service Meta-data).
- Remoteability – The approach yields an architecture that enables Service interaction between other Service that reside in separate physical environments.
- Asynchronicity – The approach yield an architecture that does not require an immediate response from a Service interaction. In other words, it assumes that latency exists in either the network or the invoked Service.
- Document Orientedness – The approach yields an architecture where the messages sent Service to Service interaction are explicitly defined, shared and that there is no implicit state sharing between interactions.
- Decentralized Administration – The approach yields an architecture that does not assume a single administrator for all Services.
This is an extended definition of Bertand Meyer’s definition of Modularity. You can look at my previous post entitled “SOA and Modularity” to see how this compares with other definitions of SOA.
Now if we were to consult the “SOA Manifesto” and its value system then we could derive the following goal: “We believe in building modular systems through intrinsic interoperability and evolutionary refinement to achieve business value and satisfy strategic goals”. The key ingredient in this statement that is left ambiguous is “Intrinsic Interoperability”. The key question for anyone employing SOA is to understand how to achieve “Intrinsic Interoperability”. Modularity and Evolutionary Refinement are well understood principles, Intrinsic Interoperability is not. One may have the belief that interoperability can be achieved by simply mandating a global standard. This can work in theory, however rarely ever does in practice. Centralized planning is rarely a scalable approach, evolutionary refinement in fact demands a decentralized approach. The question one needs to ponder is how can I build interoperable systems employing a decentralize approach. In the literature I have surveyed I have yet to find a cohesive treatment on how this can be done.
Over the past decade many Design Patterns have been proposed to address many of the concerns that are introduced with in a Service Oriented Architecture. The most notable collections have been following:
- Server Component Patterns – Covers Component and Containers in the context of server based systems.
- Service Discovery Patterns – A collection of patterns mined from discovery protocols.
- Security Patterns
- Remoting Patterns – Covers patterns identified in distibuted object middleware.
- Conversation Patterns – Covers two-party to multi-party interactions.
- Service Interaction Patterns – Similar to the previous collection.
- Workflow Patterns – More of a exhaustive list of constructs used in defining workflows from control-flow, data, resource and exception handling perspectives.
- Correlation Patterns – Correlation mechanisms
described as a grouping atomic message events into conversations and processes.
- Reverse Proxy Patterns – Very relevant in addressing service isolation and protection.
- Contracting Patterns
I’ve taken the trouble to comb through these patterns and to identify which ones lead to improved intrinsic interoperability. One of the challenges in developing a pattern language is the creation of a categorization that covers the entire collection.
Service Identification Patterns
- Dynamic Discovery – When a Service joins a network it might not have any knowledge about which other Services are available.
- Absolute Object Reference – The notion of an identifier to a service that can be exchanged by other services and used to invoke the original service is a key ingredient for Service mobility.
- Lookup – A Service is selected based on the query of Services in a directory. Provides an additional layer of indirection in identifying services.
- Referral – A Service is selected based on the consultation of a Services. The difference with the previous is that another service is responsible for making the selection.
- Proxy – A service communicates with another service that id does not have the identity of or is unreachabable.
Service Dependency Patterns
- Termination Notification – A mechanism to indicate when a Service becomes permanently unavailable is necessary to manage the evolution of Services.
- Lease Renewal – This is mechanism is similar to the original, however the onus is placed on the consuming service to renew its dependency.
- Reminder – Removes the requirement for a Service to maintain its own scheduling service.
Service Extension Patterns
- Invocation Interceptor – Provides the capability of dynamically introducing new Service functionality.
- Invocation Context – Permits new Service functionality to be added that is dependent on invocation context rather than Service definition
- Protocol Plug-in – Provides a explicit mechanism for introducing a new communication protocol to an existing Service.
- Location Forwarder – A specialization of Invocation Interceptor where the Forwarder sends an invocation to another Service.
- Delegation – Where a Service allocates a task previous allocated to it to another Service.
- Escalation – Where a Service attempts to progress a work item that has stalled by offering it to another Service.
- Deallocation – Where a Service makes a previously started task available for offer and subsequent distribution.
- Reallocation – where a Service allocates a task that it has started to another Service. Can be stateful where the current state of the task is retained, or stateless where the task is restarted.
- Suspension/resumption – where a Service temporarily suspends execution of a task or recommences execution of a previously suspended task.
Service Negotiation Patterns : The Customer and Performer negotiate until they reach an agreement (commitment) about the work to be fulfilled.
- Receiver Cancels – Receiving Service can cancel within certain timeframe.
- Sender Cancels / Contingent Request – Sending Service can cancel within certain timeframe
- Binding Request – A sending party sends an offer that it will agree to to if the receiving party accepts.
- Binding Offer – A sending party request an offer that will responded to by an offere by the receiving party.
- Resource-Initiated Allocation – The ability for a resource to commit to undertake a work item without needing to commence working on it immediately.
- Resource-Initiated Execution – Offered Work Item – The ability for a resource to select a work item offered to it and commence work on it immediately.
- Resource-Determined Work Queue Content – The ability for resources to specify the format and content of work items listed in the work queue for execution.
- Selection Autonomy – The ability for resources to select a work item for execution based on its characteristics and their own preferences.
Service Performance Patterns: The Performer fulfills the agreement.
- Role-Based Distribution – The selection of a service to perform a task is based on the role of a service.
- Deferred Distribution – The selection of a service to perform a tasks is deferred to the time of the the request.
- Case Handling – The selection of a service to perform a task is based on the case of the request.
- Capability-Based Distribution – The selection of a service to perform a task is based on the capability of the service.
- History-Based Distribution – The selection of a service to perform a task is based on a Service handling history.
- Organisational Distribution – The selection of a service to perform a task is based on the relationship of the service with other services.
- Two Phase Execution – A service sends plan information prior to the start of execution.
- Prepare to Start / Start – A service waits for a permission to start prior to the start of execution.
- Interleaved Parallel Routing – A partial ordering of tasks are defined and can be executed in any order that conforms to the partial ordering.
- Deferred Choice – A point in a process where one of several branches is chosen based on interaction with the operating environment.
Service Reporting Patterns – The performer reports on the status of the execution of the agreement.
- Fire-and-Forget – Invoke a Service without expecting a response.
- Request-Response with Retry – Invoke a Service with the expectation that a retry does not alter the semantics of the previous invocation.
- Polling – Periodically invoke a Service to derive status.
- Subscribe-Notify – Subscribe to a Service to receive future notifications.
- Quick Acknowledgment
- Sync with Server – Provide a mechanism to synchronize with a Server’s data.
- Result Callback – Provide a mechanism for the invoked Service to asynchronously return a response.
Service Acceptance (Satisfaction) – The Customer evaluates the work and either declares satisfaction or points out what remains to be done to fulfill the agreement.
- Compensating Action
Clearly there’s a lot of interesting literature out there that can provide a lot of insight into the interoperation of Services. The above list is just a rough sketch and I’m hoping to provide a more cohesive set over time.
TBD: Conversation join, Conversation refactor, Initiate conversation, Follow conversation,
Leave conversation, Atomic consumption.