AspectJ を使ったデザインパターンの改善と支援
asato <asato@ncfreak.com>
最終更新日 : 2004/6/5 (2002/9/3 より)
このドキュメントでは、AspectJ によるデザインパターンの実装を考えます。AspectJ を使うことにより各デザインパターンの実装を考えたときに、どのようなバリエーションが存在するのかを調査しています。いくつかのバリエーションは、それほど実用的ではなく、しかし、いくつかについては設計上において考慮の必要な選択肢となります。
このドキュメントの目的は、AspectJ を使って各デザインパターンにおける代表的な(あるいは唯一)の実装例を紹介するのでは なく、考えられるすべてのバリエーションを列挙し、様々な状況においてそれぞれの実装の利点や欠点を調査することです。また、AspectJ の言語的な機能の視点から、デザインパターンを深く理解することも目的としています。
YES! かなり下書きです。メモです。書きっぱなしです。垂れ流しです。内容も、間違っている部分の方が多いと思います(ほとんどかも!)! マジにウソくさい内容です。一部の記述はパターン形式っぽく書いてますが、アンチパターン かもしれません!
"AspectJ + デザインパターン" というネタについてのより信頼できるリソースとしては、以下のものを読む方が適切かと思われます (僕の AspectJ の使い方と全然違う! たぶん僕のほうが間違ってる!)。
それから、内容についてさらに注意:
- ここに書いてあることが、実践的に使える自信はありません; こんな感じに AspectJ を使って書くこともやろうと思えばできるな、程度です。
- 本当に、デザインパターンの改善や支援になっているのかどうかも怪しいところです; 全くもって自信はないです。ジョークだと思ってください m(_ _)m。
- ここで紹介しているコードに共通する潜在的な欠点は、可読性の悪さです。書いた本人でさえ、読みこなすのがつらいです (自信のある人は Decorator のコードを解読してみてください!)。
- ここで紹介しているコードは、C でいえばプリプロセッサ (?) を悪用したコードではないのかと危惧しています。疑っています; 最終的には、AspectJ をこのように乱用してはいけない、という意味で誰かの参考にでもなれば幸いです!
- 一部の内容は更新されていないまま古くなっていますので注意していください。(2003/7/2 追加)
- デザインパターン再考
- Factory Method (2003/7/24 追加 [まだ更新してない])
- 生成
- 構造
- 振る舞い
- その他
- テスト環境
- デザインパターン再考
- 基本的な考慮点
- AspectJ を使ったソフトウェア開発のシナリオの種類 (2003/12/28 追加)
- デザインパターンと AspectJ
- AspectJ を使ったデザインパターンに関するテクニックの種類
- 関連研究
- 参考文献
- 注意書き
- 参考にしたもの
- 更新履歴
- todo
テスト環境
- AspectJ 1.2rc1 (かなり一部)
- AspectJ 1.1.1 (かなり一部)
- AspectJ 1.1.1 (かなり一部)
- AspectJ 1.1rc1 (一部)
- AspectJ 1.1rc2 (一部)
- AspectJ 1.1 (一部)
- AspectJ 1.1beta4 (一部)
- AspectJ 1.0.6 (主に)
デザインパターン再考
AspectJ を使ってデザインパターンを実装しようと考えるにつれて、デザインパターンの見方が変わっていくことに気がつきました。デザインパターンとは何なのでしょうか? 構造のことでしょうか? どうなっていればデザインパターンでしょうか? どこでまでがデザインパターンでしょうか?
「パターンハッチング」ではパターンに対する誤解の 1 つとして「パターンとはコンテキスト (文脈) における問題の解決策である」というパターンに対する定義をあげています。また、以下のような反例を挙げています。
コンテキストにおける問題の解決策だけでは不十分らしいのです。足りないのは
Factory Method
なぜ役に立つのか
基本的な考慮点
- アスペクトの名前付けについて
- アスペクトの再利用について
- 1 つのアスペクトはどのくらいのクラスに関わるのか
- リファクタリングよりアスペクトのほうが適切がどうか
- アスペクトをソースコードは利用できるのかどうか
- ソースコードは利用できない
- ソースコードは利用できる
- そのソースコードは誰のものかどうか
- 自らが開発しているものである
- 外部が開発しているものである
- 単なる置換えが目的なのかどうか
- 型名が伝えることを重視しているか
- なぜわざわざアスペクトを使ってクラスを発展させるのか
- アスペクトをどこで使うのか
- 自らが開発しているアプリケーション内で
- 自らが開発しているフレームワーク内で
- 開発しているソフトウェアの種類は何か
- 何を再利用したいのか
- アスペクト作成者はクラスの内部にどこまで関与すべきなのか
- アスペクトをどこに定義するのか
- 個別なアスペクトとして定義するのか
- 関連のあるクラスの内部アスペクトとして定義するのか
- ソースコードレベルでの再利用性
- 追加的な変更に対してどのように対処するのか
- 構造的な変更に対してどのように対処するのか
- デザインパターンでのアプローチと比べてどこか優勢なのかどこが欠点なのか
- どこまでコードで意図を表現するのか
ソースコードは利用できるのかどうか
AspectJ を利用する場合、ソースコードがなければ行えることは制限される。ソースコードが利用可能でなければ Introduction はできない。
ソースが利用できる場合の例:State クラスのソースコードが利用できる
package dp;
import java.lang.reflect.Method;
public class Client {
public static void main(String[] args) {
Method[] methods = State.class.getMethods();
for(int i = 0 ; i < methods.length ; i++) {
if ( methods[i].getName().startsWith("handle") ) {
System.out.println( methods[i] );
}
}
}
}
package dp;
public class State {
public void handleA() {}
public void handleB() {}
}
package dp;
public aspect StateAspect {
public void State.handleC() {}
}
public void dp.State.handleA()
public void dp.State.handleB()
public void dp.State.handleC()
ソースが利用できない場合の例:State クラスのソースコードは利用できない
public void dp.State.handleA()
public void dp.State.handleB()
そのソースコードは誰のものかどうか
- 自らが提供しているフレームワークで使われているソースコードである
- 外部が提供しているフレームワークで使われているソースコードである
自らが提供しているフレームワークであり、ソースは利用できる
単なる置換えが目的なのかどうか
Introduction の能力
- ソースコードを変更する場合と違って、取り外しが可能である。
Introduction のできることできないこと
できること:
- フィールドの導入
- メソッドの導入
- 継承の導入
- interface の導入
できないこと:
- protected introduction is not supported
メモ:
- The access modifier applies in relation to the aspect, not in relation to the target type. So a member that is privately introduced is visible only from code that is defined within the aspect introducing it. One that is package-protectedly introduced is visible only from code that is defined within the introducing aspect's package.
- Note that privately introducing a method (which AspectJ supports) is very different from introducing a private method (which AspectJ previously supported). AspectJ does not allow the introduction of the private method "void writeObject(ObjectOutputStream)" required to implement the interface java.io.Serializable.
Introduction 使用の適切な場合
Introduction 使用の不適切な場合
- 追加(導入)しようとしているフィールドやメソッドが、そのクラスにとって自然な場合。つまり、そのクラスにとってそれまでに不足していた側面であり、それを補うためのフィールドやメソッドの追加である場合。
AspectJ を使ったソフトウェア開発のシナリオの種類
AspectJ を使っての、いくつかのソフトウェア開発のシナリオが考えられます。
|
シナリオ 1 |
シナリオ 2 |
シナリオ 3 |
アプリケーションの開発 |
○ |
○ |
○ |
ライブラリの使用 |
× |
○ |
○ |
バイトコード・ウィービング |
× |
× |
○ |
シナリオ 1 では、(javac の代わりに) AspectJ を使ってアプリケーションの開発を行います。
シナリオ 2 では、AspectJ を使ってアプリケーションの開発を行うのに加えて、外部ライブラリを使用します。しかし、バイトコードのウィービングは行いません。
シナリオ 3 では、AspectJ を使ってアプリケーションの開発を行うのに加えて、外部ライブラリを使用します。さらに、その依存しているライブラリに対して、何らかのバイトコードのウィービングも行います。
このように、特定のシナリオが、ある AspectJ によるデザインパターンの実装にも影響を与えます。シナリオ 1 では、アプリケーション内での AspectJ によるデザインパターンの実装が考えられます。シナリオ 2 では、アプリケーションが依存する特定のライブラリに対してのデザインパターンの実装が考えられます。シナリオ 3 では、特定のライブラリに対して、バイトコード・ウィービングを行うことによる、特定のデザインパターンの実装方法が考えられます。
デザインパターンと AspectJ
AspectJ を用いた AOP が威力を発揮しそうな場面として以下のものがある:
- 関連するコードをアスペクトにまとめる事による保守のしやすさ
- AspectJ の提供する機能をつかってのよりシンプルなコーディング
AspectJ を使って以下のことにトライする。
- もっとシンプルな構造でデザインパターンを実装できないのか
デザインパターンの欠点の種類
AspectJ を使ったデザインパターンに関するテクニックの種類
AspectJ を使ったデザインパターンに関するテクニックの種類には、大きくわけて以下の 3 つのテクニックが考えられます:
関連研究
異なる言語の特徴(あるいはパラダイム)が、デザインパターンの実装においてどのような影響をもたらすのかを調査した研究は、それほど多くありません。
GoF らによるデザインパターンの原典では、C++ と Smalltalk による、オブジェクト指向のパラダイムの視点からの実装が紹介されています [1]。
このドキュメントと最も関連があるのは、Hannemann と Kiczales による、AspectJ による GoF のデザインパターンの実装です [2]。彼らの視点は、どちらかといえば、再利用可能なデザインパターンを実装することにあるように見えます。
参考文献
- [1] オブジェクト指向における再利用のためのデザインパターン.
- [2] Jan Hannemann and Gregor Kiczales. Design Pattern Implementation in Java and AspectJ. OOPSLA 2002.(2002) [ここ から DL できます]
注意書き
役割の項目で使っているタグ (<< >>) は、The UML Profile for Framework Architectures からのものを使用しました (Appendix B : UML-F tags of the GoF framework patterns )。
参考にしたもの
更新履歴
- 2006/6/5 : 「Observer」を更新
- 2004/5/15 : 「Strategy」を更新
- 2004/4/25 : 「関連研究」を追加。「Factory Method」を更新
- 2004/2/29 : 「Abstract Factory」を更新
- 2004/2/28 : 「Abstract Factory」を更新
- 2004/1/14 : 「Abstract Factory」を更新
- 2004/1/13 : 「Strategy」を更新
- 2004/1/12 : 「Strategy」を更新
- 2004/1/6 : 「Strategy」を更新
- 2004/1/6 : 「Strategy」を更新
- 2004/1/5 : 「Strategy」を更新
- 2003/12/28 : 「Strategy」を更新
- 2003/12/28 : 「Strategy」を更新
- 2003/12/28 : 「AspectJ を使ったソフトウェア開発のシナリオの種類」を追加。
- 2003/12/27 : 「Strategy」を更新
- 2003/12/25 : 「Strategy」を更新
- 2003/12/24 : Factory Method を更新
- 2003/12/23 : Factory Method を更新
- 2003/11/27 : Factory Method を更新
- 2003/11/26 : 「Chain of Responsibility」を追加
- 2003/11/26 : 「Abstract Factory」を更新
- 2003/11/4 : 「Abstract Factory」を更新
- 2003/11/2 : 「Visitor」を更新
- 2003/11/1 : 「Visitor」を更新
- 2003/8/28 : 「Decorator」を更新
- 2003/7/18 : 「Observer」を更新
- 2003/7/17 : 「Observer」を更新
- 2003/7/15 : 「Observer」を更新
- 2003/7/4 : 「Visitor」を更新
- 2003/7/2 : 「Strategy」を更新
- 2003/6/18 : 「Null Object」を追加。
- 2003/6/16 : 「Adapter」を追加。
- 2003/5/31 : 「Strategy」を更新
- 2003/5/26 : 「役割オブジェクト」を更新
- 2003/5/24 : 「役割オブジェクト」を更新
- 2003/5/23 : 「役割オブジェクト」を更新
- 2003/5/22 : 「役割オブジェクト」を更新
- 2003/5/21 : 「役割オブジェクト」を更新
- 2003/5/17 : 「役割オブジェクト」を更新
- 2003/5/16 : 「役割オブジェクト」を更新
- 2003/5/15 : 「役割オブジェクト」を追加
- 2003/5/13 : 「拡張オブジェクト」を更新
- 2003/5/12 : 「拡張オブジェクト」を更新
- 2003/5/10 : 「拡張オブジェクト」を更新
- 2003/5/9 : 「拡張オブジェクト」を更新
- 2003/4/29 : Factory Method を更新
- 2003/4/28 : Factory Method を更新
- 2003/4/26 : Observer を更新
- 2003/4/25 : Observer を更新
- 2003/4/21 : Observer を更新
- 2003/4/19 : Observer を更新
- 2003/4/18 : Decorator を更新
- 2003/4/17 : Decorator を更新
- 2003/4/16 : Decorator を更新
- 2003/4/15 : Decorator を更新
- 2003/4/11 : Decorator を更新
- 2003/4/9 : Decorator を更新
- 2003/4/8 : Decorator を更新
- 2003/4/7 : Decorator を更新
- 2003/4/6 : Decorator を更新
- 2003/4/5 : Decorator を更新
- 2003/4/4 : Decorator を更新
- 2003/4/3 : Decorator を更新
- 2003/4/2 : Decorator を更新
- 2003/4/1 : Decorator を更新
- 2003/3/30 : Decorator を更新
- 2003/3/29 : Decorator を更新
- 2003/3/28 : Decorator を更新
- 2003/3/18 : Decorator を更新
- 2003/3/16 : Decorator を更新
- 2003/3/14 : Decorator を更新
- 2002/12/15 : Bridge に挑戦。
- 2002/11/26 : Decorator を更新
- 2002/11/24 : Decorator を更新
- 2002/11/23 : Decorator を更新
- 2002/11/22 : 注意書きを更新。Decorator を更新
- 2002/10/9 : Extension Object を追加。
- 2002/9/30 : Decorator を更新。
- 2002/9/29 : Decorator を更新。
- 2002/9/28 : Decorator を更新。
- 2002/9/26 : Decorator を追加。
todo
- 参考文献に「Pitfalls of AspectJ Implementations of Some of the Gang-of-Four Design Patterns」を追加すること。
- 動的横断と静的横断の視点から考える。
- DP 再考: なぜ役に立つのか
- DP 再考: なぜ必要なのか
- DP 再考: なぜこの形なのか
- DP 再考: 何が目的だったのか