アスペクト指向プログラミング
・オブジェクト指向とアスペクト指向
・オブジェクト指向
近年,プログラミング技法として一般に普及しているのが,オブジェクト指向プログラミングです.プログラミングの記事を載せているコンピュータ雑誌では,Java, C++ といったオブジェクト指向プログラミングに対応した言語を取り扱った入門記事がよく取り扱われるようになっています.
オブジェクト指向の特徴は,プログラムを「オブジェクト (object; 物)」の集合として捉えることにあります.オブジェクトはデータとそのデータに関連した機能の集合となります.たとえば,学生の成績管理プログラムでは,「学生」は氏名や成績といったデータと,それらを取り扱う種々の機能を持ったオブジェクトとなります.オブジェクトはそれぞれ特定の役割を与えられ,メッセージを相互にやり取りしながら全体としてひとつの処理を進めます.
このようなオブジェクト指向についての詳細は,関連リンクとして挙げたサイトなどを参考にしてください.
・オブジェクト指向の問題点
オブジェクト指向の特徴は,「オブジェクトがプログラムの分解単位である」ことです.これはつまり,「複数のオブジェクトにまたがる処理は複数の場所に分散する」ということを意味します.
たとえば,プログラムを作成したところ,何らかの欠陥(バグ)が見つかったとします.プログラムの動作がおかしいことは明白ですが,どこでおかしくなっているのかは分かりません.このような場合に,プログラム実行中の節目ごとにその途中経過を記録(ロギング)することが,欠陥の原因となっている部分を特定するために有効とされています.
Java におけるロギングのプログラムコード例を図に示します.ロギングに関連した部分を,赤色で書いてあります.
この図のように,ロギングするということは,文章で書くには一言で済みますが,プログラムの複数箇所にその命令を追加してやる必要があります.このとき,編集ツールの検索機能などを使って該当箇所を探すとしても,プログラムの書き換えは最終的に手作業となります.これは,次のような問題を引き起こします.
* 処理が複数箇所に分散します.後になって集めたい情報が増えたり,処理 そのものが不要になったりすると,それに合わせてすべての場所を変更する 必要が出てきます.
* プログラマが,処理を追加するべきでない場所に追加してしまう可能性があります.
* プログラマが,処理を追加するべき場所に追加し忘れる可能性があります.
* プログラマが,処理として誤ったコードを追加してしまう可能性があります.
* プログラマが,作業中に誤って本来のプログラムを壊してしまう可能性があります.
このロギングの例のように,オブジェクトをまたがった処理を「横断要素」と呼びます.横断要素が起こす問題はオブジェクト指向の特性に起因しており,オブジェクト指向を用いる限りは,ついてまわります.プログラムに分散した横断要素を検出,管理する作業をサポートするツールも研究されていますが,複数の横断要素が絡み合った場合への対処は困難なものとなっています.
「横断要素を分散させないためにはどうすればよいか」という問題提起に対するひとつの答えがアスペクト指向プログラミング,横断要素を一箇所に記述できるような言語要素 "アスペクト" の導入です.
・アスペクトとは
アスペクト指向プログラミングの基本的な考え方は,「横断要素」と呼ばれるオブジェクトをまたがった処理を,オブジェクトに分散させるのではなく単一のモジュール「アスペクト」にまとめて記述しておき,後からコンパイラなどのツールを用いてプログラムを結合しよう,ということにあります.
これを実現するために,アスペクト指向言語の処理系は,横断要素に関する処理を「明示的な呼び出し」なしで実行するメカニズムを提供しています.もし明示的な呼び出しが必要なのであれば,その呼び出し処理そのものが各所に分散してしまうからです.
処理系にもよりますが,「もし○○が起こったときは××する」というように条件付けたプログラムとしてアスペクトを記述できるようになっています.Java を拡張したアスペクト指向言語のひとつである AspectJ で,簡単なロギングを記述した例を示します.
// 先のロギングの例をアスペクトで書くと…
aspect Logging {
/* execution() 内部に書かれているメソッドの実行に対して動作
従来は,各メソッドの先頭にこのコードを書かないといけなかったが
アスペクトを使うと,オブジェクト側のコードには何も書かなくてよい.
*/
around: execution(void Foo.foo()) ||
execution(void Bar.doSomething()) ||
execution(static void Baz.doSomething())) {
// この実行時点(join point)で,呼び出されているメソッドを記録
// thisJoinPoint はどのメソッド呼び出しに相当するかの情報を持っている
logger.log("start - " + thisJoinPoint.getSignature());
// 呼び出されているメソッドの実行
proceed();
logger.log("end - " + thisJoinPoint.getSignature());
}
}
このようにアスペクトを用いることで,横断要素がもたらしたコード分散の問題を解決することができます.アスペクト指向の特徴は,次のようにまとめることができます.
* オブジェクト指向との違いは,アスペクトに横断要素をカプセル化することだけです.アスペクト指向プログラムからアスペクトを取り除くと,横断要素だけを取り除いた完全な形のオブジェクト指向プログラムになります.
* 横断要素は,複数のオブジェクトに分散することを除けば,簡単なプログラムとなることが多いということが経験的に判明しています.アスペクトとして分離した横断要素は直感的で理解しやすく,簡単に書き換えることができます.また,再利用も容易となります.
* オブジェクトから横断要素を取り除くことで,オブジェクトにはその本質的な機能だけを記述することができるようになります.これによって保守性や可読性,再利用性の向上につながります.
* アスペクトとオブジェクトの結合はコンパイル時あるいはリンク時に機械的に行われるので,人間の間違いは入り込みにくくなります.
アスペクト指向プログラミングの概念や実践例に関する情報は,日本語でもいくつかのサイトから入手することができます.関連リンクなどを参照してください.
・研究内容
アスペクト指向によって,横断要素の分離が実現されるようになりました.しかし,それによって,新たな問題もまた浮上してきています.現在,アスペクト指向プログラミングに対して成されている研究には次のようなものがあります.
* アスペクトの適用
アスペクトを用いて簡潔に記述できるような横断要素として何があるか,アスペクトを用いてその横断要素を記述することがどのような影響をもたらすかについての研究.また,アスペクトとして書くべきでない要素,書くことで保守性をかえって悪化させるような要素に関する研究.
* アスペクトの発見
オブジェクト指向で書かれた従来のプログラム内に分散した横断要素を発見し,アスペクトを抽出する作業を機械的にサポートするための研究.
* アスペクトの検証
複数のアスペクトが絡み合った際に相互に干渉を与え,正しい動作を不能とする可能性を発見するための技術に関する研究.
我々の研究グループでは,アスペクトを用いたプログラムの実行時解析の実現,アスペクトを含んだプログラムに対するプログラム解析の実現などを研究しています.
・オブジェクト指向
近年,プログラミング技法として一般に普及しているのが,オブジェクト指向プログラミングです.プログラミングの記事を載せているコンピュータ雑誌では,Java, C++ といったオブジェクト指向プログラミングに対応した言語を取り扱った入門記事がよく取り扱われるようになっています.
オブジェクト指向の特徴は,プログラムを「オブジェクト (object; 物)」の集合として捉えることにあります.オブジェクトはデータとそのデータに関連した機能の集合となります.たとえば,学生の成績管理プログラムでは,「学生」は氏名や成績といったデータと,それらを取り扱う種々の機能を持ったオブジェクトとなります.オブジェクトはそれぞれ特定の役割を与えられ,メッセージを相互にやり取りしながら全体としてひとつの処理を進めます.
このようなオブジェクト指向についての詳細は,関連リンクとして挙げたサイトなどを参考にしてください.
・オブジェクト指向の問題点
オブジェクト指向の特徴は,「オブジェクトがプログラムの分解単位である」ことです.これはつまり,「複数のオブジェクトにまたがる処理は複数の場所に分散する」ということを意味します.
たとえば,プログラムを作成したところ,何らかの欠陥(バグ)が見つかったとします.プログラムの動作がおかしいことは明白ですが,どこでおかしくなっているのかは分かりません.このような場合に,プログラム実行中の節目ごとにその途中経過を記録(ロギング)することが,欠陥の原因となっている部分を特定するために有効とされています.
Java におけるロギングのプログラムコード例を図に示します.ロギングに関連した部分を,赤色で書いてあります.
この図のように,ロギングするということは,文章で書くには一言で済みますが,プログラムの複数箇所にその命令を追加してやる必要があります.このとき,編集ツールの検索機能などを使って該当箇所を探すとしても,プログラムの書き換えは最終的に手作業となります.これは,次のような問題を引き起こします.
* 処理が複数箇所に分散します.後になって集めたい情報が増えたり,処理 そのものが不要になったりすると,それに合わせてすべての場所を変更する 必要が出てきます.
* プログラマが,処理を追加するべきでない場所に追加してしまう可能性があります.
* プログラマが,処理を追加するべき場所に追加し忘れる可能性があります.
* プログラマが,処理として誤ったコードを追加してしまう可能性があります.
* プログラマが,作業中に誤って本来のプログラムを壊してしまう可能性があります.
このロギングの例のように,オブジェクトをまたがった処理を「横断要素」と呼びます.横断要素が起こす問題はオブジェクト指向の特性に起因しており,オブジェクト指向を用いる限りは,ついてまわります.プログラムに分散した横断要素を検出,管理する作業をサポートするツールも研究されていますが,複数の横断要素が絡み合った場合への対処は困難なものとなっています.
「横断要素を分散させないためにはどうすればよいか」という問題提起に対するひとつの答えがアスペクト指向プログラミング,横断要素を一箇所に記述できるような言語要素 "アスペクト" の導入です.
・アスペクトとは
アスペクト指向プログラミングの基本的な考え方は,「横断要素」と呼ばれるオブジェクトをまたがった処理を,オブジェクトに分散させるのではなく単一のモジュール「アスペクト」にまとめて記述しておき,後からコンパイラなどのツールを用いてプログラムを結合しよう,ということにあります.
これを実現するために,アスペクト指向言語の処理系は,横断要素に関する処理を「明示的な呼び出し」なしで実行するメカニズムを提供しています.もし明示的な呼び出しが必要なのであれば,その呼び出し処理そのものが各所に分散してしまうからです.
処理系にもよりますが,「もし○○が起こったときは××する」というように条件付けたプログラムとしてアスペクトを記述できるようになっています.Java を拡張したアスペクト指向言語のひとつである AspectJ で,簡単なロギングを記述した例を示します.
// 先のロギングの例をアスペクトで書くと…
aspect Logging {
/* execution() 内部に書かれているメソッドの実行に対して動作
従来は,各メソッドの先頭にこのコードを書かないといけなかったが
アスペクトを使うと,オブジェクト側のコードには何も書かなくてよい.
*/
around: execution(void Foo.foo()) ||
execution(void Bar.doSomething()) ||
execution(static void Baz.doSomething())) {
// この実行時点(join point)で,呼び出されているメソッドを記録
// thisJoinPoint はどのメソッド呼び出しに相当するかの情報を持っている
logger.log("start - " + thisJoinPoint.getSignature());
// 呼び出されているメソッドの実行
proceed();
logger.log("end - " + thisJoinPoint.getSignature());
}
}
このようにアスペクトを用いることで,横断要素がもたらしたコード分散の問題を解決することができます.アスペクト指向の特徴は,次のようにまとめることができます.
* オブジェクト指向との違いは,アスペクトに横断要素をカプセル化することだけです.アスペクト指向プログラムからアスペクトを取り除くと,横断要素だけを取り除いた完全な形のオブジェクト指向プログラムになります.
* 横断要素は,複数のオブジェクトに分散することを除けば,簡単なプログラムとなることが多いということが経験的に判明しています.アスペクトとして分離した横断要素は直感的で理解しやすく,簡単に書き換えることができます.また,再利用も容易となります.
* オブジェクトから横断要素を取り除くことで,オブジェクトにはその本質的な機能だけを記述することができるようになります.これによって保守性や可読性,再利用性の向上につながります.
* アスペクトとオブジェクトの結合はコンパイル時あるいはリンク時に機械的に行われるので,人間の間違いは入り込みにくくなります.
アスペクト指向プログラミングの概念や実践例に関する情報は,日本語でもいくつかのサイトから入手することができます.関連リンクなどを参照してください.
・研究内容
アスペクト指向によって,横断要素の分離が実現されるようになりました.しかし,それによって,新たな問題もまた浮上してきています.現在,アスペクト指向プログラミングに対して成されている研究には次のようなものがあります.
* アスペクトの適用
アスペクトを用いて簡潔に記述できるような横断要素として何があるか,アスペクトを用いてその横断要素を記述することがどのような影響をもたらすかについての研究.また,アスペクトとして書くべきでない要素,書くことで保守性をかえって悪化させるような要素に関する研究.
* アスペクトの発見
オブジェクト指向で書かれた従来のプログラム内に分散した横断要素を発見し,アスペクトを抽出する作業を機械的にサポートするための研究.
* アスペクトの検証
複数のアスペクトが絡み合った際に相互に干渉を与え,正しい動作を不能とする可能性を発見するための技術に関する研究.
我々の研究グループでは,アスペクトを用いたプログラムの実行時解析の実現,アスペクトを含んだプログラムに対するプログラム解析の実現などを研究しています.
コメント
コメントを投稿