1. ホーム
  2. oop

[解決済み】アスペクト指向プログラミングとオブジェクト指向プログラミングの比較

2022-04-09 22:09:11

質問

私は、世界中の多くの開発者と同様、長年にわたりオブジェクト指向プログラミング(OOP)の手法でソフトウェアシステムを開発してきました。ですから、アスペクト指向プログラミング(AOP)が、従来のOOPでは完全には解決できない、あるいは直接的には解決できない問題の多くに対応しているという記事を読んだとき、私は立ち止まって、これは本当だろうか、と考えました。

私は、このAOPパラダイムを学ぶために多くの情報を読みましたが、私も同じような境遇にあります。

誰か答えを知っていますか?

解決方法は?

なぜ"vs"なのか?vs"ではないのです。アスペクト指向プログラミングは、関数型プログラミングと組み合わせて使うこともできますし、オブジェクト指向プログラミングと組み合わせて使うこともできます。vs"ではなく、"Aspect Oriented Programming(アスペクト指向プログラミング)です。 オブジェクト指向プログラミング" です。

私にとっては、AOPはある種のメタプログラミングです。AOPが行うことはすべて、コードを追加するだけで、AOPなしでも可能なことなのです。AOPはこのコードを書く手間を省いてくれるだけです。

Wikipediaには、このメタプログラミングの最も良い例の一つが掲載されています。たくさんのset...()"メソッドを持つグラフィカルなクラスがあるとします。各setメソッドの後、グラフィックのデータが変更され、その結果、グラフィックも変更され、その結果、グラフィックを画面上で更新する必要があります。グラフィックを再描画するには、"Display.update()"を呼び出す必要があると仮定してください。古典的なアプローチでは、これを解決するために その他のコード . 各セットメソッドの最後には、次のように記述します。

void set...(...) {
    :
    :
    Display.update();
}

set-methodが3つあれば問題ないでしょう。200個もあれば(仮に)、これをあちこちに追加するのは本当に苦痛になってきます。また、新しいセットメソッドを追加するときは、必ずこのメソッドを最後に追加することを忘れないようにしないと、バグが発生します。

AOPでは、大量のコードを追加することなく、代わりにアスペクトを追加することでこれを解決しています。

after() : set() {
   Display.update();
}

で、終わり!?更新コードを自分で書く代わりに、set() ポイントカットに到達した後、このコードを実行しなければならないとシステムに伝えるだけで、このコードを実行するようになるのです。200個のメソッドを更新する必要も、新しいset-methodでこのコードを追加し忘れないようにする必要もありません。さらに、ポイントカットが必要なだけです。

pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);

どういう意味ですか?つまり、メソッドの名前が "set*"(*は set の後に続く任意の名前)である場合、そのメソッドが返すもの(最初のアスタリスク)や取るパラメータ(3番目のアスタリスク)に関係なく、次のようなことを意味します。 そして MyGraphicsClass のメソッドである。 このクラスは "com.company.*" パッケージの一部であるため、これは set() ポイントカットとなります。そして、最初のコードでは " セットポイントカットのメソッドを実行する場合は、次のコード"を実行してください。

AOPがいかにこの問題をエレガントに解決しているか、おわかりいただけたでしょうか。実はここで説明したことはすべて、コンパイル時に行うことができるのです。AOPプリプロセッサは、クラス自体をコンパイルする前に、ソースを修正するだけです(たとえば、すべてのセットポイントカット・メソッドの末尾に Display.update() を追加します)。

しかし、この例はAOPの大きな欠点の1つも示しています。AOPは、多くのプログラマーが「"」と考えることを実際に行っているのです。 アンチパターン "です。正確には、".というパターンです。 遠距離での動作 "です。

距離を置いて行動することは アンチパターン(一般的に認識されている ある部分の動作が に基づいて大きく変化します。 特定が困難または不可能な の操作を別の場所で行うことができます。 プログラムです。

プロジェクト初心者の私は、どのset-methodのコードを読んでも、表示が更新されないようなので、壊れたと思うだけかもしれません。私は 見る セットメソッドのコードを見ただけでは、それが実行された後、他のコードが魔法のように実行され、表示が更新されるとは思えません。私は、これは重大な欠点だと考えています。メソッドに変更を加えることで、変なバグが発生する可能性があるのです。正しく動作しているように見えて、自明ではない(魔法のように動作している)コードの流れをさらに理解することは、本当に難しいことです。

更新情報

それをはっきりさせるために。AOPは悪いもので、使うべきではないと言っているように思われる方もいらっしゃるかもしれません。そうではありません。AOPは実際に素晴らしい機能です。ただ、「慎重に使いましょう」と言っているだけです。AOPが問題を起こすのは、通常のコードとAOPを同じように混在させた場合だけです。 アスペクト . 上の例では、グラフィカル オブジェクトの値を更新し、更新されたオブジェクトをペイントするというアスペクトがあります。これは、実際には1つのアスペクトです。その半分を通常のコードとして、残りの半分をアスペクトとしてコーディングすることが、問題を追加するものです。

もし、全く別の側面、例えばロギングにAOPを使うのであれば、アンチパターンの問題には直面しないでしょう。この場合、プロジェクトの初心者は、「このログメッセージはどこから来るのだろう?コードにはログ出力が見当たらないのですが......」と思うかもしれませんが、それは大きな問題ではありません。プログラムロジックを変更しても、ログ機能はほとんど壊れませんし、ログ機能を変更しても、プログラムロジックはほとんど壊れません - これらの側面は完全に分離されています。ロギングにAOPを使用することで、プログラムコードがやるべきことに完全に集中でき、かつ、何百ものログメッセージでコードが散らかることなく、高度なロギングを行うことができるという利点があります。また、新しいコードが導入されたとき、魔法のようにログメッセージが適切なタイミングで、適切な内容で表示されます。初心者のプログラマーは、なぜそれがあるのか、どこから来たのか理解できないかもしれませんが、「正しいこと」を「正しいタイミング」で記録するので、それがあるという事実を喜んで受け入れて、他のことに移ることができます。

ですから、私の例のAOPの良い使い方は、setメソッドで値が更新された場合は常にログを取ることです。これはアンチパターンを作らないし、問題の原因になることもほとんどない。

AOPを悪用して簡単に多くの問題が発生するのであれば、すべてを利用するのは良くないと言う人もいるかもしれません。しかし、どの技術が悪用されないのでしょうか?データのカプセル化を悪用することも、継承を悪用することもできます。有用なプログラミング技術のほとんどすべてが悪用される可能性があります。例えば、悪用できない機能だけを集めたプログラミング言語があったとします。そのような言語は、現実のプログラミングに使えるかどうかさえ議論の余地があるほど制限されたものでしょう。