Aspects of Domain Design

time to read 3 min | 520 words

On of the things that I like most about conference is that they are the place to meet and exchange a whole boat load of ideas with a large number of people. Most of the time, this is actually done on a normal level, just far more frequently than usually happen. Just this is a reason enough to visit conferences.

Sometimes, however, you get into a conversation that really open your mind. That is what Aslam Khan managed to do to me in about five minutes of hallway conversation. This short talk literally opened up for me a whole new way of thinking about the utilization of aspects and other behavioral patterns. I am going to try explaining this in this post.

Aspects are a way to add behavior to an object. Usually we are talking about being able to add pre and post actions to method calls on the fly. Aspects are commonly used to handle cross cutting infrastructure concerns. The typical examples are: logging, transactions, security and caching.

In the past, I have put domain logic in aspects, and has come to regret it very much, to the point where I believed that the only reason to use aspects is to handle cross cutting infrastructure concerns. Aslam changed my view on that.

Let us take the typical bank account example, with the Withdraw method. Ideally, I want the Withdraw method to contain just the core logic relating to its operation, so it would look something like this:

public virtual Status Withdraw(Money money)
{
	ammountInAccount -= money;
return Status.Success; }

However, what is going to happen when we have the following business role?

You may not withdraw from the account in the first week after is was opened, you may only deposit.

As usual, stupid business rule, but the example doesn't matter. The question is, where does this behavior belongs? Something that you should take into account is that there are likely to be many such rules, and any answer that you give should handle this scenario gracefully.

According to Aslam, the answer for this is in an aspect. Something like this:

public class MayNotWithdrawFromAccountOnFirstWeek : AnAspectOf<Account> // this is invoked on Account.Withdraw method
{	
	public override void BeforeExecution()
	{
		if( (DateTime.Now - Entity.DateCreated).Days > 7 )
			ReturnValue = Status.ActionCancelled;
	}
}

This allow to maintain both the single responsibility principle and create clean separation between the core entity behavior and extended behavior, which is usually implemented in a service layer somewhere.

My first thought when I heard this (I have a deep rooted suspicion of aspects for domain logic, remember) is that I want to make this explicit, so have something like the entity publish some sort of event that the container can route to all subscribers. Thinking about this further, I realize that the code to actually raise the event is exactly the kind of cross cutting technological concern that I want to use an aspect for anyway.

I am not sure about the implications of this technique, but it resonates very well with my JFHCI notion.