By now, most developers understand the importance of having clearly articulated policies for the typical, infrastructural elements of their design. Patterns-and-practices groups, well-established architecture gurus, and the industry as a whole have done an excellent job of spelling out all those areas where we need to provide cross-cutting solutions for exceptions, logging, authorization, and so on.
In line with this direction, we've stepped up to the plate and started tackling these concepts. Many of us now are building or leveraging off-the-shelf solutions to address all of these fundamental design idioms. Localizing these concepts as much as possible allows us to provide centralized management of our policies and promotes consistency in our approach to each of these concepts.
Of course, establishing these policies is easy. Making sure they are being universally applied and adopted is the hard part. As definitive as we might try to be, there's never a guarantee that every developer on your team is going to implement those policies exactly as you expected. Even the most well-intentioned team member might unknowingly stray from these policies. It's just the nature of the beast.
This aspect of my policies always has troubled me. From my perspective, it seems I must continually watch over the code to be sure that implementation of the system's policies is being consistently applied. And, with some teams, it can be an ongoing cultural battle to get all the developers to incorporate these policies into their own code.
I've been somewhat disappointed in the flexibility of my policies. I've always done what I can to isolate my implementation of these policies as much as possible. However, some policy changes still end up being more invasive than I would like. And, to me, that seems to undermine the whole point of having these policies in the first place.
I knew that the industry had started introducing tools and frameworks to address some of the facets of this problem. For me, though, the value and importance of these tools didn't really crystallize until I discovered Microsoft's Policy Injection Application Block (PIAB). This tool, which recently was added to the Microsoft Enterprise Library (see the
StickyNotes for a link), gave me a much clearer idea about how I could overcome some of the challenges I'd faced with managing, evolving, and enforcing policies.
The design of the PIAB is actually very straightforward. It leverages interception to insert itself between each class and the consumer of that class. So, every time you call a method of a class that has been "tagged" for interception, the framework will intercept that call and invoke any "policy handlers" that have been configured for that specific method.
Let's look at a simple example of what the PIAB allows. In figure 1 I've implemented a fairly traditional Data Access Object (DAO). There's an IAccountDAO interface and a concrete implementation of that interface in the form of the AccountDAO class. This class provides basic CRUD operations for maintaining
In a typical implementation, the underlying code for the AddAccount and UpdateAccount methods (not shown here) would include code to support all common horizontal policies. In this specific case, you'd at least find manifestations of exception handling, logging policies, and authorization in each of these methods.
With the PIAB, however, I'm allowed to move those policies out of these methods. Instead, you'll notice that my IAccountDAO interface introduced "Tag" attributes for each of my interfaces' entry points. Through declaration, these attributes allow me to associate one or more policies with a method. In this case, to demonstrate variety, I associated a logging policy with the AddAccount method and a validation policy with the UpdateAccount method.
Most of this magic is made possible by the use of the PIAB's class factory. In figure 1, you'll notice that my AccountDAO class was constructed by a call to the static ProcessInject.Create<>() method, which takes the interface and concrete class as generic type parameters.
When this method is called, the factory will examine the iterface of the class being constructed. If the class doesn't require any policy injection, the factory simply will return a reference to the requested type. However, if policy injection is required, it will return a proxy for that class. Now, each time the method is called, the policies declared in your interface will be applied.
This is slick enough on its own. However, the really exciting part comes when you start looking at the configuration of these policies. When I associated the "Log" tag with my AddAccount method, the "Log" value simply represented a key into a configuration file that includes the details for how the "Log" policy is to be applied.
The snippet shown in figure 2 provides a view of a pared-down PIAB configuration file. You'll notice that it includes a MatchingRule that is used to capture any method with a Tag attribute that has the value of "Log." Once a match is made, the PIAB then will invoke the items in the handlers portion of the configuration file to process each invocation.
The beauty of this approach is that it allows me to fully configure the behavior of my policies outside of the method. So, when I'm building a system, the team needs only to agree on the tags to which we want to apply our horizontal policies. And, once those tags are applied, I then can oversee the management and execution of the policies in complete isolation. In fact, I can change those policies without requiring a rebuild of the application.
While I've shown only the simplest of cases here, the PIAB actually supports a fairly extensible and flexible model configuration scheme. These configuration options allow developers to define a series of matching rules that can be chained together to express complex policy conditions that can be executed on entry or exit of a given method.
Of course, now that you have this ability to configure your horizontal policies, you need a nice tool to manage those configurations. Fortunately, the PIAB introduces just such a tool. This editor certainly simplifies the editing and maintenance of policies.
Seeing this framework in action really pushes my buttons. While I've always talked about the "separation of concerns," I can't say I really understood how far one could go with that concept. Even though I was isolating my policies, I wasn't achieving real separation. Developers implementing my policies still had to be aware of my policies and how to apply them properly. With the injection model, I can achieve a much more concrete separation that allows policies to be established, managed, and evolved entirely in their own
In the broader sense, the PIAB is forcing me to step back and reconsider how and what I might apply as a horizontal policy. It also has made me anxious to dig deeper into the details of AOP and other frameworks to see how their approaches to this problem might shape my perspective. This model certainly has changed how I attack the design of any cross-cutting concerns.
Does injection seem like a reasonable approach to isolating your cross-cutting policies? How might you leverage injection in other areas of your solutions?
Join the conversation below or start a new one in the Reader Comments section.