特定の問題はAOPでよりエレガントに解決されますか?


19

私はアスペクト指向プログラミングのアイデアに出会いましたが、それに懸念があります。

基本的な考え方は、オブジェクトを使用して十分にモジュール化されていない横断的な懸念を取り、それらをモジュール化することです。それはすべて非常に素晴らしいです。

しかし、AOPの実装は、モジュールの外部からコードを変更することのようです。そのため、たとえば、特定のオブジェクトが関数のパラメーターとして渡されたときに何が起こるかを変更するアスペクトを作成できます。これはモジュールの考え方に直接反するようです。そのモジュールの外部からモジュールの動作を変更することはできません。そうしないと、モジュールのポイント全体が覆されます。しかし、アスペクトはまさにそれをしているようです!

基本的に、アスペクトはコードパッチの一種のようです。簡単なハックに役立つ場合があります。しかし、一般的な原則として、おそらくあなたがやりたいことではありません。アスペクト指向プログラミングは、私が悪い習慣をとっており、一般的な設計原則に引き上げているように思えます。

AOPは良い習慣ですか?特定のプログラミングの問題はAOPでよりエレガントに解決されますか?


ああ、有名な猿パッチ!
ムアディブ

1
質問を編集してトーンを改善し、再開することに投票しました。
ロバートハーベイ

Questioまた、ここでは異なる形で再頼まれました:programmers.stackexchange.com/questions/19344/...
ピーター・ボートン

回答:


19

アスペクト指向プログラミングを使用すると、ソフトウェアの主要な機能に関係のないコードをアプリケーションまたはライブラリ全体に不必要に分散させることなく、実行が困難な特定の種類のプログラミングを実行できます(横断的関心事)。例は次のとおりです。

  1. ロギングとモニタリング
  2. パフォーマンス分析
  3. デバッグとトレース
  4. 元に戻す機能
  5. 入力と出力の検証
  6. 既存のオブジェクトの動作をモーフィングする
  7. オブジェクトフィルター
  8. セキュリティ実装
  9. トランザクションの管理

このような横断的関心事をアプリケーションの単一の部分に限定し、属性、メソッド呼び出しインターセプト、または動的プロキシを介してこれらの機能をコードで参照することで、横断的行動のカプセル化を許可します。これには、カプセル化がアプリケーションの他の場所に提供するすべての利点(つまり、単一の変更ポイント)があります。

ここで重要な点は、AOPが1)アプリケーション全体で共通の動作、2)アプリケーションの主要機能の周辺機器である動作をカプセル化することです。


7

ゲームの後半に来ますが、この質問に出くわすかもしれない後の開発者にこれを提供します。

アプリケーションが正しく動作するためにアプリケーションに依存している場合、AOPに強くお勧めします。アスペクトは次のように機能します。

  • アドバイス(追加の動作)が適用されます
  • 結合ポイント(メソッドの開始や終了など、追加のコードを付加できる場所、または特定のイベントがトリガーされるとき)
  • ... ポイントカット(特定の結合ポイントが一致するかどうかを検出するパターン)パターンが一致する場所

長い間コンピューターを使用している人にとって、パターンが使用されているという事実は、注意深く見るべきものかもしれません。ここsetで、引数に関係なく指定されたメソッドに一致するポイントカットの例を示します。

call(* set(..))

したがって、これはかなり抜本的なポイントカットであり、多くのことにアドバイスを適用しているので、これを慎重に扱うことが推奨されることは明らかです(しゃれは意図していません)。

または、名前や署名に関係なく、すべてにアドバイスを適用しましょう!

execution(* *(..))

したがって、明らかにここには多くの力があるので注意する必要がありますが、これはアスペクトに対する議論ではありません。 aopのバグをお楽しみください)。

比較的安全なポイントカットのように見えるものは次のとおりです。

pointcut setter(): target(Point) &&
                   ( call(void setX(int)) ||
                     call(void setY(int)) );

名前付きsetXまたはオブジェクトsetY上のメソッドPointが見つかった場合、明示的にアドバイスを提供します。メソッドはを受け取ることができるだけであり、を受け取るint必要がありますvoid。かなり安全そうですね。これらのメソッドが存在し、正しいアドバイスを適用した場合、それは安全です。そうでない場合、あまりにも悪い。静かに失敗します。

例を挙げると、友人がJavaアプリケーションをデバッグしようとしていたときに、誰もが不正確なデータを返すことがありました。これはまれな障害であり、特定のイベントや特定のデータと相関しているようには見えませんでした。これはスレッド化バグであり、テストや検出が難しいことで有名です。結局のところ、メソッドをロックして「スレッドセーフ」にするためにアスペクトを使用していましたが、プログラマがメソッドの名前を変更し、ポイントカットが一致しなかったため、アプリケーションのサイレントブレークが発生しました。

したがって、AOPを使用して例外のような側面を処理する必要がある場合、適切に設計されたシステムで何も問題がなければ、それらを削除してもソフトウェアは正しく機能することを人々に伝えます。ただし、プログラムの機能がAOPに依存する場合、プログラムに脆弱性が導入されますが、これは保証されません。

したがって、ロギング、デバッグ、およびトレースは、側面に最適な動作の優れた例ですが、セキュリティはどうですか?いや。スレッドセーフ?いや。

AOPの堅牢な代替手段については、traitsを参照してください。言語にボルトで固定されるのではなく、直接言語に統合され、「特性認識」IDEを必要とせず(助けにはなりますが)、必要なメソッドが存在しない場合はコンパイル時に失敗します。特性は、問題が最初から明確に定義されていたため、関心の分離を処理する非常にクリーンな仕事をします。私はそれらを広範囲に使用し、それらは素晴らしいです。


AOPはコア機能に使用すべきではないと主張するよりも、メソッド名に依存するポイントカットは悪い考えだと言う方が適切かもしれません。私はおそらく、ロックと同期もAOPの良いユースケースではないと主張するでしょう。
コードブリン

2

AOPが唯一の適切で実用的なソリューションである状況の1つは、ソースコードにアクセスできない場合です。ロギングの横断的関心事の疲れた古い例を使用するには:

消費するサードパーティのライブラリに制御フローを記録するとします。ロギングステートメントで完全に計測された独自のコードがあります。ただし、このライブラリにはソースがないため、ロギングステートメントを追加できません。あなたがいるのでやるバイトコードを持って、AOPは、あなたは、サードパーティのライブラリとにかくことを機器にできます。

とにかくロギングアスペクトを作成する場合は、独自のコード全体でAOPを使用してロギングを実装することも検討してください。


ロギングは、「興味深い」ことを目的としています。AOPロギングで「これらのパラメーターで入力」および「終了」以外のことを行うにはどうすればよいですか?

@Thorbjorn:ロギング/デバッグ/トレースは、AOPが役立つ機能の多くの領域の1つにすぎません。私のポイントを説明するために例として使用しました。私がやろうとしているのは、AOPによってサードパーティのバイトコードをより詳細に制御できるということです。
ジョセフタネンバウム

確かに、AOPロギングが単なる入退室ロギング以上のことができるかどうかを知りたいと思いましたか?

使用するAOPツールに依存しますが、できることには確かに制限があります。入退室ロギングを超えることは非常に不可能かもしれません。
ジョセフタネンバウム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.