旅程2:分解领域

设计停靠站点

“没有石头就没有拱门” --马可波罗

在本章中,我们将对Contoso会议管理系统进行一个高层次的概述。这将帮助您理解应用程序的结构、集成点以及应用程序的各个部分之间的关系。

在这里,我们借用Eric Evans在他的书《领域驱动设计 软件核心复杂性应对之道(Addison-Wesley Professional, 2003)中描述的领域驱动设计(DDD)方法来描述这个高级结构。DDD是成功实现CQRS模式的先决条件虽然还没有达成普遍的共识,但我们团队依然决定按照CQRS社区的惯例使用DDD里众多概念和方法,例如领域、限界上下文,和聚合。参考指南的第1章“上下文中的CQRS”更详细地讨论了DDD和CQRS模式之间的关系。

本章使用的定义

在本章中,我们使用了一些术语,我们将在后面定义它们。有关更多细节和可能的替代定义,请参见参考指南中的第1章“上下文中的CQRS”。

  • 领域(Domain):领域是指Contoso会议管理系统的业务域(参考实现)。第一章“我们的领域:Contoso会议管理系统”概述了这个领域。

  • 限界上下文(Bounded Context):术语限界上下文来自Eric Evans的书。简而言之,Evans引入这个概念是为了将一个大型的、复杂的系统分解成更易于管理的部分。大型系统由多个限界上下文组成。每个限界上下文都是自己包含领域模型的上下文,并且有它自己的通用语言(Ubiquitous Language)。您还可以将限界上下文看做明确定义了一致性边界的自主业务组件。一个限界上下文通常通过引发事件(Raising Events)与另一个限界上下文通信。

    Gary(CQRS专家)发言:

    当你使用CQRS模式时,经常使用事件在限界上下文中进行通信。集成还有其他方法,比如在数据库级共享数据。

  • 上下文映射:根据Eric Evans的说法,您应该“描述模型之间的联系点,明确所有通信需要的转换,并突出任何共享的内容。”这个练习产生了所谓的上下文映射,它有几个用途,包括提供整个系统的概览,以及帮助人们理解不同的限界上下文如何相互交互的细节。

会议系统中的限界上下文

  • 订单和注册限界上下文:在订单和注册限界上下文中包含预订、付款和注册项。当注册用户与系统交互时,系统创建一个订单来管理预订、付款和注册。订单包含一个或多个订单项。


    预订是在会议上临时预订一个或多个座位。当注册用户开始订购会议上的一些座位时,系统会为这些座位创建预订。然后,其他用户无法预订这些座位。预订保留15分钟,在此期间,登录人可以通过支付座位的费用完成订购过程。如果用户没有在15分钟内付款,系统将删除该预订,其他用户可以继续预订这些座位。

    Carlos(领域专家)发言:

    我们讨论过将系统保留预订的时间期限设置成一个参数,这样客户可以为每次会议调整这个预留时间。如果我们确定需要这种级别的控制,那么这可能是我们需要添加的一个特性。

  • 会议管理限界上下文:在这个限界上下文中,业务客户可以创建新的会议并管理它们。在业务客户创建新会议之后,他可以使用电子邮件和访问代码来访问查看会议的详细信息。当业务客户创建会议时,系统生成访问代码。

    业务客户可以指定以下关于会议的信息:

    • 名称、描述和slug(用于访问会议的URL的一部分)。
    • 会议的开始和结束日期。
    • 会议提供的不同座位类型和配额。

    此外,业务客户可以通过发布或取消发布来控制会议在公共网站上的可见性。

    业务客户还可以使用会议管理网站查看订单和参会者列表。

  • 支付限界上下文:支付限界上下文负责管理会议管理系统和外部支付系统之间的交互。它将必要的付款信息转发给外部系统,并接收付款被接受或拒绝的结果。它将支付的成功或失败报告给会议管理系统。一开始,支付限界上下文将假定业务客户在第三方支付系统中有一个帐户(尽管不一定是商家帐户),或者业务客户将接受发票支付。

旅程中未包含的几个限界上下文

虽然这几个限界上下文没有进入Contoso会议管理系统的最终版本,但是做了一些工作。社区成员正在开发这些以及一些其他功能,任何带外发布和更新都将在“CQRS之旅”网站上公布。如果您想对这些限界上下文或系统的任何其他方面有所贡献,请访问项目“CQRS Journey”网站或通过cqrsjourney@microsoft.com让我们知道。

  • 折扣限界上下文: 处理会议座位的购买管理和应用折扣。该会议与主系统三个已存在的限界上下文集成在一起。

  • 偶尔断开连接的会议管理客户端:这个限界上下文用于处理会议现场的管理,具有处理标签打印、记录参会者到达情况和额外座位销售的功能。

  • 提交和进度管理限界上下文:用于处理使用Node.js编写的论文提交和会议事件调度。

在这个版本中没有实现候选清单功能,但是社区成员正在开发这个特性和其他特性。任何带外发布和更新都将在“CQRS之旅”网站上公布。

Contoso会议管理系统的上下文映射

图1和后面的列表显示上下文映射,该映射显示构成完整系统的不同限界上下文之间的关系,因此它提供了系统如何组合在一起的高级概述。尽管这个上下文映射看起来非常简单,但是这些限界上下文的实现,以及更重要的是它们之间的交互,都是相对复杂的。这使我们能够遭遇并处理CQRS模式和Event Sourcing的广泛问题,并有了一个丰富的源头来获取很多宝贵的经验和教训。

Gary(CQRS专家)发言:

关于CQRS项目的一个常见说法是:很难理解所有部分是如何组合在一起的,特别是如果系统中有很多命令和事件。通常,您可以对代码执行一些静态分析,以确定事件和命令是在哪里被处理的,但是很难查明它们是在哪里发起的。在高层次上,上下文映射可以帮助您理解不同限界上下文和相关事件之间的集成。维护有关命令和事件的最新文档可以提供更详细的信息。另外,如果你有测试,使用命令作为输入,然后检查事件,您可以通过测试来了解某个特定命令的预期结果(参见第4章“扩展和提高订单和注册限界上下文”中的测试示例)。

图1显示了构成Contoso会议管理系统的三个限界上下文。图中的箭头表示它们之间的事件数据流。

下面的列表提供了关于图1中的箭头的更多信息。您可以在讨论单独限界上下文的章节中找到更多的细节。

  • 在创建、更新或发布会议时报告的事件。创建或更新座位类型时报告的事件。
  • 创建或更新订单时报告的事件。当与会者被分配到座位时报告的事件。
  • 要求付款。
  • 确认付款的成功或失败。

Gary(CQRS专家)发言:

会议管理限界上下文引发的一些事件是粗粒度的,包含多个字段。请记住,会议管理是一个使用创建、读取、更新和删除(CRUD)模式的限界上下文,不会引发细粒度的领域事件。有关更多信息,请参见第5章:“准备发布V1版本”。

为什么选择这些限界上下文?

在旅程(开发)的规划(初期)阶段,很明显,这些是领域中的自然划分,可以包含各自独立的领域模型。其中一些划分比其他的更容易识别。例如,很明显,会议管理限界上下文独立于领域的其他部分。它具有与定义会议和座位类型相关的明确定义的职责,以及与应用程序其他部分的明确定义的集成点。

另一方面,我们花了一些时间才意识到订单和注册限界上下文与支付限界上下文是分开的。例如,直到应用程序的V2发行版,当OrderPaymentConfirmed事件成为OrderConfirmed事件时,与支付相关的所有概念才从订单和注册上下文中消失。

Gary(CQRS专家)发言:

随着我们对领域模型理解的加深,我们在整个过程中不断细化领域模型。

更实际,从旅途的角度来看,我们想要一组限界上下文,使我们能够发布一个可工作的应用程序并包含一些核心的功能,它可以使我们去探索许多不同的实现模式:CQRS, CQRS/ES,以及与传统的集成,例如CRUD风格的限界上下文。

Beth(业务经理)发言:

Contoso希望尽快发布一个可用的应用程序,但是还要能够在开发过程中添加计划的特性和客户要求的特性,并且不需要停机就能进行升级。

CQRS之旅——旅程2(分解领域)的更多相关文章

  1. CQRS之旅——旅程1(我们的领域:Contoso会议管理系统)

    旅程1:我们的领域:Contoso会议管理系统 起点:我们从哪里来,我们带来了什么,谁将与我们同行?" 只要前进,我愿意去任何地方." --大卫•利文斯通 本章介绍了一个虚构的公司 ...

  2. CQRS之旅——旅程3(订单和注册限界上下文)

    旅程3:订单和注册限界上下文 CQRS之旅的第一站 "寓言家和鳄鱼是一样的,只是名字不同" --约翰·劳森 描述: 订单和注册上下文有一部分职责在会议预订的过程中,在此上下文中,一 ...

  3. CQRS之旅——旅程5(准备发布V1版本)

    旅程5:准备发布V1版本 添加功能和重构,为V1版本发布做准备. "大多数人在完成一件事之后,就像留声机的唱片一样,一遍又一遍地使用它,直到它破碎,忘记了过去是用来创造更多未来的东西.&qu ...

  4. CQRS之旅——旅程4(扩展和增强订单和注册限界上下文)

    旅程4:扩展和增强订单和注册限界上下文 进一步探索订单和注册的有界上下文. "我明白,如果一个人想看些新鲜的东西,旅行并不是没有意义的."儒勒·凡尔纳,环游世界80天 对限界上下文 ...

  5. CQRS之旅——旅程8(后记:经验教训)

    旅程8:后记:经验教训 我们的地图有多好?我们走了多远?我们学到了什么?我们迷路了吗? "这片土地可能对那些愿意冒险的人有益."亨利.哈德逊 这一章总结了我们旅程中的发现.它强调了 ...

  6. CQRS之旅——旅程6(我们系统的版本管理)

    旅程6:我们系统的版本管理 准备下一站:升级和迁移 "变化是生活的调味品."威廉·考珀 此阶段的最高目标是了解如何升级包含实现CQRS模式和事件源的限界上下文的系统.团队在这一阶段 ...

  7. CQRS之旅——旅程7(增加弹性和优化性能)

    旅程7:增加弹性和优化性能 到达旅程的终点:最后的任务. "你不能飞的像一只长着鹪鹩翅膀的老鹰那样."亨利·哈德逊 我们旅程的最后阶段的三个主要目标是使系统对故障更具弹性,提高UI ...

  8. CQRS之旅——前言(翻译)

    探索CQRS和Event Sourcing 本项目聚焦在使用命令和查询分离模式和事件溯源(CQRS+Event Sourcing)构建一个具有高扩展,高可用和高维护性的应用程序. 本项目定位为一个学习 ...

  9. ES与CQRS之旅

    引言 领域驱动设计(Domain Driven Design),使用统一的建模语言.专注业务领域分析.采取化整为零并反复迭代的方式,以业务领域模型为圆心,向外辐射到系统轮廓的勾勒.具体模块的实现,为我 ...

随机推荐

  1. POJ2513(字典树+图的连通性判断)

    //用map映射TLE,字典树就AC了#include"cstdio" #include"set" using namespace std; ; ;//26个小 ...

  2. 十道海量数据处理面试题 - 数据分析与数据挖掘技术-炼数成金-Dataguru专业数据分析社区

    1.海量日志数据,提取出某日访问百度次数最多的那个IP. 首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中.注意到IP是32位的,最多有个2^32个IP.同样可以采用映射的方法 ...

  3. mongodb 分页(limit)

    db.COLLECTION_NAME.find().limit(NUMBER) db.mycol.find().limit() db.mycol.find({},{,_id:}).limit().sk ...

  4. SpringBoot04 项目热部署详解

    1 热部署 优点:适用于本地和线上.无需重启服务器 2 热部署和热加载的联系和区别 2.1 联系 不用重启服务器就可以编译和部署项目 都是基于Java的类加载器实现 2.2 字面区别 热部署在服务器运 ...

  5. JSP错误页面

    exception是JSP九大内置对象之一,其实例代表其他页面的异常和错误.只有当页面是错误处理页面时,即isErroePage为 true时,该对象才可以使用.对于C项,errorPage的实质就是 ...

  6. WebGL three.js学习笔记 6种类型的纹理介绍及应用

    WebGL three.js学习笔记 6种类型的纹理介绍及应用 本文所使用到的demo演示: 高光贴图Demo演示 反光效果Demo演示(因为是加载的模型,所以速度会慢) (一)普通纹理 计算机图形学 ...

  7. CEPH安装教程(中)

    NTP服务配置 NTP客户端配置 # vim /etc/ntp.conf server 92.0.0.250 ### 手动同步下时间 # ntpdate -u 92.0.0.250 ### 启动服务 ...

  8. MySql中存储过程的理解

    到底什么是存储过程,又为什么需要使用存储过程? 存储过程简单来说,就是为以后的使用而保存的一条或多条MySQL语句的集合,可将其视为批文件,虽然它们的作用不仅限与批处理. 使用存储过程有3个主要的好处 ...

  9. SQL数据库操作整理

    1.规范 ①关键字与函数名称全部大写: ②数据库名称.表名称.字段名称全部小写: ③SQL语句必须以分号结尾. 2.数据库操作 // 1. 创建数据库,其中[]表示可以省略 CREATE { DATA ...

  10. CF 979D Kuro and GCD and XOR and SUM(异或 Trie)

    CF 979D Kuro and GCD and XOR and SUM(异或 Trie) 给出q(<=1e5)个操作.操作分两种,一种是插入一个数u(<=1e5),另一种是给出三个数x, ...