You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

从N层架构转向DDD:领域实体行为重构的困惑

老兄,你这个重构方向太对了——把领域实体从“贫血模型”改成拥有自身行为的“富模型”,代码的可读性和维护性都会提升一大截!我之前做过类似的迁移,给你唠点实际踩过的坑和落地经验:

重构领域实体的实践指南

一、先搞定实例获取的逻辑迁移

你提到的从 var customer = new CustomerLogic().GetCustomer(id); 改成 var customer = Customer.Get(id); 或者 var customer = new Customer(id);,这一步的核心是把数据获取的逻辑内聚到实体本身,但要注意两个关键点:

  • 如果用静态方法 Customer.Get(id),要处理好依赖的数据源(比如数据库上下文、仓储):可以通过依赖注入容器传递抽象仓储实例,或者用静态构造函数初始化(注意线程安全)。
  • 要是觉得静态方法不够灵活,也可以用实体工厂(比如 CustomerFactory.GetById(id)),但如果想完全让实体“自给自足”,静态方法是更直接的选择。

二、迁移业务逻辑的核心原则

把BL层的逻辑搬到实体里,一定要记住:实体只负责和自身状态强相关的业务,别啥都往里塞:

  • 跨实体的逻辑(比如同时操作Customer和Order的复杂业务)别硬塞到Customer里,这类逻辑应该放到专门的领域服务中。
  • 举个实际例子:原来的 CustomerLogic.UpdateCustomerEmail(id, newEmail),应该改成 customer.UpdateEmail(newEmail),而且校验邮箱格式、检查是否重复这类业务规则,直接写到 UpdateEmail 方法里,再也不用在外部服务里零散处理了。

三、避免持久化耦合的小技巧

当实体自己包含了获取逻辑,很容易和数据库这类持久化层耦合,这里给你个优雅的解决方案:

  • 引入仓储模式,让实体的 Get(id) 内部调用抽象仓储的方法,实体只依赖仓储接口,不直接碰数据库。比如:
public class Customer
{
    public int Id { get; private set; }
    public string Email { get; private set; }

    // 私有构造函数,强制通过Get方法创建实例,避免外部随意初始化
    private Customer() {}

    public static Customer Get(int id)
    {
        // 通过依赖注入获取仓储实例(这里可以用服务定位器或者构造注入,根据你的项目架构调整)
        var repository = ServiceLocator.Get<ICustomerRepository>();
        var customerDto = repository.GetById(id);
        
        // 把数据映射到实体
        var customer = new Customer();
        customer.Id = customerDto.Id;
        customer.Email = customerDto.Email;
        return customer;
    }

    public void UpdateEmail(string newEmail)
    {
        // 内置业务校验
        if (string.IsNullOrWhiteSpace(newEmail) || !newEmail.Contains("@"))
        {
            throw new InvalidOperationException("邮箱格式无效,请检查后重试");
        }
        // 还可以在这里添加更多业务规则,比如检查该邮箱是否已被其他用户占用
        Email = newEmail;
    }
}

四、逐步重构,别一口吃成胖子

千万别想着一次性把所有BL逻辑都迁到实体里,建议分步骤来:

  • 先迁移最独立的逻辑:比如单个实体的状态修改、简单校验规则。
  • 再处理数据获取类的逻辑,确保依赖关系梳理清楚,不会引入新的耦合。
  • 每迁移一部分就跑一遍测试,避免把旧bug带过来,也能及时发现新问题。

内容的提问来源于stack exchange,提问作者YanivHer

火山引擎 最新活动