2009-10-26 16 views
0

OK. Alors, voici mon scénario simplifié. Nous avons un système qui gère les commandes pour un certain nombre de clients. Nous souhaitons que les utilisateurs du personnel puissent voir toutes les commandes et nous souhaitons que l'utilisateur client ne puisse voir que les commandes qui s'y rapportent.Comment empêcher la répétition de la logique métier?

Lorsque vous tentez d'afficher un enregistrement particulier, nous utilisons la fonction suivante dans notre classe OrderSecurity:

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

Aux points quand on veut afficher une liste des commandes à un utilisateur, nous pouvons la fonction suivante définie dans une classe OrderService

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

Ceci est OK pour ce qui précède mais ne tient pas bien car les règles deviennent plus compliquées. Supposons, par exemple, que nous ajoutions un autre type d'utilisateur qui représente un membre du personnel moins fiable qui ne peut voir que les commandes d'un sous-ensemble de clients. Nous devrons alors ajouter de la logique aux fonctions CanViewOrder et GetOrders (et potentiellement dans les classes d'accès aux données) qui dans mon esprit viole le principe DRY. Donc, ma question est la suivante: ai-je manqué une astuce ici - est-il possible de combiner la logique métier pour obtenir la permission de voir les commandes dans un endroit que ces deux fonctions peuvent utiliser? Ou est-ce que je m'inquiète trop et que je devrais aller de l'avant et avoir la logique à deux endroits?

(Dans cette application particulière, je suis en utilisant ASP classique - ne déteste pas le joueur, déteste le jeu - mais je serais intéressé par la façon dont vous résoudre ce problème dans toutes les langues)

Répondre

1

OMI vous ne pas vous répéter ici. La logique métier dans CanViewOrder n'est pas la même que la logique métier dans GetOrders. Il y a une ressemblance superficielle, c'est vrai, mais les deux règles pourraient théoriquement évoluer différemment.

1

Vous pouvez concentrer la politique d'accès et la rendre plus générale (probablement au détriment de l'efficacité) en la gardant dans un prédicat comme vous l'avez, légèrement généralisé pour prendre en compte à la fois le sujet et l'objet :

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

alors éviter de répéter votre politique d'accès en mettant en œuvre GetOrders(user) comme un filtre appliquant CanView(user, order) sur l'ensemble des commandes. Après avoir parcouru cette route, vous pouvez définir d'autres "requêtes", une fois pour toutes, indépendamment de la politique et de son évolution. Par exemple: GetUsersWhoCanView(order), CanViewSameOrders(user1, user2), CanAnybodyView(order) ...

Pour une politique simple et relativement statique avec seulement un petit nombre de fonctions se fondant sur elle, la « approche directe », bien documenté, vous offre une meilleure efficacité et moins mal de tête. Si votre politique pouvait devenir complexe ou pourrait changer souvent ou pourrait finir par être utilisée par de nombreuses autres fonctions à l'avenir, l'utilisation de l'approche modulaire que j'ai décrite ci-dessus évite de contracter des dettes techniques.