Showing posts with label Aspect Oriented Programming. Show all posts
Showing posts with label Aspect Oriented Programming. Show all posts

Saturday, March 7, 2009

Decorator pattern: alternative to using AOP?

I've wanted to check out some of the Aspect Oriented Programming frameworks out there just to get a feel for how they behave in the code. I understand the paradigm and the vocabulary but I haven't really played around with it. AOP is one of those things I keep promising myself to check out but I always put it off. Now I'm finally sitting down to check out what's around and how it would fit in with my day-to-day.

If you're an AOP framework you're generally implemented in one of two ways; either you're compile-time and the code is "weaved" into the class of choice or you're runtime and a proxy is generated for the class in question. Basically, you're looking to attach some behavior to a class that will happen before a method call, after a method call or when an exception is thrown.

AOP being a tool in my six-demon bag, I have to see how it can improve any of my current projects. Right now, I only have the ubiquitous logging issue that is commonly mentioned in the same breath as AOP. The usual problem is thus; you have some component who's main concern is not logging wonderfully verbose diagnostic information but rather that it builds a list of accounting records for export to a general ledger or it's approximating how late an MBTA train can be before the commuting populace riots. To keep the gods of Truth and Beauty satisfied you must separate these concerns.

My only problem is that I may have already. I hadn't seen it done this way before but I was using the decorator pattern to effectively perform the same work that an AOP framework would. I had fallen into using decorator pattern recently to eliminate inappropriate inheritance (just about any inheritance is inappropriate to me but that's a topic for another post). Think of it this way; the AOP framework is providing a mechanism to intercept method calls and do some magic before or after the a method is executed. The decorator pattern is doing just that. I'll break down the pros and cons for using an AOP framework or using the decorator pattern in a moment but here's a code snippet to demonstrate the thought.

NOTE: For the sake of brevity I'm hoping you can make logical leaps about the types and classes I'm using. They're purely fictional and they're not what's important.

public interface IComicBookRepostitory
{
ComicBookCollection GetComicsBy(SearchParameters searchParams);
}

An IComicBookRepository is simply a repo for comic books. In this case it has a method for retrieving comic books by a set of parameters. The concrete class for the repo looks like the following.

public class ComicBookRepository : IComicBookRepostitory
{
public ComicBookCollection GetComicsBy(SearchParameters searchParams)
{
return new ComicBookCollection();
}
}

This class obviously does nothing of import but that's ok. We can fill this in with whatever we please when we know what that implementation will look like.

I can create a class that will "decorate" any instance of IComicBookRepostitory with error logging. Hence the LoggedComicBookRepository.

public class LoggedComicBookRepository : IComicBookRepostitory
{
private ILog _log;
private IComicBookRepostitory _wrappedRepo;

public LoggedComicBookRepository(ILog log, IComicBookRepostitory wrappedRepo)
{
_log = log;
_wrappedRepo = wrappedRepo;
}

public ComicBookCollection GetComicsBy(SearchParameters searchParams)
{
try
{
_wrappedRepo.GetComicsBy(searchParams);
}
catch (ArgumentException ex)
{
_log.Error(
string.Format("Parameters: Genre {0}, Year {1}", searchParams.Genre, searchParams.Year), ex);
throw;
}
}
}

Notice that it contains an instance of an IComicBookRepostitory. The LoggedComicBookRepository has a constructor that is configured with an ILog and an IComicBookRepostitory. The ILog will capture logged messages and the IComicBookRepostitory is what is being wrapped (decorated per the pattern). Whenever the wrapped instance of the IComicBookRepostitory throws an error it will be captured and the appropriate error logging will occur. Calling GetComicsBy(searchParams) is now completely logged and our concrete ComicBookRepository is none the wiser. Likewise, if we wanted to do more work before or after the method is called for any other reason then we may do so and capture the essence of AOP.

Here's some setup code that will perform comic book retrieval that will be logged.

public class SomeClass
{
public void DoSomething()
{
IComicBookRepostitory repo =
new LoggedComicBookRepository(
log4net.LogManager.GetLogger(GetType(LoggedComicBookRepository)),
new ComicBookRepository());

SearchParameters searchParams = new SearchParameters(Genre.Action, 1995);
ComicBookCollection collection = repo.GetComicsBy(searchParams);
}
}

That setup/configuration code can easily be hidden behind a DI container or something similar but I'm just illustrating how it would generally work.

The advantage to this is that I don't need to bring in a new library with XML configuration, code setup and an API that may not be familiar to other developers. It's also swatting a fly with a bazooka. In the scenario presented above we really don't need to involve a professional AOP solution.

Where AOP makes sense is for a more generic scenario. With the code I've been working with, I want to emit important information about specific method calls and their inputs. If I didn't care for that then an AOP framework would be a far better choice. For example, if I wanted to include code that profiled method execution then I could have a stopwatch that started on method entry and stopped on method exit using an AOP framework. The only thing it may capture about the method is its name. If I tried to hack an AOP framework into my previous example I would have to generate additional code that would provide mapping between method names, their overloads and the class that was responsible with logging each.

So, once again, I've avoided digging into an AOP framework. I know what I need to know and when I find the square hole I'll put the square block of AOP into it.

Wednesday, October 15, 2008

Too many interests, too little time

I have too many goddam things I want to check out in the world of software development and not nearly enough time to entertain them in any significant fashion.  There are a few tricklets missing or otherwise unpolished from my programming bag of demons that would prove to be valuable to my ability to dispense truth and beauty to the world of code.  Here's the latest group of stuff that I want to dig into:
  • Ruby - Believe it or not I'm beginning to feel constrained in statically typed languages (it's a mostly love and partially hate relationship).  Ruby seems to be all the rage so I want to poke around in it.
  • AOP - I would love nothing more than to break logging out of the components I write.  I know I can abstract them out in one of a billion ways but I'd rather just have it be completely invisible to classes whose responsibilities should be focused on their task and not making sure log4net gets the message.
  • Being a computer scientist - I got so wrapped into the abstraction of software that I stopped thinking about the science of it.  Steve Yegge reminded me just how much rust I've accumulated since graduating.
  • Agile Development - I've read the manifestos and some online documentation but I haven't committed to reading more details or purchasing any publications.  The only reason I'm partially reluctant to start now is that it's a major uphill battle with my current team.  They aren't dumb and they read about this stuff but there's no interest there.  I'm not much on lobbying and I can't train them all (including the role of our manager).
Right now I'm mixed between finding out what AOP offerings there are for .NET and playing in Ruby development.  I want to play with toys instead of read books.