领域模型设计
本文档引用的文件
- MyEntityName.cs
- MyEntityNameSpecification.cs
- MyEntityNameEto.cs
- MyEntityNameEventHandler.cs
- IMyEntityNameRepository.cs
- MyEntityNameConsts.cs
- MyEntityNameAppService.cs
- MyEntityNameCreateDto.cs
- MyEntityNameUpdateDto.cs
- MyEntityNameDataSeedContributor.cs
目录
- 引言
- 聚合根结构与行为
- 实体字段定义
- 审计能力继承
- 工厂方法与构造逻辑
- 业务规则验证逻辑
- 状态变更行为
- 规格模式应用
- 领域事件机制
- 事件处理响应
- 值对象与不变性约束
- 领域服务边界
- UML类图建议
- 状态转换图
引言
本文档详细描述了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提供了两种构造方式:
- 受保护的无参构造函数:供ORM框架反序列化使用
- 公共有参构造函数:作为工厂方法创建新实例,接收
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