Crosscutting in Advice/Pointcut Binding

AOP の本来の動機は、従来のモジュール化の方法(手続き型、オブジェクト指向、etc)では発生してしまう Crosscutting な要求をよりうまくクリーンモジュール化しようということ。


でも、アドバイスとポイントカットの定義自体にも、Crosscutting っぽいのが発生してしまうと思う。


たとえば、以下の例では、同じジョインポイントを参照している3つのアスペクトを示している。


public class MyClass {
public void method() { ... }
}

public aspect MyAspectA {

before() : call( void MyClass.method() ) {
...
}
}

public aspect MyAspectB {

before() : call( void MyClass.method() ) {
...
}
}

public aspect MyAspectC {

before() : call( void MyClass.method() ) {
...
}
}

分かるように、もし、参照したいジョインポイント(この例では、call( void MyClass.method() ))に変更があったら、3つのアスペクトともに変更が及ぶ。解決策の一つは、共通で参照するポイントカットを定義すること:

public class MyClass {
public void method() { ... }
}

public aspect CommonPointcuts {
public pointcut MyClassMethodCall() : call( void MyClass.method() );
}

public aspect MyAspectA {

before() : CommonPointcuts.MyClassMethodCall() {
...
}
}

public aspect MyAspectB {

before() : CommonPointcuts.MyClassMethodCall() {
...
}
}

public aspect MyAspectC {

before() : CommonPointcuts.MyClassMethodCall() {
...
}
}

それでも、まだ、アドバイスとポイントカットを結びつけるさいには、コードの重複が発生してしまう。現在の AspectJ の実装では、この重複をなくすことは難しい。


ありえる解決策は、アドバイスに名前をつけられるようにして、さらに、アドバイスにポイントカットの定義を外部からバインドできるようにすること:


public class MyClass {
public void method() { ... }
}

public aspect CommonPointcuts {

public pointcut MyClassMethodCall() : call( void MyClass.method() );

bind : MyAspect*.my() : MyClassMethodCall()
}

public aspect MyAspectA {

before my() {
...
}
}

public aspect MyAspectB {

before my() {
...
}
}

public aspect MyAspectC {

before my() {
...
}
}

ただ、アドバイスの定義だけをみても、どんなジョインポイントにバインドされるのかは分からないという欠点もある。でも、この欠点は、AJDT などの AOP をサポートする開発環境があれば、軽減されると思う。


参考:
僕が勧めても仕方がないけど、AOP の動機とかの記述で一番簡潔な気がするのは、この論文の Introduction の部分です。

Jürgen Hallpap
Towards Caesar: Dynamic Deployment and Aspectual Polymorphism
http://www.st.informatik.tu-darmstadt.de/public/Thesis.jsp?id=15