如何防止重复业务逻辑?

时间:2009-10-26 14:29:39

标签: security permissions dry business-logic

行。所以这是我的简化方案。我们有一个处理许多客户订单的系统。我们希望员工用户能够查看所有订单,我们希望客户用户只能查看与他们相关的订单。

在尝试查看特定记录时,我们在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原则。

所以,我的问题是:我在这里错过了一个技巧 - 是否有某种方法可以将业务逻辑组合在一起查看订单的权限,这两个函数都可以使用?

或者我担心太多,应该继续并在两个地方拥有逻辑?

(在这个特殊的应用程序中我使用ASP Classic - 不讨厌玩家,讨厌游戏 - 但我会对你如何用任何语言解决这个问题感兴趣)

2 个答案:

答案 0 :(得分:1)

IMO你不是在这里重复自己。 CanViewOrder中的业务逻辑与GetOrders中的业务逻辑不同。有一种肤浅的相似之处,这是事实,但这两条规则在理论上可以有不同的演变。

答案 1 :(得分:1)

您可以集中访问策略并使其更加通用(可能以牺牲效率为代价)将其保留在您所拥有的谓词中,稍微概括一下以考虑主题(用户)和对象(顺序):

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

然后执行GetOrders(user)作为在订单集上应用CanView(user, order)的过滤器,避免重复您的访问政策。

走了这条路线,您也可以一劳永逸地定义其他“查询”,其方式与政策无关,也可能如何变化。例如:GetUsersWhoCanView(order)CanViewSameOrders(user1, user2)CanAnybodyView(order),...

对于一个简单且相对静态的策略,只有少量功能依赖于它,“直接方法”,记录良好,为您提供最佳效率和最少头痛。如果您的政策可能变得复杂或可能经常更改,或者最终可能会被许多其他功能使用,那么使用我上面概述的模块化方法可以避免产生技术债务。