在DDD的正式实施开始中,我们首先应该进行需求调研,在需求调研的过程中,我们应该可以接触到这个需求各个层面的相关人员:产品设计,开发,业务代表,实施人员等等。当进行完初步的需求调研,我们可以形成对应的产品文档和产品交互设计等等,以上都是相对成熟的设计方法和流程,所以不再复述。在进行完上述环节后,我们大体上可以进行系统的设计阶段了,那么在这个阶段,我们应该如何进行我们第一步操作?
对于设计一个系统,第一步并不是划分什么微服务,而是应该先组织一个设计活动,我们将之称为:事件风暴。
事件风暴的参与者需要组织和这个系统相关方尽可能的参加:需求代表,相关业务操作人员,产品设计人员,以及开发代表(应用架构师),测试代表,实施人员等等。
当有了以上人员的参加,我们就可以开始事件风暴,
事件风暴的第一个活动就是大家集中对用例进行收集(有的已经在产品设计阶段完成了部分)和分析,或者在组织事件风暴活动之前,我们已经完成了初步的用例收集。用例收集的部分用例大体如下表格所示(图例所示是一个支付系统的设计过程):
用例基本上都是基于现实业务流程,面向不同的业务和应用和使用者,都有不同的处理流程和方式。
在收集完毕用例后,我们可以通过每一个用例按照用例主体,用例动作,以及被操作实体,继续对每一个用例进行分析和分解。其实也就是我们中学语文中经常对 一句话找出其主谓宾类似。承接上图就有了以下这些划分:
在被操作的实体对象中,如果我们将这些实体进行相应的归类,比如:
对账文件,对账批次 ,对账单,调整单一类,毕竟貌似这几个都和对账有点关系
支付订单 一类 这个感觉相对独立
商户账户 这个感觉更加独立,也归为一类
通过将实体对象的归类,我们就可以认为一类近似的实体,可以归属于一类领域。那么首先我们要先回答一个问题:我们为什么要划分领域,一个大而全的系统不好吗?
因为系统解决的一定是我们上面所列的流程和用例,所以系统可以说是面向的就是业务和流程,而领域的划分就是跨越流程,沉淀出相应的服务,服务的主体就应该是基于领域。而且一旦我们通过沉淀了服务,我们服务就超越了流程,可以支撑更多的业务和产品的创新,而且在未来业务发生变化时,应对变化的不是系统,而是服务,这样增强了我们整个系统的可扩展性。
那么上面的示例 我们至少可以划分这样三个域:账户域,支付订单域,对账域等等。然后我们可以在这些领域中,我们可以找寻其中的核心域和支撑域,以及通用域。那什么是核心域?就需要回答这个问题:这个系统是通过什么东西提供了核心业务服务是什么?这个不是技术问题,而是一个业务问题。如果回答了这个问题,那么这个问题所涉及的对象就是核心域。至于支撑域和通用域,顾名思义可以了解到,就是为了支撑核心域的其他业务域为支撑域(不通用);通用域则是在全局范围内,都需要依赖的领域,比如权限。确定整个系统的核心域是一个经验主义的过程个,核心域的划分没有绝对的公式可以套用。因为商业模式的不同会导致核心域划分结果的不同。有的公司核心域可能在客户服务,有的可能在产品质量,有的可能在物流。在公司领域细分、建立领域模型和系统建设时,我们需要结合公司战略重点和商业模式,找到核心域了,且应该重点关注核心域。
既然在不同的商业场景下,核心域就是不一样的,比如笔者曾经参与过两套支付系统的建设,很多场景都是雷同的(如上图),现今回想起来一套核心域是订单,另一套则是账户。因为虽然支付系统都有订单,但由于其中一个支付系统后面不光只是支付收单,还涉及到理财,钱包,以及海外货币汇兑(海外牌照)等等业务,所以这个系统的核心域自然是账户体系。 但另一个支付系统就是简单的收集支付订单,核对流水,最后把整个订单金额去向进行留存归档即可(因为不涉及账户资金划拨),所以核心域就是支付订单。
当我们一旦明确了核心域,我们系统建设应该将核心域的建设排在首位,最好是有绝对的掌控能力和自主研发能力,如果资源实在有限的话,可以在支撑域或者通用域上想想办法,暂时采用外购的方式也未尝不可。所以当我们需要外包时,我们应该尽可能的外包非核心域的东西,尽可能的选择其他部分。(当然如何控制外包的质量,后面再谈)