跳到主要内容
版本:Next

领域模型设计

本文档引用的文件

目录​

  1. 引言
  2. 聚合根结构与行为
  3. 实体字段定义
  4. 审计能力继承
  5. 工厂方法与构造逻辑
  6. 业务规则验证逻辑
  7. 状态变更行为
  8. 规格模式应用
  9. 领域事件机制
  10. 事件处理响应
  11. 值对象与不变性约束
  12. 领域服务边界
  13. UML类图建议
  14. 状态转换图

引言​

本文档详细描述了MyEntityName作为领域驱动设计中的核心聚合根的完整领域模型。该模型体现了典型的DDD实践,包括聚合根、规格模式、领域事件、仓储接口等关键概念。通过分析其结构、行为和交互关系,帮助开发人员理解该领域的核心设计原则和实现方式。

聚合根结构与行为​

MyEntityName是领域模型中的核心聚合根,继承自FullAuditedAggregateRoot<Guid>,封装了业务逻辑、数据完整性和行为规则。作为聚合根,它负责维护内部一致性,并通过明确定义的方法暴露可变操作。

Section sources

实体字段定义​

MyEntityName聚合根包含以下核心字段,均通过受保护的set访问器确保只能通过领域方法进行修改:

  • Code: 编号,字符串类型,最大长度由MyEntityNameConsts.MaxCodeLength定义(默认64)
  • Name: 名称,字符串类型,最大长度由MyEntityNameConsts.MaxNameLength定义(默认64)
  • Sort: 排序,整数类型,用于排序展示
  • Remark: 备注,字符串类型,最大长度由MyEntityNameConsts.MaxRemarkLength定义(默认256)
  • IsDisabled: 是否禁用,可空布尔类型,表示实体状态

所有字段均使用virtual关键字,支持EF Core的延迟加载和代理功能。

Section sources

审计能力继承​

MyEntityName继承自FullAuditedAggregateRoot<Guid>,自动获得完整的审计能力,包括:

  • CreationTime: 创建时间
  • CreatorId: 创建者ID
  • LastModificationTime: 最后修改时间
  • LastModifierId: 最后修改者ID
  • IsDeleted: 是否已删除(软删除)
  • DeleterId: 删除者ID
  • DeletionTime: 删除时间

这些审计字段由框架自动管理,无需在业务代码中手动设置,确保了审计信息的一致性和可靠性。

Section sources

工厂方法与构造逻辑​

MyEntityName提供了两种构造方式:

  1. 受保护的无参构造函数:供ORM框架反序列化使用
  2. 公共有参构造函数:作为工厂方法创建新实例,接收id、code、name等必要参数,并执行基础验证

构造过程中通过Check.NotNullOrWhiteSpace和Check.Length等断言方法确保输入数据的有效性,体现了"不变性在构造时建立"的设计原则。

Section sources

业务规则验证逻辑​

业务规则验证贯穿于整个生命周期,主要体现在:

  • 构造时验证:确保code和name非空且长度合规
  • 更新时验证:在Update方法中重新验证code、name和remark
  • 应用服务层验证:MyEntityNameAppService在创建/更新前检查名称唯一性
  • 导入时验证:批量导入时检查行级数据完整性和名称重复

验证逻辑遵循"快速失败"原则,一旦发现违规立即抛出有意义的异常。

Section sources

状态变更行为​

MyEntityName支持以下状态变更操作:

  • Update: 更新code、name、remark和isDisabled字段
  • AdjustSort: 调整排序值,支持重新排序逻辑
  • Clone: 克隆实体,生成新ID并追加"_副本"后缀

这些方法均在聚合根内部实现,确保状态变更的原子性和一致性。特别是AdjustSort方法,支持复杂的排序调整逻辑,包括上移、下移和指定位置插入。

Section sources

规格模式应用​

MyEntityNameSpecification实现了规格模式(Specification Pattern),用于构建可复用的查询条件:

  • 用途:在仓储层封装复杂的查询逻辑,提高代码可读性和可测试性
  • 实现:继承自Volo.Abp.Specifications.Specification<T>,重写ToExpression方法
  • 参数化:支持通过name参数动态构建查询条件
  • 组合性:可通过And、Or等操作符组合多个规格

该规格在MyEntityNameAppService.GetListAsync中被实际使用,实现了按名称过滤的功能。

Diagram sources

Section sources

领域事件机制​

MyEntityName通过MyEntityNameEto(事件传输对象)发布领域事件:

  • 事件定义:MyEntityNameEto包含Name属性,用于传递事件上下文
  • 事件发布:虽然当前代码未显示发布逻辑,但架构已准备好通过IDistributedEventBus发布事件
  • 事件消费:支持分布式事件处理,确保跨服务的一致性

领域事件模式解耦了业务逻辑与副作用操作(如发送通知、更新索引等)。

Diagram sources

Section sources

事件处理响应​

MyEntityNameEventHandler实现了对MyEntityNameEto事件的响应:

  • 实现接口:实现IDistributedEventHandler<MyEntityNameEto>和ITransientDependency
  • 处理逻辑:当前为空实现(Task.CompletedTask),作为扩展点预留
  • 生命周期:瞬态依赖,每次事件触发都会创建新实例

该处理器可在分布式环境中响应来自其他服务的事件,实现跨边界上下文的集成。

Section sources

值对象与不变性约束​

本模型中未明确定义值对象,但体现了值对象的设计思想:

  • 不变性约束:通过常量类MyEntityNameConsts集中管理字段长度等约束
  • 克隆标记:MyEntityNameConsts.CloneTag定义了克隆时的后缀规则
  • 数据种子:MyEntityNameDataSeedContributor确保测试数据的一致性

这些设计共同维护了领域的不变性规则。

Section sources

领域服务边界​

领域服务边界清晰,遵循分层架构:

  • 领域层:MyEntityName、MyEntityNameSpecification、MyEntityNameEto
  • 仓储接口:IMyEntityNameRepository定义数据访问契约
  • 应用服务:MyEntityNameAppService编排领域对象,不包含核心业务规则
  • DTO层:MyEntityNameCreateDto、MyEntityNameUpdateDto用于数据传输

这种分层确保了领域模型的纯粹性,避免业务逻辑泄露到应用层。

Diagram sources

UML类图建议​

Diagram sources

状态转换图​

Diagram sources