老赵
发布于 2025-09-23 / 12 阅读
0
0

用Nest实现DDD

Nest框架是什么?

Nest 框架是一个帮助开发人员快速实现基于领域驱动设计的技术框架。在 Nest 中定义了领域驱动设计的基本概念,包括聚合根、实体、值对、领域服务、应用服务、服务事件、仓储等,使用 Nest 可以帮助你全面执行你在领域模型建模中的面向对象思维。有效指导开发人员按模型编写代码,为代码检查等提供必要的依据。

实现领域驱动设计的过程主要有三个部分,分别是战略设计、战术设计、与技术架构。

战略设计划分了域/子域,制定了限界上下文,并明确了上下文映射图。战略设计对应到系统开发过程便是服务/微服务的划分。

战术设计定义了某一个限界上下文内,如何通过领域模型来处理该域内的问题空间,所以领域建模的过程但是该空间内解决方案的制定过程。

技术架构定义了与业务无关但需要由技术去解决的一些特定问题,比如面向服务的设计、事件驱动设计、分层架构设计、CQRS设计等。

为什么要使用Nest

Nest以DDD的思想为基础,实现并封装了常用的技术架构设计,让设计师更加关注于业务设计、让开发人员更加关注于业务实现。

Nest还为我们规范了领域模型的表示方式、系统的整体异常处理过程、单元测试方法、应用生命周期管理、缓存管理、事件管理、仓储实现、查询处理等。

Nest的使用将大大简化了DDD技术开发。在之后的文章中,我们将深度剖析Nest框架。

Nest能做什么

定义或标识DDD中的基本概念

领域驱动设计思想提供了一整套工具,如聚合根、实体、值对象、实体标识、领域服务、应用服务、领域事件、仓储、限界上下文等。

序号

DDD概念

Nest的实现方式

描述

1

限界上下文

NestContext

用来表示一个解决方案空间,一个子域表示一个问题空间,对应可能会有一个或多个解决方案空间,可用于指导微服务划分

2

应用服务

@AppService或ApplicationService接口

描述该限界上下文内能提供的具体功能,这些功能将通过适配器开放给用户接口、三方系统、或定时任务执行的相关能力

3

领域服务

DomainService或常规的Java服务类

不适合放在某一个聚合行为来实现的,需要协调多个聚合或实体来完成的无状态行为

4

聚合根

AggregateRoot

由多个具有紧密逻辑关系的实体组成的一个整体称为一个聚合,聚合根则是这个聚合的根实体

5

实体

Entity

具有唯一的标识、关注其生命周期过程的名词概念

6

值对象

ValueObject

没有唯一标识,而是整体值比较的名词概念,常依符于实体,表示实体的某一个复杂属性

7

实体标识

Identifier

唯一标识一个实体的标识,标识其本身是一个值对象

8

领域事件处理器

EventHandler或@EventListener

用于处理领域事件的类或方法

9

事件总线

EventBus

用于发送领域事件的工具

10

仓储

Repository

以实体为单元的持久化工具

管理生命周期

类型

阶段

上下文

BEFORE_STARTUP

上下文启动前

AFTER_STARTUP

上下文启动成功

BEFORE_SHUTDOWN

上下文停止前

AFTER_SHUTDOWN

停止成功后

应用服务

Inited

初始化完成

beforCommit

提交前

repositoryCommitted

完成仓储提交

mqCommitted

完成事件提交

repositoryCommitFailure

仓储提交失败

eventCommitFailure

事件提交失败

OnProcessingException

处理时发生异常

实体

created

实体被创建

loaded

实体被加载

preCommit

实体提交前

changed

实体已变化

基于命令模式的开发风格

基于事件驱动的开发风格

管理缓存项

  • 允许将缓存分组,按组配置缓存的策略,如过期时间,启用状态,缓存方式等。

  • 可以按组清理缓存项

  • 可以通过CacheBus工具或@CacheUpdate(Spring环境)、@CacheRemove(Spring环境)更新、移除缓存。

  • 可以通过CacheProvider自定义扩展缓存的提供者。

管理事件项

  • 可以通过EventChannelProvider自定义扩展消息通道

  • 可以通过EventBus发送事件、注册EventHandler或@EventListener(Spring环境)

  • 可以通过EventItem管理事件策略,如使用什么消息通道

管理排它锁

  • 定义锁类型

  • 通过LockProvider实现自定义锁

规范异常处理

  • 使用CustomException或CustomExceptionable来定义业务异常

  • 使用SystemException或SystemExceptionable来定义系统异常

  • 规范异常的使用:

    • 业务异常,触发Warn级别的日志

    • 系统异常,触发Error级别的日志

  • 异常不要被catch,即使catch后,也要重新抛出,除非该异常可以被忽略,被处理后的异常需要写Warn级别日志

  • 统一在最外层(适配器层)处理异常,比如webmvc适配器,使用ExceptionHandler统一处理

日志处理

  • 将日志输出到标准流中,不单独配置日志文件,以减少io

  • 由日志收集工具直接从标准流中读取内容采集到日志系统中

  • 处理了忽略的异常时,需要主动写入warn级别的日志

  • 调试信息使用debug级别

  • 运行信息使用info级别

  • error级别为系统自动写入,不要人工写入error级别的日志


评论