The SOA tenets originally appeared back in 2004 when Don Box published an article on MSDN called “A Guide to developing and Running Connected Systems with Indigo” (Indigo is what’s known today as Windows Communication Foundation or WCF for short). Don Box wrote that WCF is based on SOA principles and that unlike other approaches, specifically object orientation, SOA requires a different set of assumptions:
In Indigo, a service is simply a program that one interacts with via message exchanges. A set of deployed services is a system. Individual services are built to last—the availability and stability of a given service is critical. The aggregate system of services is built to allow for change—the system must adapt to the presence of new services that appear a long time after the original services and clients have been deployed, and these must not break functionality.
Although Microsoft have pledged to keep the MSDN Magazine online at the time of writing the article linked above is not available.
Service-oriented development is based on the four fundamental tenets that follow:
- Boundaries are explicit
- Services are autonomous
- Services share schema and contract, not class
- Service compatibility is determined based on policy
Let’s go over what that means in terms of modern REST services.
Four Tenets
Boundaries are explicit
Services interact by sending messages across boundaries. These boundaries are formal and explicit. No assumptions are made about what is behind boundaries, and this preserves flexibility in how services are implemented and deployed.
This means that:
- You must treat all services as external to you
- Internal (private) implementation details should not be leaked outside of a service boundary
- Avoid RPC interfaces because this can lead to an overuse of calls – accessing a service is not the same as accessing a local object
Services are autonomous
Services are not subservient to other code: a service reacts to a message – how that message was created and what will happen to any response the service creates is immaterial to the action that this service will take.
This means that:
- Deploy and version services independently from the clients
- Design contracts with the assumption that once published, they can’t be modified
Services share schema and contract, not class
Only messages pass from service to service, code does not.
This means that:
- Contracts should be designed to be as explicit as possible to minimize misinterpretation
- A service must be able to convert its native data types to and from some technology-neutral representation
- The contract must be versioned using semantic versioning
Service compatibility is determined based on policy
A service must be able to express in a standard representation of policy what it does and how clients should communicate with it.
This means that:
- The policy must be exposed using an Open API Specification