Enabling Aspects to Enhance Service-Oriented Architecture
by Kyle Huntley and David San Filippo, Avanade
Summary: One of the biggest hurdles to achieving true service orientation is separating the needs of the service from the needs of the application. While services should only be concerned with the business functionality that they are exposing, it is not unusual for application specific features to "leak" into the service layer. We can now overcome the difficulties that have prevented widespread adoption of aspects in practical implementations and enable architects to factor out cross-cutting concerns from the services they are designing.
Service-oriented architecture has reborn a vision of the future: systems where business functions are connected like Lego blocks, replaced like interchangeable parts; systems where traditional integration challenges become trivial. In our evolution toward this vision we face many challenges, with reusability being fundamental among them. Services with limited reusability only cloud the service-oriented vision. This article discusses how aspect orientation helps architects design reusable services to achieve that vision.
Separation of concerns says each part of an application should have one clearly defined responsibility. This concept is fundamental to reusability: If the context of a usage scenario "leaks" into the service implementation, then the service is only reusable in that context. Hindsight informs us of this well when we consider some of the reuse failures during the OO wave.
When designing for service orientation, services should ideally represent a self-contained business function with a well defined interface and binding. In practice however, services are found in many contexts with varying concerns. Services exist between operational systems, enterprise components, choreography components, and presentation components; services are clients and servers for other services, up and down the layers of an application, and across network boundaries. Indeed the very idea of an "application" begins to blur.
Aspect orientation provides an excellent approach to separation of concerns. Aspects are a way to organize system behavior in which common "orthogonal" functionality is factored out of the system's "core concerns". Aspects are then applied at points in the application to supply the desired behavior. An example is a logging aspect that logs a time-stamp when a function is invoked. Adopters will attest to the power of aspects in terms of productivity and code and defect reduction.
Although there are many implementations available, and despite its enormous potential, aspect orientation has not had widespread uptake due to a number of difficulties in their implementation:
The ideal aspect is "orthogonal" to the target functionality, meaning that nothing the aspect does will affect the rest of the system. Unfortunately, if you assume aspects are truly orthogonal then there really aren't many interesting aspects. For example, caching and authorizing are powerful aspects, but you wouldn't want your caching aspect to operate before your authorization aspect…
Aspects in typical implementations have visibility problems. Aspects can be deployed throughout an application. In many cases looking at code one cannot infer whether aspects will be involved in its execution.
Since aspects are applied orthogonally, they cannot be aware of their execution context. Different contexts would have widely different needs, but the aspect can't know that. This leads to one-size-fits-all aspects or a proliferation of special purpose aspects.
Do these problems prevent us from using aspects to achieve truer service orientation and better reusability? Emphatically No! In fact, these "problems" lead us to the characteristics of a service-aspect wedding that can only be described as harmonious.
To solve the orthogonality problem, we deploy aspects in ordered sets. This allows the scope and interaction of all participating aspects to be understood and validated ahead of time. Also, we place aspect-set invocation syntax directly onto the affected classes, so only one well-known set of aspects can apply.
By relaxing the orthogonality constraint, we can use a wide variety of aspects including: instrumentation, authorization, caching, validation, exception handling, impersonation, and transaction management. This suite of behaviors represents a great deal of code that simply does not need to be written.
The specific aspect-set invocation syntax mentioned previously helps significantly with the visibility problem, but we restrict aspects to service boundaries to solve it. Service boundaries are where we expect "things to happen" and it is only natural to expect application infrastructure, aspects, at the same boundary.
By solving the visibility problem, we can deploy a wide range of powerful behaviors as "policy," freeing developers from a host of concerns that are tedious, error-prone, and ancillary to delivering primary system functionality.
To solve the context problem, our aspects are configurable, their behaviors specialized through XML files consumed at run time. This gives them a full range of behavior, without making every case the general case or creating a host of more focused aspects.
Figure 2 (Click on the picture for a larger image)
By solving the context problem through configuration, we can manage an application's aspect behaviors through a validating GUI. Aspects can be changed across a group of services, or added incrementally as requirements become understood, without touching code.
In addressing the challenges of aspect orientation, we have removed obstacles to achieve service reusability, and taken a step on the path toward the service-orientated vision.
Kyle Huntley is Chief Architect, Avanade. David San Filippo is Solution Developer, Avanade.
This article was published in the Architecture Journal, a print and online publication produced by Microsoft. For more articles from this publication, please visit the Architecture Journal website.