Aspect Oriented Programming – When to Use a Framework

aspect-orientedcdesign

I just watched this talk by Greg Young warning people to KISS: Keep It Simple Stupid.

One of the things he suggested is that to do aspect-oriented programming, one does not need a framework.

He starts by making a strong constraint: that all methods take one, and only one, parameter (though he relaxes this a little later by using partial application).

The example he gives is to define an interface:

public interface IConsumes<T>
{
    void Consume(T message);
}

If we want to issue a command:

public class Command
{
    public string SomeInformation;
    public int ID;

    public override string ToString()
    {
       return ID + " : " + SomeInformation + Environment.NewLine;
    }
}

The command is implemented as:

public class CommandService : IConsumes<Command>
{
    private IConsumes<Command> _next;

    public CommandService(IConsumes<Command> cmd = null)
    {
        _next = cmd;
    }
    public void Consume(Command message)
    {
       Console.WriteLine("Command complete!");
        if (_next != null)
            _next.Consume(message);
    }
}

To do logging to console, one then just implements:

public class Logger<T> : IConsumes<T>
{
    private readonly IConsumes<T> _next;

    public Logger(IConsumes<T> next)
    {
        _next = next;
    }
    public void Consume(T message)
    {
        Log(message);
        if (_next != null)
            _next.Consume(message);
    }

    private void Log(T message)
    {
        Console.WriteLine(message);
    }
}

Then, the pre-command logging, command service, and post-command logging are then just:

var log1 = new Logger<Command>(null);
var svr  = new CommandService(log);
var startOfChain = new Logger<Command>(svr);

and the command is executed by:

var cmd = new Command();
startOfChain.Consume(cmd);

To do this in, for example, PostSharp, one would annotate the CommandService this way:

public class CommandService : IConsumes<Command>
{
    [Trace]
    public void Consume(Command message)
    {
       Console.WriteLine("Command complete!");
    }
}

And then have to implement the logging in an attribute class something like:

[Serializable]
public class TraceAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine(args.Method.Name + " : Entered!" );   
    }

    public override void OnSuccess( MethodExecutionArgs args )
    {
        Console.WriteLine(args.Method.Name + " : Exited!" );
    }

    public override void OnException( MethodExecutionArgs args )
    {
        Console.WriteLine(args.Method.Name + " : EX : " + args.Exception.Message );
    }
}

The argument Greg uses is that the connection from the attribute to the implementation of the attribute is "too much magic" to be able to explain what's happening to a junior developer. The initial example is all "just code" and easily explained.

So, after that rather longwinded build-up, the question is: when do you make the switch from Greg's non-framework approach to using something like PostSharp for AOP?

Best Answer

Is he trying to write a "straight to TDWTF" AOP framework? I seriously still haven't got a clue what his point was. As soon as you say "All methods must take exactly one parameter" then you've failed haven't you? At that stage you say, OK this imposes some seriously artificial constraints on my ability to write software, let's drop this now before, three months down the line we have a complete nightmare codebase to work with.

And you know what? You can write a simple attribute driven IL based logging framework quite easily with Mono.Cecil. (testing it is slightly more complicated, but...)

Oh and IMO, if you aren't using attributes, it isn't AOP. The whole point of doing the method entry/exit logging code at the post processor stage is so that it doesn't mess with your code files ans so you don't need to think about it as you refactor your code; that is its power.

All Greg has demonstrated there is the keep it stupid stupid paradigm.

Related Topic