アスペクト指向プログラミングvs.オブジェクト指向プログラミング


199

ここや世界中のほとんどの開発者と同様に、私は長年、オブジェクト指向プログラミング(OOP)技術を使用してソフトウェアシステムを開発しています。ですから、アスペクト指向プログラミング(AOP)は、従来のOOPが完全にまたは直接解決できない多くの問題に対処していることを読んだとき、一時停止して考えます、それは本当ですか?

私はこのAOPパラダイムの鍵を学ぶために多くの情報を読み、同じ場所にいるので、実際のアプリケーション開発におけるその利点をよりよく理解したいと思いました。

誰かが答えを持っていますか?


7
すべての回答は非常に良好でした。これは、すべてを組み合わせた単一のコミュニティ編集回答の完璧なケースです。すべてが同じことを言ってますが、さまざまな方法で、全体的な価値に追加する別の例を使用している
Vinko Vrsalovicを

回答:


323

なぜ「対」なのか?「対」ではありません。アスペクト指向プログラミングは関数型プログラミングと組み合わせて使用​​できますが、オブジェクト指向プログラミングと組み合わせて使用​​することもできます。それは「対」ではなく、「オブジェクト指向プログラミングによるアスペクト指向プログラミング」です。

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

ウィキペディアには、このメタプログラミングの最良の例の1つがあります。多くの "set ...()"メソッドを持つグラフィカルクラスがあると仮定します。各設定メソッドの後で、グラフィックのデータが変更されたため、グラフィックが変更され、画面上でグラフィックを更新する必要があります。グラフィックを再描画するには、「Display.update()」を呼び出す必要があると仮定します。古典的なアプローチは、コードを追加してこれを解決することです。あなたが書く各setメソッドの終わりに

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

3つの設定方法がある場合、それは問題ではありません。200(仮説)がある場合、これをどこにでも追加するのは本当に大変です。また、新しいset-methodを追加するときはいつでも、これを最後に追加することを忘れないでください。そうでなければ、バグを作成しただけです。

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

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

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

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

どういう意味ですか?関係なく、どのような方法が戻る(最初のアスタリスク)または何パラメータには(第3アスタリスク)を取る方法は、「セット*」(*は任意の名前をセットした後に続く可能性がある意味)と命名されている場合の手段、それそれがMyGraphicsClassの方法である、このクラスがパッケージ「com.company。*」の一部である場合、これはset()ポイントカットです。そして、私たちの最初のコードでは、「言うた後、設定されたポイントカットである任意の方法を実行し、次のコードを実行します」。

AOPが問題をエレガントに解決する方法をここで確認しますか?実際に、ここで説明されていることはすべてコンパイル時に行うことができます。AOPプリプロセッサーは、クラス自体をコンパイルする前に、ソースを変更する(たとえば、すべてのset-pointcutメソッドの最後にDisplay.update()を追加する)ことができます。

ただし、この例は、AOPの大きな欠点の1つも示しています。AOPは実際、多くのプログラマーが「アンチパターン」と見なしていることを行っています。正確なパターンは「遠くでのアクション」と呼ばれます。

離れた場所でのアクションはアンチパターン(認識された一般的なエラー)であり、プログラムの一部での動作は、プログラムの別の部分での操作の識別が困難または不可能であることに基づいて大きく異なります。

プロジェクトの初心者として、私は任意のセットメソッドのコードを読んでそれが壊れていると考えるかもしれません、それは表示を更新しないようです。set-methodのコードを見ただけではわかりません。それが実行されると、他のコードが "魔法のように"実行されて表示が更新されます。これは深刻な欠点だと思います!メソッドに変更を加えると、奇妙なバグが発生する可能性があります。特定のことが正しく機能しているように見えても明らかではないコードのコードフローをさらに理解することは(私が言ったように、それらは魔法のように機能します...どういうわけか)、本当に難しいです。

更新

明確にするために:一部の人々は、私がAOPは何か悪いものであり、使用されるべきではないと言う印象を持っているかもしれません。それは私が言っていることではありません!AOPは実際には素晴らしい機能です。丁寧に使ってください。AOPは、通常のコードとAspectを同じアスペクトで混在させた場合にのみ問題を引き起こします。上記の例では、グラフィカルオブジェクトの値を更新し、更新されたオブジェクトをペイントするという側面があります。それは実際には単一の側面です。その半分を通常のコードとしてコーディングし、残りの半分をアスペクトとしてコーディングすると、問題が追加されます。

ロギングなど、まったく異なる側面でAOPを使用する場合、アンチパターンの問題は発生しません。その場合、プロジェクトの初心者は、「これらすべてのログメッセージはどこから来るのでしょうか?コードにログ出力が表示されません」と疑問に思うかもしれませんが、それは大きな問題ではありません。彼がプログラムロジックに加えた変更は、ログ機能を破壊することはほとんどなく、ログ機能を変更することは、プログラムロジックを破壊することはほとんどありません。これらの側面は完全に分離されています。ロギングにAOPを使用することには、プログラムコードが実行すべきことに完全に集中できるという利点があり、どこにでも何百ものログメッセージによってコードが乱雑になることなく、洗練されたロギングを維持できます。また、新しいコードが導入されると、魔法のようにログメッセージが適切なタイミングで適切なコンテンツで表示されます。

したがって、私の例でのAOPの適切な使用法は、setメソッドを使用して値が更新された場合に常にログを記録することです。これはアンチパターンを作成することはなく、問題の原因になることはほとんどありません。

AOPを簡単に悪用して非常に多くの問題を引き起こす可能性がある場合、それをすべて使用することは悪い考えです。しかし、どのテクノロジーを悪用できないのでしょうか?データのカプセル化を悪用したり、継承を悪用したりすることができます。ほとんどすべての有用なプログラミング技術が悪用される可能性があります。悪用できない機能のみが含まれるように制限されたプログラミング言語について考えてみましょう。最初に使用することを意図されていた機能のみを使用できる言語。このような言語は非常に制限されているため、実際のプログラミングにも使用できるかどうかは議論の余地があります。


4
ロギングは、AOPが遠距離でのアクションを引き起こさない1つの具体的な例のようです。現時点では、セキュリティチェックなどの側面を使用する例としてのWikipediaは、プログラムの流れを理解しやすくするものです。
kizzx2

7
@ kizzx2:実際のところ、ロギングの優れた点です。これは、AOPについてあまり知らなくても、これまでにAOPの強みを見てきた中で最も良い例です。共有してくれてありがとう!
2010年

@Mecki、あなたの例は過度に単純化されており、一般的なユースケースを反映していません。あなたの例でDisplay.updateは、は引数を取りません。引数を渡す必要がある場合はどうなりますか(たとえば、通常、log関数にはmessageパラメータが必要になります)。次に、AOPの方法で実行するために、ボイラープレートコードをたくさん追加する必要があるのではないでしょうか。
パセリエ2014年

3
@Pacerier SOは教育フォーラムではないため、私の例は簡略化されています。私は質問者の質問に答えただけで、おそらく必要以上に詳細でした。AOPについて詳しく知りたい場合は、プログラマー向けのドキュメントを読んでみてください。詳細な質問がある場合は、ここで質問してみてください。いいえ、ありませんコメントで、行くとので、新しい質問を作成することが SOすべてに約あるものです。きっと誰かが返信であなたの疑念を払拭することができるでしょう。
Mecki

2
@Pacerier申し訳ありませんが、私はあなたのポイントを見ることができません。ここを参照してください:stackoverflow.com/a/8843713/15809このコードは、すべてのメソッド引数タイプと値を含む、すべてのパブリックメソッドへのすべての呼び出しを記録します。これを正確に1回記述するだけで、ボイラープレートコードがメソッドに追加されることはありません。答えに示されているコードだけです。
メッキー2014

29

アスペクト指向の作図は、ロギング、セキュリティなどの分野横断的な問題を実装するための優れた方法を提供します。これらの分野横断的なコンサーは、多くの場所で適用する必要があるロジックの一部ですが、実際にはビジネスロジックとは何の関係もありません。

あなたは、AOPをOOPの代わりとして、より良いアドオンとして見るべきではありません。これにより、コードがよりクリーンになり、疎結合になり、ビジネスロジックに集中するようになります。したがって、AOPを適用することにより、2つの主要なメリットが得られます。

  1. 各懸念事項のロジックは、コードベース全体に分散しているのではなく、1か所にあります。

  2. クラスには、主な関心事(またはコア機能)のコードのみが含まれ、副次的な関心事がアスペクトに移動されているため、よりクリーンです。


27

OOPとAOPは相互に排他的ではありません。AOPはOOPに追加するのに適しています。AOPは、この標準コードでメソッドコードを詰まらせることなく、ロギング、パフォーマンストラッキングなどの標準コードをメソッドに追加する場合に特に便利です。


10

私はこの質問に対する一般的な答えはないと思いますが、注意すべき点の1つは、AOPがOOPに置き換わるものではなく、支配的な構成のいわゆる専制政治1)(または横断的関心事)に対処する特定の分解機能を追加することです。

特定のプロジェクトで使用するツールと言語を制御している限り、特定のケースで確かに役立ちますが、アスペクトの相互作用に関する新しいレベルの複雑さを追加し、AJDTなどの追加ツールの理解が必要です。あなたのプログラム。

Gregor Kiczalesはかつて、Google Tech TalksでAOPに関する興味深い紹介講演を行いました。これは、私が見るのをお勧めします:Aspect Oriented Programming:Radical Research in Modularity


8

まず、AOPはOOPに取って代わるものではありません。AOPはOOPを拡張します。OOPのアイデアと実践は関連性を保ちます。優れたオブジェクト設計があれば、アスペクトでそれを拡張することがより簡単になるでしょう。

AOPがもたらすアイデアは重要だと思います。クラス自体を変更せずに、プログラムのさまざまなクラスに横断的関心事を実装する方法を考え出す必要があります。しかし、AOPは最終的には、私たちが使用する他のツールの一部になるだけで、個別のツールや手法になることはないと思います。私たちはすでにこれが起こっているのを見ています。

RubyやPythonのようないくつかの動的言語には、同じ問題を解決するミックスインのような言語構造があります。これはAOPによく似ていますが、言語に統合されています。

SpringとCastle、および他のいくつかの依存性注入フレームワークには、注入するクラスに動作を追加するオプションがあります。これはランタイムウィービングの方法であり、これには多くの可能性があると思います。

AOPを使用するために、まったく新しいパラダイムを学ぶ必要はないと思います。アイデアは興味深いですが、既存のツールや言語に徐々に吸収されています。最新情報を入手して、これらのツールを試してください。



1

私はこの質問に答えるのが遅いですが、それは私のお気に入りのトピックの1つなので、私の見解を共有しましょう。

OOPは主にビジネスロジックを整理するために使用されますが、AOP は監査、ロギング、トランザクション管理、セキュリティなどの非機能的ものを整理するのに役立ちます

このようにして、ビジネスロジックをノンフィクションロジックと分離して、コードをよりクリーンにすることができます。

カワウソの利点は、インターフェースを実装せずに非常に一貫してアドバイス(例の監査)を適用できることです。これにより、ビジネスロジックに触れることなく、変更に優れた柔軟性を提供できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.