[computer-go] Aspect Oriented Programming

Mark Boon tesujisoftware at gmail.com
Fri Sep 22 14:03:53 PDT 2006


Not really a Go programming topic, but I was just wondering if anyone  
is using this.

I first got interested in AOP about two years ago. But I never  
actually used it as my clients weren't interested in this newfangled  
idea. It seemed pretty powerful to me though. And actually a very  
elegant concept.

So now that I'm free to use whatever technology I like I started to  
use AspectJ today, for the first time. And it's really cool. To avoid  
memory-allocation and garbage-collection too often I use object- 
pooling. For this I have a simple interface called FlyWeight, which  
does nothing than defining a recycle method:

public interface Flyweight
{
	public void recycle();
}

I use static factory classes that actually allocate and pool the  
objects. Constructors are never public. When the recycle() method is  
called I return the object to the factory it came from so it can be  
reused.

Since I avoid the garbage-collector this way, I also have the  
responsibility of the object life-times again. So it's easy to end up  
with dangling references, just like in the old C++ days. To detect  
dangling references, I end up having a lot of code (with conditional  
compilation, but still) to check if an object gets accessed after it  
has been recycled. That's basically the same as accessing a dangling  
pointer.

With AOP that's all a thing of the past. With just a little bit of  
code, all my FlyWeight derived classes have automatic dangling  
reference detection. It looks like this:

import tesuji.core.util.FlyWeight;

public aspect DanglingReferenceChecker
{
	private boolean FlyWeight.isInFactory = false;

	pointcut factoryCall() : call(static * *Factory.create*());
	pointcut methodCall() : call(* *.*(..));
	pointcut recycleCall() : call(* FlyWeight.recycle());

	after() returning (FlyWeight flyWeightObject) : factoryCall()
	{
		flyWeightObject.isInFactory = false;
	}

	before(FlyWeight flyWeightObject) : target(flyWeightObject) &&  
methodCall()
	{
		if (flyWeightObject.isInFactory)
			throw new IllegalStateException();
	}

	after(FlyWeight flyWeightObject) : target(flyWeightObject) &&  
recycleCall()
	{
		flyWeightObject.isInFactory = true;
	}
}

That's all! So the following code throws an exception at the second  
call to setMoveNr().

		GoMove move = GoMoveFactory.createGoMove();
		move.setMoveNr(1);
		move.recycle();
		move.setMoveNr(2);

The only drawback I see is that I've (so far) only got it to work if  
the factory methods take no arguments. So I need setXX methods even  
for members that I'd like to set on initialisation only. But that's a  
small price to pay for something that's going to save me enormous  
amounts of work. Oh, and the other drawback is that I still have to  
see how I can run my unit-tests with aspects activated.

The good part is that it saves me a lot of work of decorating all my  
FlyWeight derived objects with code like

	if (CHECK_REFERENCES && isInFactory())
		throw new IllegalStateException();

in just about every method. The aspect also removes the need of the  
isInFactory boolean in all derived classes. The whole checking code  
when running in normal mode has actually no influence on the  
application whatsoever.

OK, just got excited over this new bit of technoloy. I won't bore you  
guys any longer with something so obviously off-topic :-)

	Mark Boon

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://computer-go.org/pipermail/computer-go/attachments/20060922/a82c093c/attachment.htm


More information about the computer-go mailing list