Sunday, June 1, 2008

Überservices are Bad

Continuing on my recent theme of coupling and cohesion, I'd like to take the opportunity to discuss a somewhat common SOA anti-pattern, the überservice. This is where we put too many concerns into a single service.

So why is this a problem? Why not put everything into a single service? In order to understand this, we need to consider one of the core values of SOA; that being that SOA draws boundaries between systems that enforce certain constraints between them, creating zones of autonomy and loose coupling.

Loose coupling between services is in part a result of the architectural style itself mandating that we have dependencies between services limited to the exchange of messages conforming to well-defined service contracts. Services have no visibility of or dependency on the implementation details of other services.

We get additional loose coupling through asynchronous communication between services (preferably publish-subscribe), eliminating data centric interfaces, decentralising our data and designing our services such that we have high cohesion within services. All this is achieved by designing our services such that they are self-contained and process-centric.

Each service controls its own data. Services are unable to directly access or manipulate data held by other services. This gives each service the freedom to represent its data locally in the way most suited to supporting the business processes that execute within that service.

As we expand the scope of a given service, the data model and the corresponding logic that executes on it becomes increasingly confused and complex. If we expand the scope of a service far enough, then we have unfettered access to any data by any component in the entire enterprise. That is, we have chaos.

Service boundaries control this complexity. We must draw them up such that we have appropriate service granularity in order to minimise coupling and maximise cohesion.

Many business processes within an organisation by their very nature are loosely coupled. That is, they do not share data directly. For example, when a customer inquires about an insurance policy, his or her details become known to the Sales department at that time.

However, until they actually proceed with purchasing a policy, their details are not known to the Underwriting department - and nor should they be. The Underwriting department doesn't care about prospective customers.

If we implement both the Sales and Underwriting processes as part of a single service, then we have data being shared between these two loosely coupled processes in an uncontrolled way, which now couples these two processes. If we need to make a change to one of these processes, the other will likely be affected.

So, drawing service boundaries between systems supporting cohesive business areas provides better alignment between the business and the systems that support it. When done properly, we end up with loose coupling between services such that our overall architecture is simplified, and we minimise the risk and impact of changes to systems in our enterprise.