- Services should be deployed, managed and versioned independently of other services and / or applications that depend upon them.
- Services should not trust any incoming messages. All messages should be validated for integrity and appropriate credentials.
- High availability of services should be ensured using a fully redundant network infrastructure that supports automatic failover etc.
- Careful consideration for capacity planning should be made to ensure appropriate provisioning of resources necessary to support services.
- Services expect that the consuming application can fail without notice and often without any notification. To maintain system integrity techniques such as transactions, durable queues, and redundant deployment and failover should be utilized. (The same applies to services used by the service as well)
- The physical location of the targeted service may be an unknown factor.
- Security and trust models are likely to change with each boundary crossing.
- Marshalling and casting of data between a service’s public and private representations may require reliance upon additional resources—some of which may be external to the service itself.
- While services are built to last, service configurations are built to change. This fact implies that a reliable service may suddenly experience performance degradations due to network reconfigurations or migration to another physical location.
- Service consumers are generally unaware of how private, internal processes have been implemented. The consumer of a given service has limited control over the performance of the service being consumed.
Since crossing service boundaries is explicit, services should make this explicit by using messages for communication instead of trying to hide the boudary crossing by imitating a distributed RPC. RMI, Remoting, DCOM take the later route.
A message style communication looks like this (via Rich Turner):
Channel chan = new ChannelFactory.CreateChannel(endpointAddress);
ActionInvocationMessage msg = new ActionInvocationMessage();
msg.Action = "SayHello";
msg.Parameters.Add(new StringParameter("Forename", "Rich"));
msg.Parameters.Add(new StringParameter("Surname", "Turner"));
Console.WriteLine(chan.SendMessageSync(msg, new SayHelloCallback(HandleResponse)));
An RPC Style communication looks like this:
HelloWorldProxy proxy = new HelloWorldProxy(endpointAddress);
Obviously a hello world doesn’t need to be a service and hence the messaging style communication looks awkward. But you should understand explicit message passing now 😉
A corrollary to this tenet or another interpretation of the tenet is "A service with well defined boundaries should provide no visibility to the internal implementation of the service. This allows a services implementation to be versioned without breaking external systems."
For Example "Service implementation details such as internal database row identifiers commonly found within a dataset should not leak outside the boundary of the service. "
More stuff here:
- The endpoint is down for maintenance each Sunday morning from midnight until 2:00 AM.
- Orders must be received within 30 minutes of their timestamp. Orders delayed in transmission more than 30 minutes will be discarded, and the application may return a Fault.
- US dollars and euros are the currencies supported by the service.
Hope this makes the ‘P’ of PEACE clear. Bye till we talk about the ‘E’ in the PEACE.