【问题标题】:Putting business logic into extension methods将业务逻辑放入扩展方法中
【发布时间】:2017-03-22 11:33:13
【问题描述】:

有一个第三方类型Person。它只是公开了Subscriptions 集合,这是一个人订阅的邮件列表:

public class Person
{
    public Person(int id)
    public IList<int> Subscriptions {get;set;}
}

(是mutable,没有任何验证,大家可以清理,但那是第三方API)。

我需要放置某种订阅业务逻辑并寻找合适的位置来执行此操作(订阅可能有一些验证规则,它们可能会根据某些条件自动添加或删除等)。我可以在这里看到两个选项:

选项 1:
这可能是我的解决方案中的一个新的Recipient 类型,所有业务逻辑都封装在SubscribeUnsubscribe 方法中:

public class Recipient
{
    public Recipient(Person person) { ... }
    public void SubscribeTo(int mailingListId) { ... }
    public void UnsubscribeFrom(int mailingListId) { ... }
}

选项 2:
一样的东西,但是变成了PersonExtensions类:

public static class PersonExtensions
{
    public static void SubscribeTo(this Person person, int mailingListId) { ... }
    public static void UnsubscribeFrom(this Person person, int mailingListId) { ... }
}

静态扩展方法可能会阻止我创建大量 Recepient 实例,但看起来不适合放置 BL。这样做有什么缺点吗?

【问题讨论】:

    标签: c# domain-driven-design extension-methods


    【解决方案1】:

    在我看来,您绝对应该更喜欢选项 1。扩展方法不是用来处理业务逻辑的;这应该总是发生在课堂上。我认为通过将Person 类的关注点与Recipient 的关注点分开,你是正确的。如果您正在考虑使用SOLID design principles,那么您肯定选择了选项 1。

    S单一责任,IE 一个类应该只有一个责任(一个“改变的理由”)。与您关于使用扩展方法代替类的问题没有密切关系,但它通过将人和接收者分开来证明您走在正确的轨道上。如果您的收件人逻辑发生变化,您不必修改每段使用人员但不关心收件人逻辑的代码。

    Open/closed -- 为扩展打开,为修改关闭。 (不要让“扩展”这个词让你想到扩展方法。)你应该总是能够添加你的(最好是抽象的)父类的扩展(子类)。像多态这样的面向对象编程的基本原则在这里发挥了作用,如果选项 2 可能,则没有。

    Liskov 替换与开放/封闭原则完美契合,因为它允许您将代码中需要父类实例的类替换为新的“扩展”子类的实例-类。

    如果您将所有逻辑都放在一个带有扩展方法的静态类中,这一切都不可能实现。

    【讨论】:

    • 这也是我的看法,我只是没有找到一个好的来源来描述它。能否请您解释一下 SOLID 是如何坚持这一点的?
    • 添加可测试性
    • 如果我需要处理大数据(1M+),是否可以作为支持静态扩展方法的论据?
    【解决方案2】:

    我不同意所选答案。 业务规则经常更改,并将它们添加到域实体中,将易失逻辑与可能几乎不可变的对象紧密耦合。如果明天您需要添加更多规则或由于业务条件的变化而更改它们会发生什么?或者,如果相同的规则适用于不同的地理区域怎么办?您将需要一次又一次地干预您的对象,添加或删除方法并提供增加的复杂性和冗长性。这是当今大多数行业很可能出现的情况。此外,这些方法很可能是公开的。因此,除非您围绕它们构建复杂的应用程序逻辑,否则任何人都可能以错误的方式使用它们。

    解决方案是将业务规则与域对象分离,委托第三个对象负责决定如何组合它们以及如何(以及何时)应用它们。这就是业务规则引擎发挥作用的地方。它们允许您创建封装任何域实体的业务规则的类,将它们添加到规则存储库并根据需要触发它们(因此您确实必须知道自己在做什么)。另一个优势是您可以让您的域实体保持轻量和简单,避免业务逻辑的冗长和复杂。

    更高级的引擎使用复杂的算法(例如 rete one),能够自己(大多数时候)找出应用规则的确切顺序,并支持依赖注入。我个人使用 NRules:它是一个开源的、企业级的规则引擎,快速可靠,建立在 rete 算法之上。

    https://github.com/NRules/NRules

    试一试,让我知道;)

    【讨论】:

      猜你喜欢
      • 2020-02-16
      • 2013-11-29
      • 2013-01-12
      • 2019-06-21
      • 2011-01-30
      • 2021-10-04
      • 1970-01-01
      • 2018-07-30
      • 1970-01-01
      相关资源
      最近更新 更多