@IT情報マネジメント会議室は、2009年4月15日に新システムに移行しました。
新たに書き込みを行う場合には、新しい会議室をご利用ください。
- PR -

アスペクト指向とは?

投稿者投稿内容
まほ
常連さん
会議室デビュー日: 2004/07/30
投稿数: 23
投稿日時: 2004-07-30 16:14
はじめまして。私はJAVA経験3ヶ月の初心者です。
J2EEのサーバーサイドについて勉強しています。
いきなりですが、アスペクト指向が漠然としてのイメージしか湧かずどのように有効でどのようなものか知りたいと思ってします。(JAVAですのでAspectJについて)
勉強していると、たまに記事があってコードが少なくなり、複数ののオブジェクトにまたがり分散している処理をモジュール化する考えだと思っています。
自分で調べてみたものの、「横断的関心事をモジュール化」でき、少しのコードでログの出力ができる。とか、ありましたが、JAVAのフィルタに似てるようで、アスペクト指向の利点がよくわからなくなりました。
ログやエラーの処理をモジュール化できるのは結構いいなっと思いましたが
なんとなく、考え方が少し違うのかな?って気もします・・・
アスペクト指向ってどういうのなのかきちんと理解したいです。
初心者でも、調べればわかるだろう事かもしれませんが、よろしくお願いします。
vincent
大ベテラン
会議室デビュー日: 2004/07/09
投稿数: 142
投稿日時: 2004-07-30 21:05
「横断的関心事を…」というアスペクト指向の前に、
まずオブジェクト指向の復習から入ってみましょう。
たとえば、継承関係をもつ以下のようなクラス群があるとします。
class Parent {
 void doSomething(){
  System.out.println("this is Parent");
 }
}
class Child extends Parent {
 void doSomething(){
  System.out.println("this is Child");
 }
}
class Grandchild extends Child{
 void doSomething(){
  System.out.println("this is Grandchild");
 }
}
これらはすべてParentクラスのインスタンスとして扱えます。
Parent p1 = new Parent();
Parent p2 = new Child();
Parent p3 = new Grandchild();

そして各クラスのdoSomething()メソッドについても
「同じ型の同じ名前で」として呼び出すことができます。
つまり、こういうことができます。
Parent[] pArray = new Parent[]{p1, p2, p3};
for(int i = 0; i < pArray.length; i++){
 //実際には違うクラスのメソッドを統一した書き方で実行
 pArray[i].doSomething();
}

実行結果は各インスタンス毎に異なりますが、すべて
「ParentインスタンスのdoSomething()」として統一的に
扱うことができました。もちろん、直接継承関係になくても
interfaceを使えばさまざまなクラスのメソッドを統一的に
扱うことができます。

ですが、この方法にもいくつか問題点があります。
そこで、アスペクト指向が登場してくるわけです。
ここまでOKでしょうか? 長いので続きは次回。

間違ったこと言ってたら突っ込んで下さい>識者の方々
vincent
大ベテラン
会議室デビュー日: 2004/07/09
投稿数: 142
投稿日時: 2004-07-30 22:06
先ほどの例では、それぞれ違うクラスの処理を統一的に扱う方法を紹介しました。
しかし、この方法を使う場合は必ず、扱いたい各オブジェクトが
継承関係にあるか同じinterfaceをimplementsしていなくてはなりません。
そして、実行させたい処理のメソッドシグネチャ(メソッド名+引数の形)も
同じでなくてはなりません。
つまり、同じグループとして扱える最小単位=同じ型にキャストできる単位に
なるわけです。

ですから、以下のようなクラス群の場合は先ほどの方法が使えません
class Alpha{
 void doAlpha(){//これを実行させたい
  System.out.println("this is Alpha");
 }
}
class Beta{
 void doBeta(){//これを実行させたい
  System.out.println("this is Beta");
 }
}
class Gamma{
 void doGamma(){//これを実行させたい
  System.out.println("this is Gamma");
 }
}

前回とは違い、これらは同じ型として扱えません。
Alpha a = new Alpha();
Beta b = new Beta();
Gamma g = new Gamma();

でも一括処理したいので(仕方なく)Objectの配列として扱います。
Object objArray = new Object[]{a, b, g};

そうすると、だいたいこんな感じになります。ダサいですねえ。
for(int i = 0; i < objArray.length; i++) {
 if(objArray[i] instanceof Alpha){
  Alpha a = (Alpha)objArray[i];
  a.doAlpha();
 }else if(objArray[i] instanceof Beta){
  Beta b = (Beta)objArray[i];
  b.doBeta();
 }else if(objArray[i] instanceof Gamma){
  Gamma g = (Gamma)objArray[i];
  g.doGamma();
 }
}
前回とは違い、非常に見苦しいコードになってしまいました。コードの量が多いのも
もちろんそうですが、これでは扱いたいクラスが増えるたびに↑の分岐を
書き足さなくてはなりません。また、使っていたクラスのメソッドが廃止されたときも
コードに修正が必要となります。残業や徹夜も増えます。

で、ここでやっとアスペクト指向がでてきます。アスペクト指向の考え方では
上記のような(クラスやメソッドシグネチャが違う)場合でもオブジェクト群を
統一的に扱うことができます。

簡単に言うと、オブジェクトの型情報に依存しないで上記コードの
//これを実行させたい
の部分を抽出して実行していくわけです。
(イメージ)
for(int i = 0; i < objArray.length; i++) {
 //何ていうクラスかはどうでもいいけど
//もしobjArray[i]に「これを実行させたい」マークの付いた
 //メソッドがあったら実行する
}
Javaの場合、上記のような命令をJava言語固有の文法だけで
表現することができないため、支援ツールとしてAspectJなどを使います。
(C#であれば「属性」を使うことでアスペクト指向を表現できます)
このような「マークづけ」がクラス階層に依存しないことを指して
「横断的関心事をモジュール化」と言っているわけです。

できるだけ具体的に…と書いてみましたが如何でしたでしょうか。
長々とすいません。
まほ
常連さん
会議室デビュー日: 2004/07/30
投稿数: 23
投稿日時: 2004-08-02 14:32
vincentさん。
細やかな説明ありがとうございます。考えていたこととまったく違い、とても勉強になります。
やっと、なんとなく見えてきた感じはします。やはり、すぐには理解できないようですが・・・

>上記のような(クラスやメソッドシグネチャが違う)場合でもオブジェクト群を
>統一的に扱うことができます。

上記の意味を理解できるようにもう少し勉強したいと思います。
頭ではぼんやりとしたイメージはあるのですが、まだまだわかってません。
継承関係(オブジェクトの型情報など)に依存せずオブジェクト群を統一的に操作できる。ことは初めて知りました。 ←考え方間違ってないですよね?

まだまだ、勉強していくので
些細なことでもけっこうですから、教えていただけたらと思います。
未記入
常連さん
会議室デビュー日: 2004/08/03
投稿数: 21
投稿日時: 2004-08-03 11:57
はじめまして。
アスペクト指向を勉強してみようかなと思っています。

アスペクト指向の利点って何ですか?
利点がよくわかりません。
でゅうく
大ベテラン
会議室デビュー日: 2003/11/30
投稿数: 129
投稿日時: 2004-08-03 15:29
下記が参考になると思いますよ。

http://www.atmarkit.co.jp/farc/rensai/redge24/redge24.html
t-wata
大ベテラン
会議室デビュー日: 2002/07/12
投稿数: 209
お住まい・勤務地: 東京
投稿日時: 2004-08-03 16:02
例えば、各コンポーネントのメソッドごとに、ユーザーアカウントによるアクセス
制限をかける場合、各メソッドの入り口で、ユーザー名を取得して、別途設定された
ポリシーに従いチェックし、正当な権限を持たないなら例外をスローする必要があり
ます。

と言うわけで、ユーザーを認証するモジュールとポリシーチェックを行うモジュール
を作り、各メソッドの入り口でチェックをするようにコーディングしたとしましょう。

さて、ここで、ユーザーごとにポリシーを設定するのが面倒なので、ユーザーに
対してロールを設定し、ロールベースのアクセス制限に変更したい、また、1人の
ユーザーに複数のロールを割り当てたい、という要求が来たとします。
いかがですか?そもそもアクセス制限の方法なんて、コンポーネント開発者が意識
しなきゃいけないの?フレームワークやランタイムでやってくれりゃいいのに、
と感じてしまいますよね。

AOPでは、このアクセス制限のようなコンポーネントによらないものを「横断的関心」
と呼びます。そして、横断的関心と、コンポーネントロジックを分離するための手段
を提供しています。
この場合、AOPを使えば、各コンポーネントは一切アクセス制限などしていなくても、
後からアクセス制限モジュールを呼び出すロジックを織り込むことができます。

AspectJの場合、

public aspect AccessControl {
pointcut doCheck() : execution(public *.*(..))&&!within(package.acl.*);
before(): doCheck() {
//認証モジュールから、認証済みユーザー名を取得
User user = Authentication.getCurrentUser();
//ユーザー名からロール名を取得
Role[] roles = user.getRoles();
//ポリシーチェックモジュールによりチェック
boolean isValid = false;
for (int i = 0;i < roles.length; i++){
isValid = isValid ? true : Policy.check(roles[i], thisJoinPoint.getThis().getClass());
}
if (!isValid)
throw new AccessControlException("Authentication failer for current user");
}

というようなAspectを1つ作って、javacの代わりにajcを使って全コンポーネント
をコンパイルするだけで済みます。
認証モジュールやポリシーチェックモジュールの仕様が変更されても、修正箇所が
非常に少なくて済みますし、各コンポーネントはポリシーチェックモジュールや
認証モジュールに依存しないので、再利用性が高くなります。
未記入
常連さん
会議室デビュー日: 2004/08/03
投稿数: 21
投稿日時: 2004-08-03 18:05
引用:--------------------------------------------------------------------------------
AspectJの場合
pointcut doCheck() : execution(public *.*(..))&&!within(package.acl.*);
before(): doCheck() {・・・}
--------------------------------------------------------------------------------
とありますが、aclというパッケージの実行する前にチェックを行なう処理で、aclには何も加えなくてもよく、変更が起こっても、doCheck()だけを変えればいいってことですか?
このように、同じような処理をいろいろな所で行っているのを横断と言い、これをまとめることがアスペクト指向なのかな?
おかしいトコは突っ込んでください。

スキルアップ/キャリアアップ(JOB@IT)