@it_gateです。
プログラミングの方法論、オブジェクト指向プログラミング(通称OOP)とアスペクト指向プログラミング(通称AOP)について少々。

アスペクト指向プログラミングもオブジェクト指向プログラミングと同様に属性と手続きをセットにすることで、取り回しのしやすい(=再利用しやすい)モジュール分割を実現する方法論です。独立性が高いと言ったりもします。モジュール分割という目標こそ同じですが、アスペクト指向とオブジェクト指向とでは分割する切り口が変わってきます。

オブジェクト指向では、モジュールを現実世界のモノと見立てて「汎化/特化」の継承関係を加味してモジュール分割を行います。これらモジュールをオブジェクトと呼ぶわけですが、例えば生き物がモデルなら「犬は哺乳類」「猫も哺乳類」「哺乳類は動物」「爬虫類も動物」といった具合で、動物に共通してみられる特徴(属性)や動作(手続き)は「動物」オブジェクトに全て持たせ、哺乳類固有の特徴や手続きのみを「哺乳類」オブジェクトに持たせます。加えて「哺乳類は動物である」と継承関係を定義することで、「哺乳類」オブジェクトに「動物」オブジェクトの機能を持たせることができるという考え方です。動物に限らず「官製ハガキもハガキ」「往復ハガキもハガキ」「ハガキは郵便物」「手紙も郵便物」といったモノの分け方もオブジェクト指向です。分け方に決まりはないので、如何に簡潔な単位に分けれるかがプログラマーの腕の見せどころです。「犬」「猫」「官製ハガキ」「往復ハガキ」といった最終的なオブジェクトが具体的であればある程、「哺乳類」「爬虫類」「動物」「郵便物」といった途中のオブジェクトで共通の特徴が洗い出せれば洗い出せる程、一般的にオブジェクト指向としての品質は高くなります。

アスペクト指向では、「関心事」という側面でモジュール分割を行います。例えば、同じ「犬」というオブジェクトであっても、「飼い犬」や「野良犬」や「警察犬」、「盲導犬」では関心事が違ってくると思います。「関心事」という言葉が少々分かり辛いですが、例えば飼い犬ならご飯を食べている時「食べること以外に何も関心がない」けど、野良犬なら「周囲に敵が迫ってこないか気にしているよ」とか、警察犬や盲導犬なら「ご主人からの指示がないか常に気にかけているよ」等です。これらはオブジェクト指向と比べて曖昧で具体的にコレと導くのが難しく、「こういう傾向がある(こういう傾向を持たせたい)」というくらいのさじ加減(つまり経験)がものをいうモジュール分割手法です。この「ご飯たべている時は〜だよ」という「関心事」はオブジェクト(独立したモノ)として成り立っていないということが理解できればとりあえずはいいと思います。「〜の時は」というモジュールの適用範囲も含めてAOPの範囲です。

オブジェクト指向とアスペクト指向は共存する関係で、「犬」というオブジェクトはそのままに、「飼い犬」か「野良犬」か「警察犬」か「盲導犬」かで異なる「関心事」を後付けでくっつけてしまおうというのがアスペクト指向です。「それなら飼い犬とか野良犬とかいうオブジェクトに直接持たせてやれば?」という意見がでそうですが、「犬」というオブジェクトには手を加えなくて良い(テスト済みのオブジェクトが使える!)という事と、横断的な「関心事」を1まとめにできるのがアスペクト指向のメリットです。先ほどの例だと警察犬と盲導犬の「ご主人の指示に気をかける」というのが2つのオブジェクトで横断的な関心事になります。

..ちなみに、「飼い犬」か「野良犬」かといった違いは生活環境程度の違いでしかなく(もしかしたら警察犬は固有の能力を持っているかもしれませんが)、メソッド内部の振る舞いは変われどオブジェクト指向の汎化/特化程の違いは生まれ難いため、マーカーインタフェースで色分けするという感じが多いです。(急に実装の話しになってすみません。。)

関心事で分けられるということは、逆に関心の無い事は気にしなくていい(実装しなくていい)という事でもあります。自分では気にしなくても、後で関心を持っている誰かがプログラミングしてくれます。

オブジェクト指向の流れで「犬」で説明を始めましたが、もはやアスペクト指向はオブジェクトとは関係ないのでプログラミングで話した方が分かりやすいと思います。例えば「ログイン機能」、「画面出力機能」「PDF出力機能」と「プリンタ出力機能」を持つアプリケーションがあったとして、他には目もくれずこれら機能を実装します。その後で、実はもう一つあった「出力を行う場合にはユーザー認証が済んでいることを確認を忘れないでね」という機能を取り込むために、ユーザー認証の確認を行う機能を別途1つ実装して出力処理に後付けしてやる流れがアスペクト指向を適用する流れになります。

後付けの仕組みとしては、ボタン操作等を通じてアプリケーションが呼び出すこれら出力機能の「出力メソッド」を横取り(インターセプト)し、先にユーザー認証の確認を済ませた後、本来の「出力メソッド」へ処理を戻すアプローチ。より具体的な実現方法ではProxyメソッドを呼び出す実装にしておき後から別のメソッドを差し込める様にしておく方法や、コンパイルや動的リンクの際に別のメソッドを織り交ぜる方法でインターセプトするという等の仕組みで実現されます。JavaではProxyタイプのAOPであればSpring等のフレームワークが、コンパイルや実行時に織り交ぜるAOPであればAspectJやJBossAOPが古くから提供されています。

メソッド呼び出しや例外発生時に様々なオブジェクトで横断的な(共通の)処理を行いたい場合は、AOPの導入を検討してみるのもいいと思います。ただ・・・後付けでインターセプトしてしまうものだから何処で何が呼ばれているのかソースを追うだけではつながらないのが困ったものです。闇雲に手を出すのはお勧めしません。個人的には例えばウェブサービスの認証確認等のかなり広範囲に渡って横断的実装が必要な場合に限定して使うのがいいと思っています。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です