計算式はアスペクト指向プログラミングの代替アプローチですか?
これは、分野横断的な問題を管理するための F# のソリューションですか。
以下の記事を見て、AOP (アスペクト指向プログラミング) が頭に浮かびました。
この記事では、著者はロギングを処理する計算式の例を提供しましたが、ビジネス ロジックの主な意図をわかりにくくすることなく、コードの実際のロギングの側面を分離しました。
私の考えは正しいですか?
計算式はアスペクト指向プログラミングの代替アプローチですか?
これは、分野横断的な問題を管理するための F# のソリューションですか。
以下の記事を見て、AOP (アスペクト指向プログラミング) が頭に浮かびました。
この記事では、著者はロギングを処理する計算式の例を提供しましたが、ビジネス ロジックの主な意図をわかりにくくすることなく、コードの実際のロギングの側面を分離しました。
私の考えは正しいですか?
はい、モナドは分野横断的な関心事への優れた (そして慣用的な) アプローチです。モナドははるかに一般的な概念ですが、モナドを使用できる用途の 1 つは、システム内の効果をモデル化することです。
FP の専門用語では、効果という言葉はしばしば副作用を意味します。ロギング、監査、パフォーマンス監視、キャッシング、メータリングなどの多くの分野横断的な問題には、すべて (定義上) 副作用があります。これらはセカンダリ ステートフル リソースへのデータの「書き込み」を伴うため、 State または Writer モナドでモデル化できます。
認証、承認、検証などの他の分野横断的な問題は、多くの場合、Reader モナド (または、場合によっては State モナド) で対処できます。
F# の計算式は、Haskell の表記法と同じように、モナド コンビネータ (基本的にはreturnとbind ) に対して構文糖衣を提供します。ただし、Haskell とは対照的に、モナドの計算式ビルダーは、言語に既に組み込まれているいくつかのもの ( 、 )do
を除いて、自分で定義する必要があります。async
seq
横断的な問題に対処するためにモナドを使用することは、AOP とは異なるアプローチです。
オブジェクト指向プログラミングでは、AOP に対して 2 つの根本的に異なる見方があります。
私の本で説明しているように、コンパイル時のウィービングは、この問題に対処するための手間がかかり、柔軟性に欠ける方法であると考えています。デコレータを使用することは、同じ目標を達成するためのよりエレガントで柔軟な方法です。
この発言の動機は、懸念事項の分離に対する私の好みです。
OOP でコンパイル時のウィービングを使用すると、多くの場合、次のようなコードになります (C# の例)。
[Log]
public void SaveOrder(Order order)
{
// Implementation goes here...
}
ここでの問題は、懸念事項が分離されている一方で、まだ結合されていることです。再コンパイルしない限り、ログインしないことを決定することはできません。SaveOrder
計算式の使用は、次のようなものです。
log { return saveOrder order }
繰り返しになりますが、分野横断的な関心事は実装と共にコンパイルされます。
ただし、類似点は、モナド コンビネータを使用して懸念事項をまとめて作成できることです。これは、コンパイル時のウィービングでは簡単に実現できません。OOP では、ログに記録しないメソッドを簡単に取得することはできず、オブジェクトを一緒に構成すると「魔法のように」ログに記録されます。
一方、モナドを使用すると、純粋な関数を取り、それをモナドのコンテキストで構成できます。このような後でバインドされるロギングは、構造的に Decorators を使用することと同等です。
したがって、そのようなコードをアプリケーションのエントリ ポイント (そのComposition Root )に委ねる限り、分野横断的な問題に計算式を使用することが適切であると考えています。