Announcing SheepAOP (Part 1)

Not the wittiest name, I realize, but certainly among the top in the cuteness league. SheepAOP is yet another AOP tool for the .NET environment (which frankly aren’t that many). It uses IL weaving to inject croscutting concerns to your dll at compile time. (And soon, SheepAOP will also support IL weaving at assembly load-time as an alternative, leaving the original dll intact).

The project is still in its very early inception, it just started last week, so I’m all ears to as many feedbacks as I can get.
I did a presentation on this yesterday, which I’m going to recap here in this 2-part-series.

Part 1 – AOP for Everyone
Part 2 – SheepAOP Basics

AOP for Everyone

SheepAOP project is driven primarily by experimental intents, but its ultimate goal is to make AOP more accessible for .NET developers.
In today’s climate, when we talk about AOP, we normally would only use it for things of the grandest scale, like transaction-management, logging, security authentication, and all that sort. But there are many trivial things in our everyday work that we won’t immediately think of AOP. In those instances, we usually feel like we need an intensely compelling reason before we even think about resorting to AOP. I think this is down to the lack of the tooling, especially in the .Net space, where AOP has become something highly exotic.

This is what I intend to change, by bringing in a free alternative onto the table, making AOP a bit more accessible that hopefully people would just go ahead and start writing aspects for simple things without thinking much about it, just like what people do in Java for instance, where AspectJ has become a defacto standard, so ubiquitous that whenever you sense the slightest need for an aspect, chances are you already have AspectJ within your library stack, so you just go ahead and write your aspects.

Simple Everyday Thing

Nothing is simpler than the cliché Shopping Cart example, a bare one notch above Hello World. So let’s use this as our example.

public class ShoppingCart
{
    public void AddProduct(Product product, int qty)
    {
        product.StockQty -= qty;
        _items.Add(new CartItem(product, qty));
    }
}

public class Product
{
    public int StockQty
    {
        get { return _stockQty; }
        set
        {
            _stockQty = value;
        }
    }
}

A clean simplistic shopping cart class. But life as a developer is never this clean and simple. In fact, the customer just came with a new Notification rule, specifying that:
“If StockQty drops below 5, then send a notification email to the Purchasing Department to restock the product.”

So we’re going to carry out that rule whenever the StockQty property is set (line #17). So what are we gonna need? Firstly, you’ll obviously need an INotificationService in the Product class, and the ShoppingCart is going to supply that, all the way from the top where you meet your IoC container.

At this point, you would not normally think of AOP. You would instead employ a more conventional approach by rearchitecting your domain structure. You use the good old Dependency-Injection, and introduce double-dispatch pattern around your methods.

public class ShoppingCart
{
    public void AddProduct(Product product, int qty,
                    INotificationService notifier)
    {
        product.ReduceStock(qty, notifier);
        _items.Add(new CartItem(product, qty));
    }
}

public class Product
{
    public void ReduceStockQty(int qty, INotificationService notifier)
    {
        _stockQty -= qty;
        if(_stockQty < 5)
            notifier.Send(Notice.Restock, this);
    }
}

So we changed the StockQty property into a method so we can inject a new dependency, which is passed all the way through shopping-cart up to the top, which depending on your object structure, may be quite deep. You have to make the same change to all places that use the StockQty property to accommodate the new dependency. This is an example of one simple change that make a great impact to the source code.

There’s no problem with this approach, we use this pattern everyday. But let’s now shift our thinking a little bit.

The main drawback of this approach is pollution. Let’s ask ourselves: does this piece of code really belong here? It doesn’t seem right to me. What’s a warehouse purchasing policy doing in a Product class? It is completely unrelated to the business of putting a product into your shopping trolley. And why do we need an INotificationService to use a shopping-trolley anyway? We certainly don’t send any notification email when you chuck a product into the trolley, but the service is just there to cover a specific edge-case scenario that might or might not happen somewhere down the line of the executing flow. If it only happens occasionally, why do we have to pass the notification-service every time? That seems to put a lot of unnecessary garbage to our otherwise clean code.

In typical projects, these edge-case-scenarios are usually quite plenty. There are usually a vast number of combinations of all different possibilities that we need to cater for, e.g. apply extra tax if the customer is within certain countries. Our code starts to look like transaction-scripts of various if-else conditions. Our classes are becoming less and less about shopping-carts and products; and more and more about different bits and pieces of all unrelated concerns, glued together to cover all possible basis.

What about all other notification alerts? Every time the customer define a new notification-template, we need to open our application source-code, look in our domain classes where we can fit the logic in, and implant the notification condition right there, and rewire all the required dependencies. We do that for each of our notification rules, and the whole notification policy is those pieces of logics scattered all over the source-code. Every time we define a new one, we need to remodify our domain source-code again. Each of our classes now has a lot more than one reason to change. Any class can change any time for any reason, and none of them can seem to escape from it.

Say Hello to SheepAOP

Let’s see an alternative way of implementing the same requirement. Let’s rewind back to the start.

public class ShoppingCart
{
    public void AddProduct(Product product, int qty)
    {
        product.StockQty -= qty;
        _items.Add(new CartItem(product, qty));
    }
}

public class Product
{
    public int StockQty
    {
        get { return _stockQty; }
        set
        {
            _stockQty = value;
        }
    }
}

These are our classes when they were still neat and clean. Everything about shopping-cart and product, and nothing else. So now, what’s the first thing that we’re going to change on these classes?

Right, the answer is nothing. We are not going to touch these classes. They already do all they’re meant to do, so leave it that way, keep them clean and simple, and don’t pollute them with any other garbage.

Instead, we are going to create a new class, let’s call it WarehouseNotificationAspect.

public class PurchasingNotificationAspect: IAspect
{
}

This class can be defined completely separate from your actual classes. Anywhere you want. You can even place this in a separate project, let’s say, Sheep.NotificationPolicy project, if you like.

Now let’s define a “pointcut”. If you’re not familiar with the terminology, don’t worry we’ll get there in no time. For now, you only need to know pointcut as a “criteria to search within your source-code”. In our case, we want to target the setter of our “Product.StockQty” property, so let’s write our pointcut for that.

[RegisterPointcut]
public static void SetProductPointcut(PointcutRegistry reg)
{
    reg.AddCurrentAssembly()
        .Listen(r => r.Setter(p => p.StockQty));
}

Now that we have our pointcut, we can offer an “advice” to it. We can say: “when this ‘property is set’ (PropertySet), after ‘it’s done’ (OnExit), please ‘do this and that’”.

public void Init()
{
    Listener.PropertySet(SetProductPointcut).OnExit += (j, c) =>
    {
        if ((int)j.Value < 5)
            _notifier.Send(Notice.Restock, (Product) j.Instance);
    };
}

During compile time, SheepAOP will insert these extra logic at the end of the StockQty property, and save it to your dll.

Since this aspect class is just a normal POCO class, it means you can just manage this using your normal IoC container, so you will have all your dependencies sorted. The full source-code of our aspect becomes:

public class PurchasingNotificationAspect: IAspect
{
	[RegisterPointcut]
	public static void SetProductPointcut(PointcutRegistry reg)
	{
		reg.AddCurrentAssembly()
			.Listen(r => r.Setter(p => p.StockQty));
	}

	private readonly INotificationService _notifier;
	public PurchasingNotificationAspect(INotificationService notifier)
	{
		_notifier = notifier;
	}
	public void Init()
	{
		Listener.PropertySet(SetProductPointcut).OnExit += (j, c) =>
		{
			if ((int)j.Value < 5)
				_notifier.Send(Notice.Restock, (Product) j.Instance);
		};
	}
}

Your original ShoppingCart and Product classes remain untarnished, so you can unit-test them easily as a plain shopping-cart without having to worry about other unrelated concerns and depedencies. Similarly, you can unit-test your notification-policy in isolation by testing your notification-aspects.

Jargons

Let’s review our jargons.

  1. Pointcut: Search-criteria of what you want to influence with your aspect. We had a very simple pointcut in our previous example, but pointcut can be very sophisticated. I’ll give an example using a pseudo-code with a language we’re all familiar with: SQL.
    select from all [methods] where
    	(methods:
    		is public or protected &
    		Name like ‘Get*’ | ‘Find*’ &
    		Returns (all types:
    			IsAssignableFrom (Money or Number)) &
    		Declared in (all types:
    			namespace: is ‘Sheep.Domain.*’ &
    			Implements(type: Name like ‘I*Service’)) &
    		Args is (int id, ..., string *name, )
    	)
    

    We were selecting all methods where it’s public or protected, with a name beginning with Get or Find, returning any type assignable from Money or Number, declared within any type within the ‘Sheep.Domain.*’ namespace, and implements any ‘I*Service’ interface, with arguments of yada yada yada.

    We can search not only methods and property. We can even search a specific-line-of-code! Such as this one.

    select all [instructions] where
    	(field: Product.‘_stock*Qty’ &
    		type: int or double
    	) &
    	instruction: Executed within
    	(method:
    		Name(‘Change*’) &
    		Declared in type: ShopingCart
    	)
    

    Just to give an idea of what pointcut does, let’s see one in action. I need to use an example from Java, because quite frankly I could not find anything from .Net that is even remotely comparable to AspectJ. So here’s AspectJ on Eclipse IDE.

    PS: AspectJ is an ambitiously sophisticated AOP framework, and SheepAOP is no where near it in any possible way. But the maturity of AspectJ makes for an excellent example to give you a good idea about various AOP concepts.

    image
    (Image #1, AspectJ Pointcuts)

    Unlike anything on .Net, in AspectJ aspect is a first-level language construct. So see on the left pane, we have an aspect that declares an annotation using pointcut * Account+.*(..), i.e., all methods within Account class with any name and any arguments. The right pane instantly shows you that 3 methods are affected by this pointcut. These 3 methods are your croscutting concern that you want to target with your aspect. You can even visualise these pointcuts within the IDE.

    image
    (Image #2, AspectJ Pointcuts Visualisation)

    On the right pane, you see your pointcuts, and the main panel shows you how each of these pointcuts crosscuts through your source-code. Imagine the blue one as our Notification Policy. We can see various places where we put some specific logic to send notification emails based on certain conditions. We can create an aspect for this so we don’t pollute our source-code with anything that’s not related with the actual business of your application.

  2. Jointpoints: The “search result” of your pointcut. Those 3 methods on the right pane of Image#1, we can see our Pointcut matches with 3 jointpoints (the validate(), credit(int), and debit(int) methods)
  3. Advice: Once we have our pointcut, we can offer it some advices of how those pointcuts should change their behavior (i.e. logging, start-transaction, authorisation, etc).
  4. Aspect: We have our pointcut, we offer it some advices, we have an Aspect.Here’s another example from AspectJ of a complete Aspect.
    image
    (Image #3, AspectJ Aspect)We have a complete AspectJ aspect. We define a pointcut to target all public methods under Account class (with any name and arguments), and we offer it an advice that “before” you execute the method, please authenticate the “account”, where “account” is the owner (aka the ‘this’) of the method.

Different Flavours

There are few different ways we can do AOP:

  1. Code Generator
    e.g. T4, CodeSmith
  2. Dynamic Proxy
    e.g. (Castle DynamicProxy), Spec#, NAspect
    This is by far the most popular AOP approach in .Net, which is unfortunate as it’s also the most limited way of doing AOP of all. It can only be used for objects managed by IoC, then its virtual/interface requirement, no static-methods, etc, making it hardly useful for too many purposes.
  3. .Net Profiller API
    e.g. TypeMock Open AOP (CThru).
    .Net profiler API’s use in production environments is strongly discouraged, although how bad we’ll get punished for violating it still remains unclear.
  4. IL Weavinge.g. AspectJ, PostSharp, and SheepAOP
    This is the most popular approach outside the .Net circle.

Why Another One?

PostSharp is an excellent product and has done remarkably well over the years, but one of my primary reasons of my reinventing it with SheepAOP (apart from to offer an open-source alternative) is down to the difference in style. PostSharp puts a huge emphasize on the use of .Net Attributes. The problem of Attributes in AOP is that the attribute itself becomes the repetitive crosscutting concerns. In contrast, SheepAOP firmly sticks on the well-known AOP pattern and terminologies using pointcuts, jointpoints, and advices, although the use of attribute will also be supported soon.

(.. more about SheepAOP in part 2)

Summary

SheepAOP is an open-source AOP framework, still in its early inceptions, that aims at bringing the classic AOP style and patterns to the .Net audience. The framework uses IL weaving (thanks to Mono.Cecil) to inject croscutting behaviours during compile-time.

In this post, we’ve discussed about how aspects can be used to help everyday’s domain-driven applications, beyond the highly clichéd transactions and logging.

The next post (part 2) will cover the basics of using SheepAOP.

The SheepAOP project repository and source-code of this post can be found in Codeplex: http://sheepaop.codeplex.com/

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s