关于DDD的总结思考

2023-09-26  本文已影响0人  LHZ_123

建模方法

  1. 用例分析法
  2. 事件风暴法

建立领域模型

主要是要识别领域对象(domain object),领域对象之间的关系,以及领域对象的关键属性,必要的时候还要将领域对象组织成模块。

找到领域实体,描述实体规则,画出实体之间的关系

截屏2023-09-27 14.03.02.png

划分模块

很多实体和关联混杂在一起,形成了一个“蜘蛛网”。但人的认知能力是有限的,面对这样一张复杂的对象网络,就产生了认知过载(cognitive overload)。解决这一问题的方法就是“模块化”。也就是说,把模型中的业务概念组织成若干高内聚的模块(module),而模块之间尽量低耦合。

截屏2023-09-27 14.02.47.png

按领域模型设计数据库

截屏2023-09-27 14.44.59.png

分层架构设计

DDD分层架构.drawio.png

代码设计

推荐的分包原则

截屏2023-09-27 15.48.27.png

结构化分解

对于复杂的业务流程,可以使用结构化分解让代码有层次更清晰。


截屏2023-09-27 15.52.28.png 截屏2023-09-27 15.52.42.png 截屏2023-09-27 15.53.05.png

“表意接口”(Intention-Revealing Interfaces)模式

截屏2023-09-27 15.57.38.png

“领域服务”(Domain Service)模式

package chapter11.unjuanable.application.orgmng;
// imports...

@Service
public class OrgService {
    private final OrgValidator validator;  //代替了原来多个 Repository
    private final OrgRepository orgRepository;

    @Autowired
    public OrgService(OrgValidator validator
              , OrgRepository orgRepository) {
        // 为依赖注入赋值...
    }

    public OrgDto addOrg(OrgDto request,Long userId) {
        validator.validate(request); // 代替原来的 validate() 方法调用
        Org org = buildOrg(request, userId);
        org = orgRepository.save(org);
        return buildOrgDto(org);
    }

    private OrgDto buildOrgDto(Org org) {
       //将领域对象转成DTO...
    }

    private Org buildOrg(OrgDto request, Long userId) {
       //将DTO转成领域对象...
    }
package chapter12.unjuanable.application.orgmng;
// imports ...

@Service
public class OrgService {
    private final OrgBuilderFactory orgBuilderFactory;
    private final OrgRepository orgRepository;
    private final OrgHandler orgHandler;  //新增了一个领域服务依赖

    @Autowired
    public OrgService(OrgBuilderFactory orgBuilderFactory
            , OrgHandler orgHandler
            , OrgRepository orgRepository) {
        // 为依赖注入赋值 ...
    }

    @Transactional
    public OrgDto addOrg(OrgDto request,Long userId) {
        // 添加组织的功能已完成,这里省略 ...
    }

    //修改组织基本信息
    @Transactional
    public OrgDto updateOrgBasic(Long id, OrgDto request, Long userId) {
        Org org = orgRepository.findById(request.getTenant(), id)
                .orElseThrow(() -> {
                    throw new BusinessException("要修改的组织(id =" 
                                + id + "  )不存在!");
                });

        orgHandler.updateBasic(org, request.getName() 
                , request.getLeader(), userId);
                
        orgRepository.update(org);

        return buildOrgDto(org);
    }

    //取消组织
    @Transactional
    public Long cancelOrg(Long id, Long tenant, Long userId) {
        Org org = orgRepository.findById(tenant, id)
                .orElseThrow(() -> {
                    throw new BusinessException("要取消的组织(id =" 
                                + id + "  )不存在!");
                });

        orgHandler.cancel(org, userId);
        orgRepository.update(org);

        return org.getId();
    }

    private static OrgDto buildOrgDto(Org org) {
        // 将领域对象转换成DTO
    }
}

“工厂”(Factory)模式

DDD 认为,领域对象的创建逻辑也是领域层的一部分。如果创建领域对象的逻辑比较简单,可以直接用对象的构造器来实现。但是如果比较复杂,就应该把创建逻辑放到一个专门的机制里,来保证领域对象的简洁和聚焦。这里说的专门机制可以是一个方法或者一个类,可以有很多种实现方式。不论具体方式是什么,在 DDD 里统称为工厂(Factory)模式。

通常,领域对象的工厂放置在domain层,到时对象构建的入参基本上来自application层的参数。如何既保持层间依赖原则,又不新增中间对象,我们可以借助Builder模式来实现对象的构建。

package chapter11.unjuanable.domain.orgmng;
// import...

public class OrgBuilder {
    //用到的 validator
    private final CommonValidator commonValidator;
    private final OrgTypeValidator orgTypeValidator;
    private final SuperiorValidator superiorValidator;
    private final OrgNameValidator orgNameValidator;
    private final OrgLeaderValidator orgLeaderValidator;

    //用这些属性保存创建对象用到的参数
    private Long tenantId;
    private Long superiorId;
    private String orgTypeCode;
    private Long leaderId;
    private String name;
    private Long createdBy;

    public OrgBuilder(CommonValidator commonValidator
            , OrgTypeValidator orgTypeValidator
            , SuperiorValidator superiorValidator
            , OrgNameValidator orgNameValidator
            , OrgLeaderValidator orgLeaderValidator) {
        //注入各个 Validator... 
    }

    // 为builder 的 tenant 属性赋值,然后返回自己,以便实现链式调用
    public OrgBuilder tenantId(Long tenantId) {
        this.tenantId = tenantId;
        return this;
    }
    // 其他5个属性赋值与 tenantId 类似 ...
    
    public Org build() {
        validate();

        Org org = new Org();
        org.setOrgTypeCode(this.orgTypeCode);
        org.setLeaderId(this.leaderIc);
        org.setName(this.name);
        org.setSuperiorId(this.superiorId);
        org.setTenantId(this.tenantId);
        org.setCreatedBy(this.createdBy);
        org.setCreatedAt(LocalDateTime.now());

        return org;
    }

    private void validate() {
        commonValidator.tenantShouldValid(tenantId);
        orgTypeValidator.verify(tenantId, orgTypeCode);
        superiorValidator.verify(tenantId, superiorId, orgTypeCode);
        orgLeaderValidator.verify(tenantId, leaderId);
        orgNameValidator.verify(tenantId, name, superiorId);
    }
}

本文主要参考

钟敬老师的《手把手教你落地 DDD》
张建飞老师的《基于DDD的应用架构设计和实践》

上一篇下一篇

猜你喜欢

热点阅读