The Service Granularity Matrix
Like most things relating to Enterprise Architecture, the answer to the question of how to design a Service in a Service-Oriented Architecture (SOA) is “it depends”. One of the most frequent questions that we, and most enterprise architects, often address is how big a Service should be. This question is reminiscent of the issue many developers grappled with as they transitioned from procedural programming approaches, in which a single program encapsulated one application, to object-oriented forms of programming in which developers separated logical units of application functionality into objects that provide capabilities of encapsulation, inheritance, polymorphism, and the other wonders of object orientation.
Just like many budding developers, for me, learning the programming language required to build objects wasn’t the problem. Rather, my brain cramp came from wondering exactly what an object was. Is it just one big program wrapped up in an object? Is it just a bunch of functions that used to be procedural, now encapsulated as objects? After months of brain cramps and headache, the light bulb finally turned on. Objects are a form of abstraction that differ from the concept of procedural code, but doesn’t replace it — it simply offers a new way of organizing and consolidating functionality. I quickly realized that simply creating objects didn’t make something object-oriented. And as such, simply creating Services doesn’t make something Service-oriented. Indeed, it’s the change in thought and approach that represents the Service orientation movement, not the development of a handful of Services.
For many, this movement to Service orientation offers brain-cramping, mind-bending thought patterns around how the Service concept differs from the object concept. A Service is not simply an object exposed with a standards-based API or just another way of doing object-oriented programming “in the large”. Indeed, just as object orientation offers a different level of abstraction and thought from procedural programming, Service orientation offers a different level of abstraction and thought from object-oriented development. Indeed, the Service-oriented movement is not a technology one at all! It is a business-oriented movement where the abstractions are the very abstractions that relate to how a business considers the ever-changing and continuously heterogeneous aspects of its organization and how they can be composed in a loosely-coupled manner to allow for flat and predictable cost of change. This means that we have to rethink the way in which we approach IT capabilities, not simply expose the same assets in the same way using a new interface or middleware.
Fine vs. Coarse-Grained Services
Just as object orientation brought the issue of encapsulation to the fore (but didn’t invent the concept), Service orientation highlights the challenge of granularity. As we defined in our Solving the Service Granularity Challenge ZapFlash, the concept of granularity is a relative measure of how broad the interaction between a Service consumer and provider must be in order to address the need at hand. In the industry parlance, a fine-grained Service addresses a relatively small unit of functionality or exchanges a small amount of data. In contrast, a coarse-grained Service abstracts larger chunks of capability within a single interaction. As can be observed by the way these two concepts are describe, these term are not absolute. There is no single measure for fine-granularity or coarse-granularity. Rather, the measure applies in relation to the Services available and the number of interactions required to accomplish a specific goal.
Yet, this concept of granularity is incredibly important to the enterprise architect because it has a direct impact on two major goals of Service orientation: the composability of loosely-coupled Services, and the reusability of individual Services in different contexts. Before an architect can go about designing a Service Contract, they must first somehow come up with the requirements for that Service. As we discussed in the Right-Sizing Services ZapFlashand in numerous other white papers and writings on this subject, an architect has two general approaches to identifying Services: starting from the business-process or a business model and decomposing that into sub-processes or sub-models recursively until some condition is met by which it can’t be decomposed any further. Alternatively, an architect can start from the IT systems already implemented, expose Service interfaces from the APIs and access points that already exist, create Service Contracts on top of those interfaces, and then compose them together until the business process requirements are met. While top-down approaches are generally favored to achieve the “right” level of granularity, in reality, proper Service-oriented approaches combine both top-down and bottom-up in a continuous and iterative manner.
We discussed the top-down and bottom-up approaches in our Should All Services be Reusable ZapFlash, and the main conclusion is that a business should be able to find many ways to compose that Service into different Service-Oriented Business Applications (SOBAs). Such composability is where the true business value of SOA lies, and is a guide for architects trying to figure out the appropriate level of granularity.
In this analysis, an architect might realize that a particular Service should be designed at a fine level of granularity to give it the greatest amount of reuse across multiple process scenarios. Alternatively, the architect might realize that a particular transactional or efficiency requirement could require a coarser level of granularity. In essence, architects have to balance flexibility against efficiency to help determine granularity.
Atomic vs. Composite Services
Yet, granularity is not the only measure of a Service’s applicability. Indeed, one of the core tenets of Service orientation is that any collection of Services can be composed together to create a new Service. In the industry parlance, we call such Services composite as opposed to atomic Services, which abstract only the implementation of the Service, rather than a composition. However, this definition is quite murky. What might seem to be atomic in the eyes of a Service consumer since it appropriately has no visibility into the implementation of that Service might actually be composite from the perspective of the Service provider. Indeed, to all Service consumers, the Service appears as atomic even if it might be composite. The only way to definitively know if a Service is composite is for a Service consumer to inspect some declarative logic that identifies specifically how a Service is composed. Of course, for a Service consumer to be required to have that visibility violates the rule of loose coupling. No Service consumer should be required to know how a Service provider is implemented, lest there be a change to how the Service is implemented.
However, the concept of atomic vs. composite Services is incredibly important to the enterprise architect. In particular, SOBAs are composed of Services and expose Service interfaces. This means that most SOBAs are composite Services that implement a process. As such, when architects define their business Services in a top-down manner what they are actually doing is defining which activities are implemented as composite Services, and thus must be further decomposed, and which are identified as atomic Services, at which point decomposition activity stops and Service implementation begins. In this light, the concept of Service atomicity is an architectural activity. From an implementation perspective, one could implement composite Services using emerging Service composition metadata languages and runtime tools, while atomic Services could be implemented using platform-specific approaches. However, this is not a hard-and-fast rule.
Evaluating the Service Granularity Matrix
While at first blush it might seem that all atomic Services are fine-grained and composite Services coarse-grained, this is not necessarily the case. Since granularity is a measure of interaction and business appropriateness, and atomicity is a measure of process decomposition, it is quite possible to have coarse-grained atomic Services and fine-grained composite Services. As a way of explaining how this might come about, consider the below Service Granularity Matrix:
In this evaluation, one could have coarse-grained Services that are in fact atomic because there’s no way to decompose them further. Perhaps they originated from a mainframe and the lowest level of granularity you can get is still too coarse. This does not make the Service composite. Likewise, consider a case where a Service has been built to provide a small part of a large interaction, and in this consideration it is fine-grained, yet the Service itself is composed of other Services at the same level of fine granularity. This might especially be the case in situations where the Services are supporting business processes in multiple contexts, such as fine-grained telephony Services that are themselves composed of atomic Services exposed from legacy assets.
The chart also implies that fine-grained Services are highly reused, but this is not really always the case, just as coarse-grained Services are not guaranteed to be business oriented. Once can even argue that while fine-grained services may be more reusable, if they’re too fine-grained, that reduces their reusability, because they might tend to have too narrow a use, just as Services that are too coarse-grained are so constrained.
The ZapThink Take
This decoupling of granularity from atomicity frees the enterprise architect from having to consider them together, and enables the creation of a wide range of business- and implementation-appropriate services that consider the full scope of Service requirements. Indeed, a proper Service-oriented analysis and design approach considers separately the issues of granularity and atomicity with respect to five key aspects: reusability, efficiency, transactionality, consumability, and visibility of the Service. What might at first seem to be a composite Service from the perspective of reusability might actually need to become atomic due to reasons of transactionality. Likewise, what might seem to be fine-grained for the purposes of visibility and auditing might become coarse-grained for reasons of efficiency. Indeed, the Service granularity matrix serves as just another tool in the belt of the effective enterprise architect.