なぜ「対」なのか?「対」ではありません。アスペクト指向プログラミングは関数型プログラミングと組み合わせて使用できますが、オブジェクト指向プログラミングと組み合わせて使用することもできます。それは「対」ではなく、「オブジェクト指向プログラミングによるアスペクト指向プログラミング」です。
私にとって、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を簡単に悪用して非常に多くの問題を引き起こす可能性がある場合、それをすべて使用することは悪い考えです。しかし、どのテクノロジーを悪用できないのでしょうか?データのカプセル化を悪用したり、継承を悪用したりすることができます。ほとんどすべての有用なプログラミング技術が悪用される可能性があります。悪用できない機能のみが含まれるように制限されたプログラミング言語について考えてみましょう。最初に使用することを意図されていた機能のみを使用できる言語。このような言語は非常に制限されているため、実際のプログラミングにも使用できるかどうかは議論の余地があります。