Thursday, March 27, 2008

Decomposing Services

In my last post, I discussed how a service exposes one or more endpoints. But how many endpoints should a service expose? What is the rationale for exposing more than one endpoint?

The purpose of a service endpoint is to provide access to functionality exposed by the service. The functionality exposed is determined by the syntax and semantics of the messages exchanged via that endpoint.

The binding/policy of the endpoint determines the service level agreements (SLAs) (such as messaging reliability and performance) upheld by the service, as well as the demands made of the consumer in order to successfully communicate with the service (such as message security).

A service may be decomposed into multiple autonomous components. This is not a component in the traditional sense. That is, it is not a single .NET assembly or Java package. It is an entire horizontal partition of a service. An autonomous component comprises an endpoint, business logic and data. To the consumers of a service, it is assumed that no data is shared between the autonomous components of a service.

Being part of the same service, autonomous components may share the same domain model, and consequently may share the same database schema. That being said, they may or may not in fact share the same physical database. If they use different physical databases, those databases may or may not share the same schema.

So for example, we may have one autonomous component responsible for dealing with standard customers, and another responsible for dealing with VIP customers. Although the functionality exposed by each component may in fact be identical; by separating the service into two autonomous components, we give the ability to provide different SLAs for service consumers dealing with VIP and non-VIP customers. For example, we may use an unsecured HTTP transport for the non-VIP customers, and a secured MSMQ transport for the VIP customers.

Note that the VIP and non-VIP customer data although sharing the same structure and business rules, are not in fact sharing the same physical data. If the two autonomous components were to share the same database, we would be dealing with separate database records for the VIP and non-VIP customers.

As another example, we may decide to have separate autonomous components for different product lines supported by a service. In this case, each component would likely have a different domain model (and database schema); although there may be some structural aspects in common.

For instance if we were dealing with different insurance product lines, we may have information common to every policy across all product lines in a table whose structure was common to every autonomous component; while maintaining the flexibility to have independent structures for each product line in tables whose schemas are not shared between autonomous components.

In conclusion, there is no value in arbitrarily exposing multiple endpoints for a service. But rather we should define multiple endpoints where there is a need for decomposing a service into autonomous components, assigning each autonomous component its own endpoint.