第 26 章 查询:领域报告
第 26 章 查询:领域报告
构建非过度耦合到领域结构的报告的指导原则
在使用事件溯源的应用程序中构建报告
对在属于一个有界上下文的报告和需要从多个有界上下文中集成数据的报告之间做出选择时所涉及的取舍进行探讨。
- 有界上下文中的领域报告
构建软件系统是为了支持业务的需求。这些需求不仅包括产生 收益的功能,还包括评估业务执行情况的能力。
在你的应用程序中选择如何实现报告涉及考虑类似的权衡问题:开发速度,可维护性,性能,甚至可扩展性。
这里的报告被定义为用于一些分析目的的一组连贯数据的呈现。并非被管理者或者出于商业信息BI目的特殊使用的报告的这一正式概念。
-
- 从领域对象中派生的报告
让你所有的数据集中在相同的有界上下文中是最简单的报告场景。
这种情况下,不用担心分布式的问题,但是你做出决定时需要做的最大的决策就是,是否要在生成报告时使用你的领域代码。
# |
报告生成方式 |
1 |
使用简单映射 构建一个报告的最快方式大概就是使用领域对象并且将其属性映射到提供数据以及呈现构建视图所需逻辑的一个视图模型上。 如何构建你的视图模型,可以使用一个Report Builder类来实现。 但是这个生成report的性能会让人着急。 直接使用以上的映射,那么可能需要公开领域对象上的额外属性,这样会增加服务层耦合到领域结构的可能性。为了降低多余耦合,可以使用中介模式。 |
2 |
使用中介模式 使用中介模式,将你的视图模型传递到一个中介内,它本身会被传递到领域中。 然后领域对象会与该中介交互,它会相应更新视图模型。
|
|
|
-
- 直接访问数据存储
当性能和效率很重要的时候,或者再不希望通过复杂的层和映射时,许多DDD实践者都会直接从数据库中提取他们的报告。
在CQRS的应用程序中,会创建专用的,非规范化的数据副本,以便于需要他们的每份报告。
# |
|
1 |
查询一个数据存储 通过直接查询一个数据存储来构建报告会为你提供更大的控制权并且让你能够编写有效的查询。 但是这种范式的分享是,违背了DRY的原则,即重复工作的原则。 且修改维护遗漏风险较高。 |
2 |
读取非规范化视图缓存 有时候,即便使用手工SQL直接查询数据的效率也会很低。 基于这个原因,有些DDD实践者选择创建特定视图/报告的非规范化数据副本(视图缓存)。 这里的非规范视图承担了Report Builder的复杂性,这样报告的查询就会简单。 |
|
|
-
- 从事件流构建投影
从事件流构建投影
投影实际上只是对产生一些期望状态的事件流或基于原始流中事件内容的新流进行查询而已。
这个投影的查询,为了作出一份诊断分析,一个流会将每个月产生一个流事件。
- 为投影设置ES
- 创建报告投影
- 计算流中的事件数
- 根据需要创建尽可能多的流
- 从流和投影中构建一份报告
- 跨有界上下文的领域报告
当使用一个分布式系统时,比如:“战略模式:用于分布式领域驱动设计的模式”。
跨界报告的生成方法
1 |
事件驱动原则来创建一个专用的报告有界上下文,它会订阅大量的事件,这些事件具有本地存储在单个数据库中的所需的所有信息。 |
2 |
也可以转而使用更轻量级的方法,就是使用UI复合技术,“复合应用程序”。 |
-
- 符合UI
除了这种复合UI的方式,还可以在一个领域中进行客户端或者服务器聚合。
-
- 单独的报告上下文
出于性能,效率或便利性的原因,让用于报告的所有数据库存在于相同数据存储中可能是一个重要条件。关于此的一个实例是数据仓库。其中企业希望在其寻找未揭示的见解以新的方式切割其所有的数据。
实现一个报告上下文在范围和实现方面有很大的区别。
在最简单的情况下,可能类似在于其他任何有界上下文中订阅事件并将这些事件存储在SQL数据库中。
从另一个极端来说,可能需要通过各种数据库技术,推荐引擎以及机器学习算法来推送数据。
- 要点
使用事件流的投影也会牺牲后台出来换取更简单的读取。