Enterprise Library 3.0 Policy Injection Application Block - Crosscutting Concerns vs. Business Logic in AOP

Enterprise Library 3.0 Policy Injection Application Block - Crosscutting Concerns vs. Business Logic in AOP

by David Hayden ( Florida ASP.NET Developer ), Filed: Enterprise Library 3.0

 

The other day I talked about how much I like the idea of caching being thought of as a crosscutting concern and using the new CachingCallHandler in Enterprise Library 3.0 to neatly tuck away the caching behavior out of my class so that only business logic and rules are exposed:

The use of the CachingCallHandler was described via an attribute but could have easily been tucked away in the configuration file as a policy:

 

 public class NewsController
{
    private INewsService _service;

    public NewsController(INewsService service)
    {
        _service = service;
    }

    [CachingCallHandler]
    public NewsHeadlineCollection GetLatestNewsHeadlines()
    {
        return _service.GetLatestNews();
    }
}

 

Ayende wisely discusses a scenario where the use of AOP can get out-of-hand ( Limitations of Declarative Coding ) and actually hurt the expressiveness of your code by adding business logic into the CachingCallHandler itself. Using his example below, we start adding business logic into the declarative CachingCallHandler as well as writing exceptions to the policy in our code to specify things like how long to cache the object, when to cache the object, any dependencies on the cache itself, and when not to cache:

 

[CachingCallHandler(Expiration="10:00", CacheIfCallOver="0:30",
    DependencyConnectionStringName="MyDatabase", 
    DependencyStatement="SELECT * FROM HeadLines Where
datePublished > getdate()-1
")] public NewsHeadlineCollection GetLatestNewsHeadlines() { if( _service.BigStoryNowDeveloping) CachingCallHandler.Current.SkipCaching(); return _service.GetLatestNews(); }

 

Now as you know, we could hide all this detail and put it in the configuration file, so the “ugliness“ of the code is really a moot point. I think what Ayende is saying and for which I totally agree is that in general AOP is about moving crosscutting concerns out of your application, not business logic / rules.

There is a line where AOP can help you better maintain and express the intention of your code by removing “infrastructure code” that just clutters your domain model. If the line is crossed, however, you will find that the code is more difficult to maintain and understand as you begin to hide business logic and rules inside policies and declarative statements. You may also find yourself writing extra code to compensate for the limitations placed within your policies and declarative statements that could have been better handled inline with normal if, then, and else statements.

I think the documentation for the Enterprise Library 3.0 Policy Injection Application Block nicely describes the intention of the PIAB and AOP in general:

“Applications comprise of a mix of business logic and crosscutting concerns, and the two are typically intermingled - which can make the code harder to read and maintain. Each task or feature of an application is a "concern", and those that implement the features of an object within the application, such as the business logic, are core concerns. Crosscutting concerns are the necessary tasks, features, or processes that are common across different objects. Examples are logging, authorization, validation, and instrumentation. The purpose of the Policy Injection Application Block is to separate the core and crosscutting concerns.”

This clearly signals to me that using AOP to encapsulate and pull out business logic is not the intent. The intent is to remove the distractive crosscutting ( typically infrstructure ) concerns from our business logic that makes code harder to maintain and understand.

In my example, my intention is that there are no business rules associated with the caching of the LatestNewsHeadlines. I expect the news will rarely change and to just cache it for the duration of the web application. New news, if any, doesn't have to be displayed until the application stops and starts up again.

 

[CachingCallHandler]
public NewsHeadlineCollection GetLatestNewsHeadlines()
{
    return _service.GetLatestNews();
}

 

If I wanted more control over cache duration, for example, we start getting into business rules. I don't necessarily object to adding business logic into the CachingCallHandler Declaration, but only if it continues to express the intent of our code and make it more maintainable. Hence, if one wanted to add cache duration to the CachingCallHandler:

 

[CachingCallHandler(Expiration="10:00")]
public NewsHeadlineCollection GetLatestNewsHeadlines()
{
    return _service.GetLatestNews();
}

 

I could go for that. It doesn't take much to grok the intent of this code. As developers, we need to figure out where AOP makes sense and where it starts to cause us pain.

As it turns out, the CachingCallHandler code that I have seen pre-release to Enterprise Library 3.0 does not have any intention of offering you more than what I mentioned in my example. There is no place to add business rules to specify cache duration, cache dependency, and various reasons for when to cache. You can, of course, create a custom cache handler if you want that functionality. However, be aware of making your code harder to maintain and understand by its use.

Update: Tom Hollander mentioned that one will be able to specify the cache duration as part of the CachingCallHandler Attribute in the final release of Enterprise Library.The constructor of the attribute takes 3 integers for hours, minutes and seconds:

 

[CachingCallHandler(0, 10, 0)]
public NewsHeadlineCollection GetLatestNewsHeadlines()
{
    return _service.GetLatestNews();
}

 

Thanks for the input Tom. I like the CachingCallHandler even more :)

 

Source: David Hayden ( Florida ASP.NET Developer )

Filed: Enterprise Library 3.0

 

posted on Tuesday, April 03, 2007 1:21 PM

My Links

Post Categories

Article Categories

Archives

Loose-Leaf Tea