entity-framework - 如何避免规则形式的业务逻辑贫乏的领域模型

标签 entity-framework domain-driven-design entity business-logic anemic-domain-model

我正在设计一个具有简单 Entity Framework 支持的域对象的系统,该对象具有我需要根据一系列规则更新的字段 - 我想逐步实现这些规则(以敏捷的方式)并且当我使用 EF 时我持怀疑态度关于将每个规则放入域对象中。但是,我想避免编写“程序代码”和使用贫血的域模型。这一切都需要可测试。

例如,对象是:

class Employee { 
 private string Name; 
 private float Salary; 
 private float PensionPot;
 private bool _pension;
 private bool _eligibleForPension;

}

我需要建立一些规则,例如“如果 Salary 高于 100,000 并且 _eligibleForPension 为 false,则将 _eligibleForPension 设置为 true”和“如果 _pension 为 true,则将 _eligibleForPension 设置为 true”。

大约有 20 条这样的规则,我正在寻找是否应该在 Employee 类或类似 EmployeeRules 类中实现它们的建议?我的第一个想法是为从“Rule”继承的每个规则创建一个单独的类,然后将每个规则应用于 Employee 类,可能使用访问者模式,但我必须将所有字段暴露给规则才能做到这一点感觉不对。虽然在 Employee 类上设置每条规则也感觉不太正确。这将如何实现?

第二个问题是实际的员工是支持数据库的 Entity Framework 实体,所以我不乐意为这些“实体”添加逻辑 - 特别是当我需要模拟对象以对每个规则进行单元测试时。如果他们有我在同一个对象上测试的规则,我怎么能 mock 他们?

我一直在考虑在应用规则之前使用 AutoMapper 转换为更简单的域对象,但随后需要自己管理对字段的更新。对此也有什么建议吗?

最佳答案

一种方法是使规则成为Employee 的内部类。 .这种方法的好处是字段可以保持私有(private)。此外,规则的调用可以由 Employee 类本身强制执行,确保它们总是在需要时被调用:

class Employee
{
    string id;
    string name;
    float salary;
    float pensionPot;
    bool pension;
    bool eligibleForPension;

    public void ChangeSalary(float salary)
    {
        this.salary = salary;
        ApplyRules();
    }

    public void MakeEligibleForPension()
    {
        this.eligibleForPension = true;
        ApplyRules(); // may or may not be needed
    }

    void ApplyRules()
    {
        rules.ForEach(rule => rule.Apply(this));
    }

    readonly static List<IEmployeeRule> rules;

    static Employee()
    {
        rules = new List<IEmployeeRule>
        {
            new SalaryBasedPensionEligibilityRule()
        };
    }

    interface IEmployeeRule
    {
        void Apply(Employee employee);
    }

    class SalaryBasedPensionEligibilityRule : IEmployeeRule
    {
        public void Apply(Employee employee)
        {
            if (employee.salary > 100000 && !employee.eligibleForPension)
            {
                employee.MakeEligibleForPension();
            }
        }
    }
}

这里的一个问题是 Employee 类必须包含所有的规则实现。这不是一个主要问题,因为这些规则体现了与员工养老金相关的业务逻辑,因此它们确实属于同一类。

关于entity-framework - 如何避免规则形式的业务逻辑贫乏的领域模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15646184/

相关文章:

c# - 不允许使用源类型 'dynamic' 或具有类型 'dynamic' 的连接序列的查询表达式

rest - 为什么 REST 动词不一定对应于 CRUD 操作?

symfony - 在表单字段类型 'entity' 添加自定义选项

java - JPA 实体和关系 OneToMany、ManyToOne、ManyToMany - 良好实践

linq - Entity Framework 和链接表问题

asp.net-mvc-3 - 具有服务层的 asp.net mvc 存储库模式,何时混合存储库中的实体?

c# - 通用存储库在上下文之间拆分 LINQ 表达式

c# - 如何避免领域模型中的持久化逻辑?

c# - 具有 MediatR 的 CQRS 和命令的可重用性

ios - Swift 3 - 核心数据 - 获取结果 Controller 访问关系属性