0

わかった。これが私の単純化されたシナリオです。多数のお客様のご注文に対応できる体制を整えております。スタッフ ユーザーはすべての注文を表示できるようにし、クライアント ユーザーは関連する注文のみを表示できるようにします。

特定のレコードを表示しようとするとき、OrderSecurity クラスで次の関数を使用します。

Public Function CanViewOrder(order)
    If currentUser.MemberOfStaff() Then
        CanViewOrder = True
    Else
        CanViewOrder = (order.ClientId = currentUser.ClientId)
    End If
End Function

注文のリストをユーザーに表示したい時点で、 OrderService クラスで定義された次の関数を使用できます

Public Function GetOrders()
    If currentUser.MemberOfStaff() Then
        GetOrders = GetAllOrders()
    Else
        GetOrders = GetAllOrdersForClient(currentUser.ClientId)
    End If
End Function

これは上記の場合は問題ありませんが、ルールが複雑になるにつれてうまく機能しません。たとえば、クライアントのサブセットからの注文のみを表示できる、信頼性の低いスタッフ メンバーを表す別のユーザー タイプを追加するとします。次に、CanViewOrder および GetOrders 関数 (および場合によってはデータ アクセス クラス) にロジックを追加する必要がありますが、これは私の考えでは DRY 原則に違反しています。

ですから、私の質問は次のとおりです。ここでトリックがありませんか?ビジネスロジックを組み合わせて、これらの機能の両方が使用できる 1 つの場所で注文を表示する許可を得る方法はありますか?

それとも、心配しすぎて、2 か所でロジックを実行する必要がありますか?

(この特定のアプリケーションでは、私は ASP Classic を使用しています - プレイヤーが嫌いではなく、ゲームが嫌いです - しかし、どの言語でもこの問題をどのように解決するかに興味があります)

4

2 に答える 2

1

アクセス ポリシーを集中して、主語 (ユーザー) と目的語 (順序) の両方を考慮してわずかに一般化したような述語に保持することで、(おそらく効率を犠牲にして) より一般的なものにすることができます。

Public Function CanView(user, order)
    (magic)
End Function

次に、一連の注文にGetOrders(user)適用するフィルターとして実装することで、アクセス ポリシーを繰り返さないようにします。CanView(user, order)

このルートをたどると、ポリシーやポリシーがどのように変化するかに関係なく、他の「クエリ」も一度だけ定義できます。例: GetUsersWhoCanView(order)CanViewSameOrders(user1, user2)CanAnybodyView(order)、...

少数の関数のみが依存する単純で比較的静的なポリシーの場合、十分に文書化された「直接的なアプローチ」が最も効率的で、頭を悩ませることが少なくなります。ポリシーが複雑になったり、頻繁に変更されたり、将来他の多くの機能で使用される可能性がある場合は、上で概説したモジュール式のアプローチを使用することで、技術的負債の発生を回避できます。

于 2009-10-27T14:00:55.740 に答える
1

IMO あなたはここで自分自身を繰り返していません。のビジネス ロジックはCanViewOrder、 のビジネス ロジックと同じではありませんGetOrders。表面的な類似点は確かにありますが、理論的には 2 つのルールは異なる形で進化する可能性があります。

于 2009-10-26T17:06:01.513 に答える