Saturday, September 27, 2008

AOP: what is it and why do I care

Aspect Oriented Programming or AOP. This is Yet Another Acronym (or YAA ) but for most people and most cases it's really just another recipe to solve problems in your programmer cookbook. There are many resources out there on AOP on the web and I won't attempt to cover all details of AOP.

For those new to the concept, AOP will be most clear to you through the lens of logging concerns. How many of you have written or seen code like the following?:

DoSomething action= new DoSomething();
string result = action.Execute();
Logger.Log("Info", result);
Or even worse:

DoSomething action = new DoSomething();
Customer result = action.Execute();
LogCustomer.Log(result.FullName, result.Address, result.Phone);


Only you see it every 3 lines and scattered everywhere, throughout the code base. Do something as simple as changing logging framework, changing what you log or adjusting your static logging class can end up being a nightmare. AOP attempts to solve this more cleverly by using a combination of rules called "pointcuts" to match what you log, and then executing functions called "advices" .

The flexibility and implementation of pointcuts vary greatly from one AOP framework to another, so you'll have to consult your framework of choice's docs. But I can give you an example using IoC container Castle Windsor:
1: WindsorContainer container = new WindsorContainter();
2: container.Register(AllTypes.Of.FromAssembly
(Assembly.GetExecutingAssembly()).Interceptors.Add(new InterceptorReference(typeof(LoggingAdvice))).Last));

Now lets recap what's going on here? First line initializes the container, second line registers all classes that implement the ICommand interface in the currently running assembly, and then adds the LoggingAdvice. You can change this to all classes, or only individual classes but that's an exercise I leave up to the reader. Lets show the code now:

public interface ICommand{
string Execute(string sendString);

}

public class Command: ICommand
public string Execute(string sendString)
{
string toconsole = sendString + " this is from the console";
Console.WriteLine( toconsole);
string retvalue = sendString + " this is returned by the method";
return retvale;
}

This is a simple enough class. It writes the sent string to the console with some additional information, then returns the sent string with where it is in the Execute Method.

And the LoggingAdvice is as follows:

public class LoggingAdvice:IInterceptor
{

public void Intercept(IInvocation invocation)

{
invocation.Proceed();
Object argument = invocation.GetArgumentValue();
Console.WriteLine(argument.ToString() + " from LoggingAdvice" );
Object returnValue = invocation.ReturnValue;
Console.WriteLine(returnvalue.ToString() + " from LoggingAdvice" );

}


}
note the invocation.Proceed() method call. This ends up having the "Advised" or "Intercepted" method execute then and there. Then the invocation will be able to get the return value. This means you could move the proceed call to just before the ReturnValue call.

Now client code would look something like so:

class Program{

static void Main(string[] args)

{
WindsorContainer container = new WindsorContainer();
//add registration code from above here
ICommand cmd = container.Resolve();
cmd.Execute(args[0]);
}
What's going on here? Windsor retrieves an instance of ICommand which will give you the Command class. The Execute is called on the ICommand instance with the args from the command line passed in. You'll find a result similiar to so when run from the command prompt:

1: program.exe "doing stuff"
2: doing stuff this is from console
3: doing stuff from Logging Advice
4: doing stuff this is returned from the method from Logging Advice


Let's recap, our core code is making no direct calls to a logging class and it is not sprinkled all over our code. While in this trivial example the gains are not realized but anything larger than 300 lines of code we're going to see a benefit from using an AOP framework.

In upcoming posts I'll cover other frameworks and more common uses of AOP.

Tuesday, September 23, 2008

Quartz.Net and Castle.Scheduler for scheduled jobs

I've had the opportunity to work with both scheduler frameworks in the same project (ended up switching out Quartz.Net for Castle.Scheduler) and here is what I found.

Quartz.Net

Positives:
  1. CronTrigger alone is almost worth it. Anyone with a unix background (like me) finds this a big win.
  2. Based on a very mature Java based project so in theory it's design is well tested.
  3. Has support for supplying different Calendars (think holiday calendar, being loaded into a "job" so that it knows not to fire on your organizations particular holidays, this is nice to have in banking for example).
  4. comes with command line client and service. This wasn't out when I was using it and I had to implement my own versions.
Negatives:
  1. Complete Seperation of Triggers (scheduling objects) and a "JobDetail" (think name, description, etc). This in my experience lead to alot of confusion with developers and caused alot of inconsistency. Example: When wanting to reschedule a job, you had to reschedule it by it's trigger name. Which would cause problems if you had that trigger setup on more than one "JobDetail", and also would require you to find the trigger name of that job anyway.
  2. A lot of string literals. Just my personal take don't care for this.
  3. Some incomplete implementations. Example: when using 0.9.1 I had a dev who was stuck on why NextFireTime wasn't showing up on a Trigger. Some things are just tagged as not implemented yet.
  4. MegaClasses. Lots of methods, lots of noise. Again this is a port so it's not like Quartz.Net can vary too terribly much from Quartz.
  5. Only one developer that I can see. He works hard, pushes out releases frequently, but the Castle team is top notch and has many qualified contributors, it's not a fair comparison.
  6. RamJobStore was solid, ADOJobstore was a bit flakey and didn't work nearly as well.
Castle Scheduler

Positives:
  1. Leverages Castle Windsor. If you use it already this is huge plus.
  2. Simple small easily understandable classes.
  3. JobSpec easy to understand and transparent to the junior devs. Includes a trigger property so that there is only a 1 to 1 mapping between triggers and jobs.
  4. SqlJob store is well supported and works about as well as the InMemoryJobStore.
  5. Out of the box clustering of schedulers using a db backend to track jobs between the schedulers.
Negatives:
  1. As most castle projects, may not be enough docs for less experienced devs unused to reading source code and unit tests.
  2. Limited out of the box trigger support. You'll have to implement your own triggers to get something outside of daily and interval executions.
  3. You have to be comfortable builing Castle Trunk. This is a limiter to new users obviously.

Summary
.
Both of them do the job if you need a job scheduler. If you already "speak Castle" and are comfortable with that tool chain then Castle.Scheduler is a much lower friction option. If you don't already use Castle (which I love btw) , or you need complex scheduling then Quartz.Net may be more for you. However, fear the AdoJobStore and prepare to use another method to persist you jobs, if you find friction using it for higher performance scenarios.

I'll try to make time showing the basic use of Castle.Scheduler not already covered in docs later in the week.