DDD架构下多实体共享业务逻辑与事件类的存放位置咨询
共享业务逻辑的DDD目录组织方案
针对你提到的跨实体共享的隐藏标记逻辑,这里有几种符合DDD实践的目录组织方式,可根据项目规模和复杂度选择:
1. 领域服务模式
把共享的动作处理器MarkItemAsHidden、事件MarkedItemAsHidden放在Domain目录下的对应子目录,投影器HidingProjector单独归类:
- 目录结构示例:
Domain/ ├── Entities/ │ ├── Product.php │ ├── Category.php │ └── Cart.php ├── Services/ │ └── MarkItemAsHidden.php ├── Events/ │ └── MarkedItemAsHidden.php └── Projections/ └── HidingProjector.php - 逻辑说明:领域服务负责封装跨实体的通用业务行为,
MarkItemAsHidden作为领域服务,可通过定义Hideable接口约束传入的实体(要求Product、Category等实现该接口,确保具备统一的状态变更能力),触发对应的领域事件。事件作为领域层核心元素,单独存放便于统一管理;投影器属于领域层的投影逻辑,和同类型组件归类存放。
2. 通用领域模块模式
如果未来会有更多跨实体的通用业务逻辑,可在Domain下创建Shared子模块,专门存放这类共享组件:
- 目录结构示例:
Domain/ ├── Entities/ │ ├── Product.php │ ├── Category.php │ └── Cart.php └── Shared/ ├── Services/ │ └── MarkItemAsHidden.php ├── Events/ │ └── MarkedItemAsHidden.php ├── Projections/ │ └── HidingProjector.php └── Interfaces/ └── Hideable.php - 逻辑说明:Shared模块用来隔离通用领域逻辑和特定实体的业务逻辑,避免领域层结构混乱。同时通过
Hideable接口规定实体需实现的方法(比如markAsHidden()),让MarkItemAsHidden服务依赖接口而非具体实体,符合依赖倒置原则,扩展性更强。
3. 行为驱动的实体扩展模式
如果隐藏逻辑本质是实体自身的行为,只是多个实体都具备该行为,可让实体自行实现逻辑并触发事件,MarkItemAsHidden作为应用服务协调执行:
- 目录结构示例:
Domain/ ├── Entities/ │ ├── Product.php(实现Hideable接口,内部触发MarkedItemAsHidden事件) │ ├── Category.php(实现Hideable接口,内部触发MarkedItemAsHidden事件) │ └── Cart.php └── Events/ └── MarkedItemAsHidden.php Application/ └── Services/ └── MarkItemAsHidden.php Infrastructure/ └── Projections/ └── HidingProjector.php - 逻辑说明:这种方式更贴合DDD“实体封装自身行为”的核心原则,应用服务仅负责接收请求、调用实体方法,事件由实体内部触发。投影器属于基础设施层的持久化或视图更新逻辑,放在Infrastructure目录下的Projections子目录。
关键注意点
- 无论选择哪种方式,建议定义
Hideable接口,约束所有需要支持隐藏逻辑的实体,避免MarkItemAsHidden服务处理不兼容的实体类型。 - 领域事件
MarkedItemAsHidden应包含实体标识、类型、操作时间等核心信息,便于投影器或其他事件处理器处理。
内容的提问来源于stack exchange,提问作者SPQRInc
相关产品推荐
相关产品推荐

