回答:
可能であれば、横断的な関心事を個別のモジュールにカプセル化し、依存関係の注入によってアプリ全体で使用できます。これにより、横断的な関心事の実装を、コード全体での使用からある程度切り離すことができます。
ただし、これは常にエレガントに機能するとは限りません。それが人々がAOPのようなもので問題に対処しようとしている理由です。
私がまだ見たことがない他の2つのオプション:
モナドと矢印を使用した関数型プログラミング
FPでは、他の何かと同様に横断的な関心事を表します。つまり、関数呼び出しで渡すものです。それを明示的に行うのは面倒なので、モナド(または矢印)を使用して、渡される余分な情報を隠すことができます。
最も一般的なAOPの例はロギングです。モナドでは、メッセージのリストを保持する「ロガー」モナドを作成します。LoggerMonadを使用して実行する機能には、ログメッセージを投稿する機能があります。Arrowsを使用すると、アプリケーションのデータフロー全体をモデル化し、必要に応じてログルーチンをモデルに組み込みます。おもう。矢印はかなり複雑です。
エンティティ/コンポーネントベースのプログラミング
ゲームエンジンのために私が研究し、実験してきたこと。OOPのような「オブジェクト」の代わりに、すべてをデータのパケット(コンポーネント)とコンポーネントのタイプで動作するサービスに分解します。コンポーネントは、リレーショナルデータベースのように、共通のIDによってグループ化され、リンクされたコンポーネントのグループはエンティティです。そのようなシステムにロギングを追加するには、どのコンポーネントがシステムを通過するかに基づいてトリガーする新しいロギングサービスを追加します。
どちらの方法でも、非常に簡単に横断的な変更を簡単に行うことができますが、どちらも高レベルのアーキテクチャモデルです。したがって、おそらく最初から使用する必要があります。コンポーネントモデルは、理論的には既存のOOPシステムに組み込むことができます。あなたの言語が十分に強力であれば、モナドも同様だと思います。
横断的関心事の問題に取り組む方法はいくつかあります。
より優れたデザインパターン、イディオム、または抽象化メカニズムを使用する:コードはモジュール化できますが、横断的である場合があります。コードを維持するには、モジュール化できる設計手法を使用するようにリファクタリングする必要があります。そのようなリファクタリングは、異なる種類の横断的切断を導入する可能性がありますが、うまくいけば、横断的カットは安定しており、変更される可能性は低いです。
より豊富な言語機能の開発:横断的な表現の多くは、より優れた抽象化メカニズムを介して解決でき、場合によっては新しい言語機能が必要になります。たとえば、機能的およびオブジェクト指向の機能を含むより高度な言語では、多くの場合、必要ではないため多くの設計パターンを採用していません。設計パターン自体は、いくつかの異なるオブジェクトとクラスの役割を記述するため、本質的に横断的であることに注意してください。Javaでは、ランタイムのコストは高くなりますが、多くの場合、アスペクトの代わりにリフレクションを使用できます。たとえば、リフレクションを使用すると、わずか数行のコードで何百ものクラスでビジターパターンをサポートできます。DJライブラリNortheasternからは、まさにそれを行う反射ソリューションの1つです。ミックスインはC ++で利用可能な強力なテクニックであり(Javaではありません)、アスペクトと同じユースケースのいくつかを提供できます。
より優れたツールサポートの提供:grep
リファクタリング操作の使用や実行などの手法は、コードのクロスカットに関連する問題に対処できます。たとえば、インターフェイスで宣言されたメソッドの名前は、プログラムを横断する可能性があります。(ここでの技術的な違いに注意してください。クロスカットするのはメソッドの実装ではなくメソッドの名前です。)これは通常、EclipseのようなIDEでは問題ではありません。名前を使用するコード内の場所。このように、プログラミング環境があなたにとって十分に表現力がある場合、言語機能を必要としないことは可能です。
ドメイン固有の言語を使用する:AspectJの前に登場した初期のアスペクト言語は、ドメイン固有であり、関数の構成を効率的に組み合わせるためのスレッド同期やデータフロー分析などの特定の問題にのみ適用されました。これらの言語は実験的でしたが、それ以外の場合は横断的だった懸念をモジュール化するのに非常に成功したようです。
ジェネレーティブプログラミングテクニックを使用する:メタレベルにステップアップすることは、アスペクト指向プログラミングの実装テクニックと見なされる場合がありますが、単純なアスペクトを超えるほど十分に大きな領域です。生成手法(プログラムが別のプログラムのソースコードを生成する場合)も、ドメイン固有の言語に関連しています。
これらすべてについて、AOPの学習が適切だと思います。AOPは、AOP言語を使用しなくても、コードの概念を拡張するのに役立ちます。
一般に、宣言的な機能でコード要素にタグを付けますが、具体的にはC#/。NET / Monoの世界の属性システムにタグを付けます。
私はAOPの専門家ではありませんが、長年にわたってそれについて読んだことから、Lisp、特にメタオブジェクトプロトコルのような部分が提供するメタプログラミングのより弱い形式のように常に見えてきました。
これは驚くことではないでしょう、グレゴール・キザレスはAMOPの作者の一人で、後にJava向けのAspectJを書きました!