One of the questions I get asked rather frequently in my travels is how many services are appropriate in any given architecture? Well this is one of those unfortunate situations where the answer is, it depends. However there are some good rules of thumb that can lead you to determine whether you're on the right track in terms of defining your service model.
In the field, the number of services we see in any given enterprise tends to vary wildly. In some organisations there is only one service - the überservice. Other organisations have stated they have well over 10,000 services. But how good are these architectures? As I've previously stated just because an architecture is service oriented doesn't make it good.
We've discussed überservices before and they are clearly not a good thing. So we definitely want more than one service. But 10,000? How on earth did they achieve that figure? Well at the end of the day the number of services you'll end up with is largely determined by the granularity of your services. Fine grained services will result in more services than coarse grained services. We've discussed service granularity before too.
Ultimately the number of services you end up with will largely be determined by the flavour of SOA you pursue. If you take the JBOWS approach (not recommended), then you could end up with any number of services. You're building services in a completely uncontrolled way that doesn't conform to any particular architecture. Usually the longer you follow this path, the more services you'll end up with. Hopefully you stop before you reach 10,000.
If you go down the road of Service Oriented Integration then you'll end up with the same number of services as you have applications you are trying to integrate. If you have 400 applications in your enterprise, you'll end up with 400 services. Again, I wouldn't recommend this approach.
Layered service models have to take the prize in this competition. Due to the incredible fine granularity of services in this model you can literally end up with thousands of services! This is yet another reason why I wouldn't recommend this approach.
And finally we have self-contained process-centric service models. With this approach services are centred around process-centric cohesive business capabilities. The number of services you will end up with will depend on the overall complexity of your business model. But about 10-20 services is a good rule of thumb. Any more than 30 or 40 and I'd be raising the alarm bells.
Another thing to note is that the size of the organisation (in terms of staffing levels) is not a major factor in determining the appropriate number of services. The number of services will grow as the complexity of the business model grows. Keep in mind though that sometimes the complexity of the business must grow in order to cater for increased staffing levels.
Wednesday, August 6, 2008
How Many Services?
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.
Monday, May 12, 2008
Service Granularity Example
A while back, Ayende posted a proposed service model based on an example business context provided by a reader. This provides a good example for discussion around service granularity. For the sake of brevity I won't repeat the complete details of the example or the solution proposed by Ayende here.
In essence, the business in question is a physician job placement organisation, which owns two separate physician job placement companies. There is about a 95% overlap in business process definitions. That is, the business processes between the two subsidiaries are 95% the same. From an enterprise architecture standpoint, this is an interesting example as it illustrates the importance of the business context in determining the IT architecture.
Firstly, we need to understand whether both of these separate subsidiary companies operate independently, or if there are functions shared between the two. If there are many shared functions, then what we are really looking at here is one company with two brands. If functions are not shared, one needs to ask why this is. Certainly one would imagine there would be plenty of synergistic opportunities for sharing functions, resulting in better efficiencies and cost savings.
If for whatever reason the business wishes to operate these subsidiaries independently (this could be because the business has different long term strategic plans for the future of each business, or simply because they wish each business to be able to operate and evolve independently without influence from the other), then we are looking at two separate SOAs - one for each subsidiary.
This doesn't mean going through the exercise of designing and building two architectures. One would presumably put together a single architecture and then tailor it for each subsidiary. One would develop systems supporting that architecture and simply deploy two instances - one for each subsidiary. Now each subsidiary can now evolve independently.
Now, onto the service model itself. In the example, there are three core functions performed by the organisation - marketing and recruiting (which are performed by the Sales department), and credentialing (performed by the Credentialing department).
In this scenario, we need to understand whether the Marketing and Recruitment business processes have sufficient loose coupling and high cohesion to be implemented as separate services. If these processes share a lot of business logic and the information models of these processes have a lot of similarities, then we should implement a single Sales service to support both business processes. We would probably consider implementing these as autonomous components within the Sales service.
Alternatively, we would implement separate Marketing and Recruitment services. Either way, it seems would should have a separate Credentialing service as this is performed by a different department, so I would assume the Credentialing business process is quite independent from the other business processes.
Ayende's proposed solution however outlined eight separate services. At closer inspection, there appears to be somewhat low cohesion between these services. That is, some of them would likely be described using the same domain models.
In fact, the defined services seem to relate more to operations that may be exposed by a service, as opposed to services in their own right. For example, there is an Available Candidates service as well as a Register New Candidate service. Both of these services deal with candidates, supporting different aspects of the overall Recruitment process.
Consequently with this service model we would likely end up with chatty, synchronous request-reply, data-centric operations exposed by each of the services. Pursuing coarser grained services centred around cohesive business processes as suggested above would deliver a more loosely coupled service model.
Monday, April 21, 2008
Service Granularity
Two key outcomes that we aim for in the design of software systems are high cohesion and loose coupling. Cohesion is the degree to which the concerns within a single software component are related. Coupling on the other hand is the measure of interdependency between software components.
We have discussed many strategies for reducing coupling between services in the past. Examples include decentralising your data, using process centric interfaces, using asynchronous messaging, using document-centric messaging, and avoiding command messages. Furthermore, SOA as a style of architecture promotes loose coupling through the use of service contracts that encapsulate the implementation details of a service behind its boundary.
However one of the largest determining factors of coupling is in fact the level of cohesion found within services.
One way of looking at cohesion is how precise a domain model is at expressing the problem domain. If the domain model contains ambiguities such that definitions become confused, then we have low cohesion. Where we start to lose cohesion with a domain model we look at subdividing the model, which Eric Evans makes reference to with his Bounded Context pattern.
We will then likely have the same entity (e.g. a customer entity) represented in both models, but the representations will see the entity from different points of view, optimised for the subdivided domain model. So for example, we may have Sales and Billing domain models - both involving a customer entity, but seeing it from different perspectives. This would result in a different data structure in both models with different business logic, but both pertaining to the same customer entity.
In SOA terms, when we see the concerns of one service becoming ambiguous and confused, we look at subdividing it into two or more services such that the domain models of each service have high cohesion again. If done correctly, we will find that the new services will also have loose coupling between them, as the concerns between services will be only loosely related.
If we subdivide too far, we will find that information models and business logic become duplicated between services as the relative difference in definition of the same entity between domain models becomes increasingly similar.
So there is a delicate balance with regards to service granularity such that we get the right mix of cohesion and coupling.
There is no magic formula for service granularity. It is simply a matter of iteratively refining your architecture until you have sufficient loose coupling and high cohesion. Where you start seeing the need for synchronous request-reply interactions between services, cross service transactions, CRUD interfaces and duplication of logic and data representation between services, you have subdivided too far and must start combining services.
Where you start seeing confused representations of entities in the domain model of your service, you have not subdivided far enough.