行。所以这是我的简化方案。我们有一个处理许多客户订单的系统。我们希望员工用户能够查看所有订单,我们希望客户用户只能查看与他们相关的订单。
在尝试查看特定记录时,我们在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 - 不讨厌玩家,讨厌游戏 - 但我会对你如何用任何语言解决这个问题感兴趣)
答案 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)
,...
对于一个简单且相对静态的策略,只有少量功能依赖于它,“直接方法”,记录良好,为您提供最佳效率和最少头痛。如果您的政策可能变得复杂或可能经常更改,或者最终可能会被许多其他功能使用,那么使用我上面概述的模块化方法可以避免产生技术债务。