微服务简介

单体式架构

现在我们看到的C端产品和B端产品,大都采用的是单体式架构,无论是用户感知到的前端页面还是后台架构,都是把所有的功能、服务集成于一体的,所以叫作单体式架构。

微服务

“微”是指微小,即将单体式架构的产品化整为零,拆分成一个个更小的单元,进行解耦;
“服务”是指用户可以感知的、独立的功能单元,每个服务都具有自主运行的业务功能,它既可以是一个个系统,也可以是一个个独立的功能模块,如员工信息管理模块、合同管理模块。甚至可以“微”到一个个接口,我们的产品就是由一个或多个服务组成的。

微服务与领域驱动设计

与微服务这种“化整为零、分而治之”的思想相同,领域驱动设计也是基于这一思想,将一个庞大的业务领域先拆分成一个个小的子领域,然后针对这些小的子领域,分而治之。

流程驱动设计与领域驱动设计

当产品复杂度较低时,流程驱动设计所需时间更短;随着产品复杂度逐渐提升,当产品复杂度到达一定程度时,流程驱动设计所需的时间会呈指数上升,而领域驱动设计所需的时间则始终比较平稳,所以从这一点看,流程驱动设计更适合简单的小型产品,而领域驱动设计更适合复杂的产品。
领域驱动设计的最后一步大家可以发现,这两种设计方式其实存在一定的包含关系。对于复杂系统而言,我们需要先采用领域驱动设计划分子域,当将复杂领域化繁为简后,在子域内就能采用流程驱动设计的方式了。

领域驱动设计

领域驱动设计(Domain Driven Design,简称DDD)是一种开发复杂软件的方法,是指在某个具体的领域中,一种面向对象的设计方式。
【PS:更大的对象】

基础概念

领域与子域

领域,广义上是指一种特定的范围或区域;在领域驱动设计中,领域是指业务范围内所有的服务和活动。将领域按一定规则划分成逻辑分离、同时彼此间又有联系的小领域,就是子域。
根据子域与业务关联的紧密程度,子域又可以分为核心子域、支撑子域和通用子域三类。
image.png
(1)核心子域
核心子域是指从公司角度来看,业务中最重要的子域。
子域划分是从公司角度,而非用户角度来划分的。例如,一个电商产品,对于用户来说最重要的是快速、方便地买到自己想要的商品,所以用户眼中的核心子域应该是“交易子域”;而对公司而言,其发展前期最关注的确实是交易部分,这时从公司角度和用户角度所定义的核心子域是相同的,但随着公司业务的发展,其重心在不断变化,假如公司为了与竞品形成差异化优势,需要通过打造更高效的物流服务来形成公司的核心竞争力,那么这时最核心的子域就是“物流子域”。
(2)支撑子域
支撑子域是指与业务相关,但不是核心部分的子域。例如,电商系统中的库存子域、订单子域等。
(3)通用子域
通用子域是指能够被多个领域共用的子域。例如,用户账号子域,多个领域都需要用到,具有很强的通用性。

子域分类要点

子域类型的划分不是一成不变的,不同的业务、维度、时期,划分的结果都会有很大差别。

  • 业务不同划分结果不同。如果是一个电商后台管理系统,用户信息子域一般是通用子域;而如果是一个用户管理系统,那么用户信息子域可能就变成了核心子域或支撑子域。
  • 阶段目标不同划分结果不同。如果公司的阶段性目标再一次调整,从前面打造高效的物流服务变为建设高效的库存管理,那么核心子域就会变成库存子域。

    实体、属性、值对象、聚合、联系

    实体、属性、值对象、聚合、联系是设计数据库、E-R图中最基础的几个概念。
    image.png
    (1)实体
    实体是指现实世界中具有唯一性的现实或虚拟的对象,简单理解就是领域中的一个个概念。例如,人事管理领域中的员工、薪酬、组织等。实体又分为强实体和弱实体。

  • 强实体是指可独立存在,无须依赖其他实体的实体,如员工、组织都是强实体。

  • 弱实体是指无法独立存在,对其他实体(强实体或弱实体都可以,一般为强实体)有很强的依赖性的实体,如岗位就是弱实体,它需要依赖组织这个强实体才能存在,脱离组织谈岗位是没有意义的。

(2)属性
属性是指描述实体的特征。如员工这个实体,其属性包括员工ID、员工姓名、身份证号、住址等。
(3)值对象
值对象是属性的具体值,如员工ID这个属性,每个员工都有一个具体的ID,这个具体的ID就是值对象。
(4)聚合
聚合是指以一个强实体为基础,多个与之相关的弱实体共同组成的一个整体,其中的强实体也叫作聚合根。例如,以“组织”这一强实体为基础,与“岗位”这一弱实体共同组成的“组织”聚合。
(5)联系
联系也称关系,是反映实体内部或实体之间的关系。实体内部的联系通常是指组成实体的各属性之间的联系;实体之间的联系通常是指不同实体或实体聚合之间的联系。

领域模型

领域模型是将业务领域中的概念进行抽象后,用具象的方式表现这些概念间关系的图形。在这个模型中,有两大特点。

  • 抽象的。领域模型是以提炼的业务概念为基础,梳理它们之间的关系,虽然模型是通过图形具象展现的,但对于最终的产品形态来说,它仍然是一个抽象的事物。
  • 解决特定问题。每个领域中的问题非常多,有的问题很复杂,领域模型不可能做到面面俱到,它只能解决特定方面的问题,也就是体现系统能够管理的实体、实体关系及子域间的关系。

#领域驱动设计实践

1)分析需求,识别实体

领域驱动设计的基础是实体,第一步要做的就是要根据前期调研的需求,与业务代表一起识别系统需要管理的实体。
一个比较快速有效的方法是通过需求中的动宾短语来识别,找出需求清单中所有动宾结构的短语,将这些短语中的宾语提炼出来,然后将表达为同一个意思的宾语合并、去重,就能初步得到我们要的实体。
避免遗漏的方法:按具体场景分别梳理。专注单线主流程,忽略分支流程和异常流程。

2)多个维度,划分子域

当一个领域模型中的实体比较多时,要将这些实体划分到不同的子域中,达到聚焦重点、“分而治之”的效果。
在划分子域时,可以先按类型进行划分,即找出模型中的核心子域、支撑子域和通用子域分别管理的实体是哪些。
如果这样划分后的核心子域依然很复杂,那么可以进一步按业务领域来划分。从业务维度进行划分时,需要结合业务、技术、团队三个维度综合考量。

  • 业务维度,是指根据业务需求和当前阶段的目标划分子域,与业务重点关联的实体就划分到核心域中,与业务相关但重要性不高的实体就可以放到支撑域中。
  • 技术维度,是指根据实体数据的通用性和复用性划分通用域的实体。例如,HRM系统中的员工、组织、岗位这三个实体,是非常通用的信息,很多第三方系统都需要用到,调用也非常频繁,所以应该把这三个实体单独抽离出来,划分到通用域中。
  • 团队维度,是指根据团队成员的能力、技术水平、擅长领域这些因素划分子域,这样各个子团队就能领到更契合自己能力的子域任务了,让团队成员的能力最大化,最终提升整体效率。

image.png

3)分析实体,建立关系

划分了子域,我们再来分析实体间的关系,并根据实体间的关系,分析子域间的联系。
实体关系是指不同实体是如何关联的,可以分为直接关联和间接关联两种。

直接关联:有直接影响的实体关系。例如,“岗位”与“员工”“组织”与“岗位”的关系,就是直接关联,在领域模型中用实线相连。 间接关联:通过中间实体相互影响的实体关系。例如,“员工”与“组织”的关系,是通过“岗位”这个中间实体建立的。

对应关系:1对1(1∶1),1对多(1∶n),多对多(n∶n)。
表达规则:为了更精准地表达实体间的关系,我们会把对应数量的起始值和终止值都写出来。以“员工”与“岗位”的关系为例,每个“员工”入职后至少有一个“岗位”,所以起始值是1,同时又可以兼任多个岗位,如果管理上没有限制的话,那么终止值就是n(n>1),因此“员工”对应“岗位”的数量就是从1到n的连续值,在模型中用1,…,n表示,中间的省略号就是连续的意思。如果起始值与终止值相等,就可以只写一个数。
子域关系:在建立实体关系时,不同子域间的实体关系同样需要建立,形成完整领域的模型。

4)走查场景,优化模型

【PS:走查无处不在】
通过走查场景,从简化模型和分析模型能否满足各个场景的需求两方面对模型进行优化。
简化模型
在建立模型时,我们需要有一个意识:在满足需求的前提下,模型越简单越好。因为模型越简单就越稳定,后续改动的可能性就越小,同时无论是后台设计还是产品设计都更清晰、更容易,所以我们需要尽量简化模型。在简化模型时,产品经理可以从简化实体和简化关系两方面入手。

  • 简化实体:简化实体是简化模型中最有效的方式。它包括以下两个方面。一方面是把不需要的、定义错误的实体删除,有时候我们容易把实体的属性定义为新的实体,如员工简历,完全可以作为员工的属性之一进行管理,而不需要将其定义为新的实体。另一方面是将实体整合。
  • 简化关系:在建立关联时,产品经理可以根据需求挖掘关联关系的限制条件,并将这些限制条件应用到关系上,将多对多简化为1对多,将1对多简化为1对1。

    为什么不在实体确定后就进行简化,非要等到前面做了那么多工作了才进行实体简化呢? 因为很多实体到底能不能简化,需要分析了与其他实体间的关系才能确定。另外,简化模型其实是一个持续的过程,从识别实体到最后一步,都可以进行。

判断模型的准确性
判断模型的准确性一方面是看模型是否能满足业务需求,另一方面是看模型关联关系是否正确。

  • 模型应满足多个场景的需求:不仅要看当前的业务需求,还要预测未来可能的需求。
  • 关联关系应正确:在领域模型中,两个实体无论是直接关联还是间接关联,往往会有多条路径可以找到对方,这时我们就要通过多条路径去找对应关系,看通过各个路径找出的关系是否一致。

    5)统一名词,形成共识

    将所有涉及的实体、名词整理成一张词汇表,以达到团队内统一概念、统一名词的目的。比如节日和节假日的区别。
    为了使开发人员在写代码时也能保持名词的统一,实体的英文名及缩写也要整理出来。

    6)子域内流程驱动设计

    领域驱动设计最重要的价值之一是帮助我们把庞杂的业务领域有序地划分为一个个相互独立,同时又相互关联的子域。当这些子域确定后,我们还无法拿出具体的产品方案,所以从这一步开始,我们就可以在各个子域内按流程驱动设计的方法进行了。