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