领域驱动设计系列(二):领域模型

前言

领域驱动设计里有很多东西,我们可以应用在各种各样的开发模式里,所以接下来说的一些东西,我们可以部分使用。

说道领域驱动的领域,大家肯定就要开始说Bounded Context,聚合,聚合根,容易让大家搞糊涂。 我觉得先抛开这些概念,后面再来说如何设计聚合,先简单来说。

模型

过去,我们在多层设计里定义了很多Model, 数据库的Model(DB Entity), 然后为了不依赖数据库,我们有设计了业务的Domain Model, 同时我们又设计了ViewModel, 这样一般也没什么问题,职责也很清晰。但是有几个问题

  1. 我们要做很多的模型转换,转入转出。当然我们可以用AutoMapper来但是AutoMapper的性能实在难以恭维,大家可以在网上搜索AutoMapper performance.
  2. 领域模型成了一个单纯的DTO了。

领域模型

首先我们要看领域,就是我们尽量把业务聚合到一个领域里,比如我们要做一个功能,可以看到用户每一次的登录日志,那个这个登录日志其实就是属于用户这个领域里。

其次我们看模型,原来我们的模型都是只有属性,也就是贫血模型,贫血的意思就是没有行为,像木乃伊一样,但是实际上领域是我们要完成业务的最主要的地方,我们希望领域能够自制,也就是领域自己管理自己。

示例

比如有一个Employee, 他的状态有Active, Pending, DeActive, 业务上是Pending只能改为Active.

```c#
 public class Employee : Entity
{
    public Name Name { get; set; }
   
    public EmployeeStatus EmployeeStatus { get; set; }

}
```

如果是贫血的Employee模型,我们往往代码如下

```c#
public class EmployeeService : IEmployeeService
{
    private readonly IUnitOfWorkFactory _unitOfWorkFactory;
    private readonly IEmployeeRepository _employeeRepository;

    public EmployeeService(IUnitOfWorkFactory unitOfWorkFactory, IEmployeeRepository employeeRepository)
    {
        _unitOfWorkFactory = unitOfWorkFactory;
        _employeeRepository = employeeRepository;
    }

    public void ChangeStatus(EmployeeStatus status, Guid employeeId)
    {
        using (var unitOfWork = _unitOfWorkFactory.GetCurrentUnitOfWork())
        {
            var employee = _employeeRepository.GetById(employeeId);
            employee.EmployeeStatus = status;

            unitOfWork.Commit();
        }
    }
}
```

但是上面的代码的问题就是领域没有自治,本来修改我的状态是我的事,你能不能修改,外面随意修改我的状态是很危险的,比如Pending状态只能改为Active状态。 所以如果不是贫血的模型,我们代码就会这样,让领域自己来管理

```c#
public class Employee : Entity
{

    public UserId UserId { get; private set; }
    public EmployeeStatus EmployeeStatus { get; private set; }


    public void ChangeStatus(EmployeeStatus status)
    {
        if (this.EmployeeStatus == EmployeeStatus.Pending && status != EmployeeStatus.Active)
        {
            throw new Exception("Only can Active when status is pending");
        }

        this.EmployeeStatus = status;
    }

}

public class EmployeeService : IEmployeeService
{
    private readonly IUnitOfWorkFactory _unitOfWorkFactory;
    private readonly IEmployeeRepository _employeeRepository;

    public EmployeeService(IUnitOfWorkFactory unitOfWorkFactory, IEmployeeRepository employeeRepository)
    {
        _unitOfWorkFactory = unitOfWorkFactory;
        _employeeRepository = employeeRepository;
    }

    public void ChangeStatus(EmployeeStatus status, Guid employeeId)
    {
        using (var unitOfWork = _unitOfWorkFactory.GetCurrentUnitOfWork())
        {
            var employee = _employeeRepository.GetById(employeeId);
            employee.ChangeStatus(status);

            unitOfWork.Commit();
        }
    }
}
```

因此可以看出,我们把业务代码尽量写在领域里让领域自治。

后记

其实领域驱动设计最难的就是设计领域(Domain), 也就是后面会说到的AggregateRoot 聚合,但是我想我们先让领域不再贫血,这样在传统的多层设计,数据驱动等架构都可以使用这种模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
领域驱动设计(Domain-Driven Design,简称DDD)是一种软件开发方法论,旨在解决复杂业务领域的软件开发问题。DDD强调将业务领域作为软件设计和开发的核心,通过深入理解业务领域的知识和规则,将其准确地映射到软件模型中。 在DDD中,将业务领域划分为多个领域模型,每个领域模型都包含了该领域的核心概念、业务规则和行为。通过使用领域模型,开发团队可以更好地理解业务需求,并将其转化为可执行的软件代码。 DDD提供了一系列的设计原则和模式,帮助开发团队构建高度可维护、可扩展和可测试的软件系统。其中一些重要的概念和技术包括: 1. 领域模型领域模型是对业务领域的抽象和建模,它包含了实体、值对象、聚合、领域服务等概念,用于描述业务领域的核心概念和关系。 2. 聚合聚合领域模型中的一个重要概念,它是一组相关对象的实体,负责维护整个聚合内部的一致性和业务规则。 3. 领域事件:领域事件是领域模型中发生的重要事实或状态变化,它可以被其他领域模型订阅和处理,用于实现领域间的解耦和协作。 4. 领域驱动设计的分层架构:DDD提倡使用分层架构来组织软件系统,将领域模型放在核心层,与应用层、基础设施层等进行交互。 5. 领域驱动设计的战术模式:DDD提供了一些战术模式,如聚合、工厂、仓储等,用于解决领域模型的复杂性和持久化等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值