It is always encouraging to see that we're making steady progress toward a deeper understanding of Service-Oriented Architecture (SOA). One of the clues that we're making progress is that we are increasingly fielding questions regarding architecture, rather than implementation or infrastructure. At a recent conference, for example, we were quite encouraged when someone asked the question, "should all services be reusable?"
On first glance, this question has a straightforward answer. After all, since one of the goals of SOA is to build reusable services, then why shouldn't all of them be reusable? But upon further reflection, answering this question properly requires greater subtlety as well as deeper architectural thinking. This ZapFlash, therefore, not only explores the answer to this question, but also illustrates what we mean by deeper architectural thinking.
The question as to whether all services should be reusable leads to two further questions, and which question you ask depends upon whether you are thinking about architecture in a top-down or bottom-up fashion. The top-down approach to SOA starts with a picture of all the business processes within an organization, and then looks to decompose those processes with an eye toward identifying areas of redundancy that indicate likely service candidates. Since this top-down approach focuses on meeting business objectives and increasing efficiency through reducing redundancy, and hence increasing reusability, the key question architects should ask is whether maximizing reusability is always the most important best practice, or whether there are other priorities that the architect should consider as well.
In fact, while reusability is one of the most important criteria for determining which services to build, there are other criteria that architects must consider as they go about meeting ever-changing business requirements through the SOA abstraction. In particular, the evolvability of services is a criterion every architect should consider. There may be services that realistically have only one application, but may nevertheless experience ongoing requirement change. In other words, there are situations where agility rather than reusability is the driving force for service design. While a particular Service might only have one consuming application, the fact that it is subject to continuously changing requirements dictates the design of the service more so than its reusability. In such cases, it may be cost-effective to put in place the overhead necessary to ensure the required loose coupling for such services, even though they may each only have one consumer.
Another example where reusability may not be the top priority for service design is where loose coupling due to the contracted nature of the interface itself is the priority, especially in a business-to-business (B2B) situation. Two business partners trying to improve their automated interactions may be struggling with implementation-specific limitations (getting a Java-based application at one company to interact with a mainframe-based app at the other, for example). In such a case, building Services with contracted interfaces that abstract the underlying implementation may ease such interactions, even if such services are only valuable for that single, point-to-point interaction.
Taking the opposite tack to top-down thinking, the bottom-up approach to SOA starts by looking at existing IT capabilities in the enterprise as the starting point for developing services that expose the existing functionality an organization already depends on. One of the key challenges that architects face in this scenario is how much of the existing functionality they should expose as services, and at what level of granularity. If reusability is the primary driver for identifying areas of service enablement, then it follows that some existing IT functionality may never end up as a service. The challenge then is to determine which functionality should be exposed as services, and more generally, prioritizing the service enablement of existing functionality.
One way to get at solving the above challenge is to leverage a useful rule of thumb: the 80/20 rule, which states that 20% of the existing functionality in any given system will be used 80% of the time. The remaining 80% of the functionality handles special cases, exceptions, and other low-use scenarios. And while the greatest use doesn't necessarily mean the greatest reuse, service-enabling that 20% is likely to lead to the greatest level of reuse as a rule of thumb. Clearly, if an architect can identify the 20% of existing IT systems with the heaviest use, service-enabling that portion of your functionality will provide the business its biggest bang for the buck, partly by easing access to the functionality, but even more significantly, by enabling broader reuse of that functionality as well. There may be reasons to service-enable other IT assets, to be sure, but it's less likely that reusability will be the primary driver for that follow-on enablement. In other words, func tionality that is potentially less reusable is a lower priority for service enablement.
Architecting for proper granularity
Of course, experienced architects know that neither the top-down nor bottom-up approach alone is adequate. The top-down approach by itself is likely to identify services that aren't cost-effective to build, and the bottom-up approach alone risks producing redundant, ungoverned Services. A core SOA best practice, therefore, is to take an iterative approach that switches from top-down to bottom-up and back again, improving both the architecture and the services with each iteration.
Let's work through an example of iterative SOA that also sheds additional light on the question of this ZapFlash. Let's say we've defined (or already created) services 1 and 2 that are compositions of individual Services, as illustrated in the following diagram:
1 = A ⇒ B ⇒ C ⇒ D ⇒ E 2 = F ⇒ B ⇒ C ⇒ D ⇒ G
As an architect you're wearing your top-down hat, so you notice that services 1 and 2 each share the composition of fine-grained services B, C, and D. So in the next iteration you specify the coarser-grained service 3 as follows:
3 = B ⇒ C ⇒ D
Which enables you to redesign 1 and 2 as follows:
1 = A ⇒ 3 ⇒ D 2 = F ⇒ 3 ⇒ G
You've followed the familiar agile principle of refactoring out redundancy, yielding simpler, easier to maintain definitions for services 1 and 2. But here's the key question: is service 3 more or less reusable than services B, C, and D? In fact, Service 3 will generally be less reusable than B, C, and D, because in the general case, these finer-grained services will be reusable in a broader set of situations than the coarser-grained service 3, because it's possible to consume B, C, and D separate from one another, while consumers of service 3 are expecting B, C, and D together.
Nevertheless, it will make sense to leverage service 3 in this way, when service 3 is more business-oriented than B, C, and D separately. Coarse-grained services are more likely to be business-oriented than fine-grained ones, and finding that service 3 has a clearer business value than B, C, and D is sufficient motivation for building service 3. After all, services B, C, and D are still around, and if someone needs them in the future, they're reusable as well. But because service 3 is coarse-grained and business-oriented, it will be more composable than services B, C, and D.
Also keep in mind that service 3 is still reusable, just not as reusable as some other services. And remember, you're not simply architecting for today's services, but you're architecting to enable the business to recompose services as necessary to meet tomorrow's requirements, as well. The fundamental architectural principle to keep in mind here is that coarse granularity can be more important than reusability when the level of granularity improves the composability of the Service.
The ZapThink takeNot only have we added shades of subtlety to the question of whether services should be reusable, we've also put a fine point on the definition of reusability itself by distinguishing it from composability. This distinction is subtle because, after all, composition of services can be a form of reuse whenever it's possible to compose one service into multiple processes. Understanding the difference between the two concepts, however, goes right at the heart of understanding SOA itself.
A service would clearly be very reusable if there were a million service consumers out there making regular use of the service -- and that would be a good thing, to be sure. But that service may not be composable if business users aren't able to find a way to incorporate it into composite applications that implement service-oriented business processes (known as Service-Oriented Business Applications, or SOBAs). If a Service is truly composable, therefore, then the business should be able to find many ways to compose that Service into different SOBAs. Such composability is where the true business value of SOA lies.