【问题标题】:How do I prevent the repetition of business logic?如何防止业务逻辑的重复?
【发布时间】:2009-10-26 14:29:38
【问题描述】:

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

在尝试查看特定记录时,我们在 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 - 不要讨厌播放器,讨厌游戏 - 但我很想知道你如何用任何语言解决这个问题)

【问题讨论】:

    标签: security permissions dry business-logic


    【解决方案1】:

    IMO,您不会在这里重复自己。 CanViewOrder 中的业务逻辑与GetOrders 中的业务逻辑不同。确实有表面上的相似之处,但从理论上讲,这两条规则可能会有所不同。

    【讨论】:

      【解决方案2】:

      您可以集中访问策略并使其更通用(可能以牺牲效率为代价),方法是像您一样将其保留在谓词中,只是稍微概括一下以同时考虑主题(用户)和对象(顺序):

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

      然后通过实施GetOrders(user) 作为过滤器来避免重复您的访问策略,并在订单集上应用CanView(user, order)。

      走这条路后,您也可以一劳永逸地定义其他“查询”,其方式独立于政策及其可能发生的变化。例如:GetUsersWhoCanView(order)、CanViewSameOrders(user1, user2)、CanAnybodyView(order)、...

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

      【讨论】:

        猜你喜欢
        • 2012-03-01
        • 1970-01-01
        • 2017-09-01
        • 2016-07-12
        • 2015-02-12
        • 1970-01-01
        • 2017-03-24
        • 2010-12-09
        • 1970-01-01
        相关资源
        最近更新 更多