02|统一语言是必要的吗?

你好,我是徐昊。今天我们来聊一聊领域驱动设计中的统一语言与模型的关联。

在上一讲,我们介绍了领域驱动设计的核心理念,即在业务系统中应该使用与问题域相关的模型,而不是通用的数据结构去描述问题。并由此介绍了Eric Evans提倡的知识消化,总结起来就是“两关联一循环”。

我们讲了第一个关联,那就是模型与软件实现的关联,并解释了为什么它是实践知识消化的前提。那么今天我们来讲第二个关联:统一语言与模型关联,也就是从模型中提取统一语言。

不过在讲具体做法之前,我们要先思考一下,为什么需要统一语言,以及统一语言会带来哪些好处。

统一语言是基于领域模型的共同语言

统一语言(Ubiquitous Language)是一种业务方与技术方共同使用的共同语言(Common Language),业务方与技术方通过共同语言描述业务规则与需求变动。可以说,共同语言为双方提供了协作与沟通的基础。注意,这里的业务方泛指一切非最终软件实现者,他们可能有很多名字:客户、产品、业务、业务分析师、解决方案架构师、用户体验设计师等等。

共同语言也有很多种形式。比如,用户画像(User Persona)与相关的用户旅程(User Journey) ,就能从流程角度有效地构成共同语言。再比如,数据字典(Data Dictionary)在很长的时间里,也是从软件实现侧形成共同语言的依据。

不过领域驱动设计中的统一语言,特指根据领域模型构造的共同语言。这也是为什么要为它特意构造一个专有且生僻的词汇Ubiquitous Language,来和我们一般意义上的共同语言作出区分。

我们知道,领域驱动设计是一种模型驱动的设计方法。那么在理论的理想情况下,模型本身就应该是业务方和技术方讨论需求的基础(如下图所示)。照此来看,这是不是就意味着统一语言是多余的呢?

通过图示可以看出,直接使用模型作为统一语言在实际操作中效果并不理想。

我们可以先从业务方和技术方各自所站的视角来分析一下。

如果站在研发人员的角度,直接使用模型有诸多好处。但是如果将视角切换到业务方,模型就不够直观了,业务方难以直接把模型和他们对系统的理解关联到一起。这主要是因为业务方看待系统的角度与开发人员不同。

业务方大多习惯从业务维度(Business Perspective),比如流程、交互、功能、规则、价值等出发去描述软件系统,这是业务方感知软件系统的主要途径。而模型则偏重于数据角度,描述了在不同业务维度下,数据将会如何改变,以及如何支撑对应的计算与统计。那么,业务的维度就被模型的抽象隐藏了,业务方是无法从模型中直接感知到业务维度的。

此外,模型是从已知需求中总结提炼的知识,这就意味着模型无法表达未知需求中尚未提炼的知识。但是,单纯使用模型一定会有无法表述的需求,因而我们需要一个相对允许歧义与未知的隔离层,来帮助我们发现和反馈模型的不足。

更确切地说,我们需要一种能与模型关联的共同语言,它既能让模型在核心位置扮演关键角色,又能弥合视角差异,并提供足够的缓冲

从模型中提取的统一语言,覆盖了领域模型中的概念与逻辑,还提供必要的补充,以帮助业务方理解模型。同时,统一语言也扮演了试验田的角色,其中出现的未被提取的知识,将作为触发提炼知识的循环,逐步完善模型。因而,如下图所示,我们会在提炼知识的循环中使用统一语言,而不是模型。

再进一步说,不直接使用模型,也是领域驱动方法对其他模型驱动方法的反思。同样兴起于20世纪末21世纪初的模型驱动架构(Model Driven Architecture),就建议业务人员直接使用模型描述需求,然而并没有取得成功。因为相对于模型的精确,统一语言的模糊反而更能满足人与人之间交流的需求

因而,虽然理论上说可以不需要,但统一语言并不是多余的,它源自一线实践者的经验,是一种实证的智慧。

当然,经过了多年实践之后,最终我们还是借由不同的建模方法,能够几乎仅仅使用模型作为统一语言了,我会在第7-9讲为你介绍。不过在那日到来之前,我们还需要知道,统一语言带来的好处与改变,怎么提取统一语言,以及现在它是个什么样子。

修改代码就是改变统一语言

我们在讲关联模型与软件实现时,提到它的最终目的是达到这样一种状态:修改模型就是修改代码;修改代码就是修改模型。要知道,统一语言是从领域模型中提取的,包含了领域模型中的概念与逻辑。那么改变了模型,实际上也就改变了统一语言

于是,修改代码就是修改模型,改变模型就是改变统一语言,修改代码等于改变统一语言。这是一个强而有力的推论,因为它描述了这样一种可能的场景:不是因为需求变更,而是因为代码重组与重构引起的代码修改,最终会反映到统一语言中,反映到我们应该如何理解并沟通的需求上去(如下图所示)。

这相当于让开发方来定义业务问题,并要求业务方按照开发提出的模型来描述业务和需求。这听起来匪夷所思,但实际上这种情况每时每刻都在上演,只是身在其中的人并不自知而已。

想想看,一旦将软件实现与领域模型关联,那么对实现的简化,也就是对领域问题的简化;从实现中抽取的抽象概念,也就是从问题域中抽取的抽象概念

通常的情况是,技术方通过代码不断修改实际的业务模型,但这种变化很难有效传递给业务方,于是这种变化就成为了“隐秘的角落”。同时,也很难让业务方以技术方改变后的业务概念去思考问题。最终导致双方互看不爽,分歧越来越大。

因此,看起来匪夷所思的情况,实际上一直都在发生。技术方一直都在定义业务,只是没有合理的途径让业务方了解并接纳而已。

不过统一语言及其背后的领域模型从观念上改变了这一状况,它将大家从各自的领地,也就是业务与技术中,拉到了一个中间地带。统一语言与领域模型既不完全属于业务,也不完全属于技术,而是双方共有的部分。于是技术方与业务方就有了差不多的话语权,至少有了可以沟通和协同的空间。

一旦业务方接受了统一语言,实际上就是放弃了对业务100%的控制权,也意味着统一语言在业务上能够赋予开发人员更大的控制权。这或许是出于Eric的故意设计,抑或是源于Eric对敏捷价值观的深刻认同,在有限的几次接触中,我并没有跟他求证过。但可以肯定的是,统一语言实际上赋予了技术人员定义业务的权利

你可能会有疑问,业务人员放弃对业务的100%控制权话语权不是一件坏事吗

正如前面所讲,在实际工作中,修改代码引起模型改变无可避免。因而无论业务人员是否愿意,他们对业务其实都没有100%的控制权。差别仅仅在于业务人员是否知晓这种改变,是否有机会验证这种改变在合理的方向上

可以说,统一语言给予了双方一种沟通和协商的途径。只不过,统一语言在给技术方带来额外的权利同时,也隐含着额外的义务,即借由统一语言,在提炼知识的循环中,接受业务方的监督与反馈。如果业务方不同意技术方修改的模型,那么在后续提炼知识的循环中,可以修正这种误差,也就是技术人员也丧失了对代码100%的控制权。

看到这儿,你可能就明白了。除了将“隐秘的角落”公之于众外,模型还通过统一语言将开发视角的介入业务领域,为业务方带来有益的补充。毕竟跨行协作是创新的土壤,不是吗?

总结来说,统一语言提供了一种更好的协同方式的可能性。在业务方大多强势的环境中,难能可贵地建立了技术反馈业务的途径,降低了知识消化过程失败的风险。

听了这么多好处,我猜你肯定希望看到一个例子,以便直观地理解什么是统一语言。那么我在这里就展示一个简单的例子。

一个简单的统一语言提案

统一语言本身的形式并不重要,或者说统一语言并没有统一的形式,它甚至可以是任意一种形式。但是,当且仅当,统一语言与领域模型关联,且多方认可并承认对统一语言的集体所有权时,统一语言才能成为真正的统一语言

统一语言必须是团队的共识,是团队成员愿意在工作中使用的语言。在经由那个神圣的社交时刻(social moment)之前,我更愿意将它称作统一语言提案,以示与真正的统一语言的差别。毕竟在业务方与技术方都认可之前,它并不是统一语言。

统一语言可以包含以下内容:

  • 源自领域模型的概念与逻辑;
  • 界限上下文(Bounded Context);
  • 系统隐喻;
  • 职责的分层;
  • 模式(patterns)与惯用法。

我们仍然以极客时间专栏的模型为例,看看能提取出怎样的统一语言。由于目前这仍然是个很简单的模型,提取出来的语言可能无法包含上述所有内容,但能帮助你理解它,这就足够了。

根据这个模型,我们可以从中提取到对应的领域概念,也就是领域模型中的实体:

  • 用户(User)是指所有在极客时间注册过的人;
  • 订阅的专栏(Subscription)是指用户付费过的专栏。

同时由于User与Subscription之间的关系,我们可以提取一个业务逻辑:

  • 用户可以订阅多个专栏。

除了源自领域逻辑的核心概念之外,界限上下文、系统隐喻等其他几项都可以看作对业务维度的补充与展开。将它们引入通过统一语言后,可以帮助业务方更直观地理解模型

比如系统隐喻就是在价值与业务模式维度上的补充与扩展。我们经常会听到某某产品说,我们要做某某领域的淘宝,或者我们是某某行业的滴滴。这样言简意赅地表示了产品的愿景,也就是价值定位与核心模式。这些信息也应该放进统一语言中。类似的,责任分层关注“稳定性”,哪些是稳定而哪些是易变的;模式与惯用法是业务规则、流程与实现模式。

稍微需要额外提及一下的是界限上下文(Bounded Context)。界限上下文是围绕某些模型设置的边界。所有人对于如何利用边界中的模型有清晰明确的想法,这个想法借由这个边界保持一致,不受外界信息的干扰。

这个定义稍微有点不好理解,实际上界限上下文是现实中某种决定在模型上的反映。它可以是源自业务领域本身的,这时候界限上下文的范围就和子域(Subdomain)等概念所表示的范围重合了。比如,我们说这是订阅子域,因而存在一个叫做订阅的界限上下文。我们可以将界限上下文的名字放入统一语言:

  • 订阅。

此外,界限上下文还可以表示其他一些有的没的。比如,如果用户(User)源自另外一个服务,或者遗留系统,我们没法修改它。于是我们可以建立一个界限上下文,叫“动不了”,用来解释为什么会做出一些古怪的设计决定:“因为有的地方动不了”。我们需要在统一语言中加入这个界限上下文的名字,因为当我们说到“动不了”的时候,可能会指代这个上下文。

总的来说,界限上下文是万能的,应用之妙存乎一心,关键在于你会不会用。我建议你把它当个筐,不好解决的问题都扔进去就好了。

言归正传,我们现在抽取的语言是这样的:

  • 用户(User),指所有在极客时间注册过的人;
  • 订阅的专栏(Subscription),指用户付费过的专栏;
  • 用户可以订阅多个专栏;
  • 订阅。

通过定义与解释,我们使这些词语在其所使用的上下文中没有歧义。再通过这些基础词汇,去描述业务的行为或者规则,慢慢就可以将其确立为跨业务与技术的统一语言了。要始终记得,统一语言是在使用中被确立的

那么这个语言该怎么用呢?除了在日常沟通中口头使用之外,比如还可以通过它来编写用户需求(以用户故事的形式):

作为一个用户(User),当我查阅购买过的专栏(Subscription)时,从而可以看到其中的教学内容。

或是用它来描述行为驱动开发(Behaviour Driven Development)的测试:

当用户(User)已购买过了某个专栏(Subscription),那么当他/她访问这个专栏时,就不需要再为内容付费。

或是实例化需求(Specification by Example,SbE)的说明,等等。

重点是,在所有可能的地方使用这个语言。只有当所有工种角色都接受它,使用它去描述业务和系统的时候,它才会真正成为统一语言。

小结

我们来简单地总结一下。统一语言特指根据领域模型构造的业务方与技术方都使用的共同语言。虽然在理想中,我们希望直接使用模型作为统一语言。但从实际出发,直接使用模型的效果并不好。

主要是两点:

  • 模型将业务维度隐藏了,对业务方显得不够直观;
  • 对于未提取的知识,超出了模型的表达能力。因而统一语言是非常必要的。

需要强调的是,统一语言提供了一种更好的协同方式的可能性。统一语言与其背后的领域模型赋予了研发人员通过重构定义业务的能力,在业务方大多强势的环境中,难能可贵地建立了技术反馈业务的途径,降低了知识消化过程失败的风险。

到这里,我们的“两关联一循环”就还剩最后一个环节:凝练知识的循环。我们下节课再见。

编辑小提示:为了方便读者间的交流学习,我们建立了微信读者群。想要加入的同学,戳此加入“如何落地业务建模”交流群>>>

思考题

通过两节课的介绍,我想你大概对于知识消化与领域驱动设计有了自己的理解,那么你会怎么跟别人介绍领域驱动设计?你认为领域驱动设计到底是什么呢?

欢迎把你的思考和想法分享在留言区,我会和你交流。同时,我也会把其中不错的回答在留言区置顶,供大家学习讨论。

精选留言

  • 奔跑的蜗牛

    2021-07-02 22:45:02

    课后问题思考:
    领域驱动设计,逼着业务方和实现方像玩跷跷板一样共同构建业务系统,从协作角度看,这个游戏的特点是,【一个人没法玩】。
    板≈共同语言,支点≈模型,以“支点”为中心,以“板”为媒介,双方你一下我一下地玩。

    “板”+“支点”很大程度上定义了游戏的基本规则。
    作者回复

    good metaphor

    2021-07-03 08:05:58

  • Jxin

    2021-06-26 18:49:42

    上节留言是我错了:
    1.特地翻了下蓝书。统一语言->模型的理解浅了(模型不等于是画出来的类图或则代码,而应该是消化知识时的思维模式的产物)。是我以前的认知偏差了,实际工作中多是和业务方讨论出统一语言,再对统一语言做实现,结果就愣是把认知扭曲成这个顺序了。关键的错误认知在于,误以为模型指的是基于与业务方沟通的结果做的解决方案和代码实现。熟不知,在与业务方沟通时,自己脑袋中基于建模的思维模式就将业务知识消化转换成模型定义,并直接以自己定义的模型的术语与业务方做沟通,待沟通结束,已经完成了 模型->统一语言 的推导。

    课后题:
    1.领域驱动设计分两块,第一块是通过两关联一循环的知识消化方式,理解业务知识,并反馈给合作方对应的模型定义,以达成认知共识和行为约束(业务方讲故事要基于统一语言,开发人员改代码要反映到统一语言上)。也就是常说的战略部分;第二块是通过一系列的编码风格或者说编程范式,构建以领域模型为核心的代码结构,保证领域模型的富类型以更好的表达统一语言,保证领域模型的干净以更好的应对变化坚守统一语言与代码模型的原子操作。也就是常说的战术部分。
    2.领域驱动设计其实只是一系列软件开发过程的经验总结而成的方法论的总称,取这个名字主要因为这些方法论大多围绕领域业务为核心来设计模型和构建软件项目。可以说是来自字将的喜好。但也正应为领域驱动设计表达的是一个集合,所以现今流行的一些方法论也可以加入其中,只要是便于构建以领域业务为核心的软件项目这个目标,领域驱动设计的集合来着不惧。

    个人疑问:
    这么说统一语言是为了缓解开发和业务专家的认知差距?如果开发或者业务专家能完全理解业务和软件业务模型,就可以不需要统一语言?
    对于咨询行业来说,要应对众多的业务,每个都要成为专家显然不现实。但对于互联网大厂,很多业务或者开发在一个岗位一干就十来年,只要愿意学习,不管是开发掌握业务知识还是业务掌握软件模型显然都不是难事。那么还需要统一语言吗?现在,我认为统一语言其实只是一个别名,在开发与业务沟通的场合,所有双方的共同认知都属于统一语言(又是字将的喜好)。统一语言 ==(业务知识+软件模型)/共同认知。所以,可以不要统一语言直接用模型这个问题本身就有问题,毕竟有些时间统一语言就是模型,模型就是统一语言,不过是场景不同叫法不同。
    作者回复

    敬请期待下一课和7-9节

    2021-06-27 12:35:06

  • 箭和方糖

    2021-06-28 23:35:40

    技术人员通过重构进而影响业务,这个观点很独到,但从自身经验而言确实匪夷所思。这个真的是有可能的吗?从技术角度出发的重构真的可以影响经验老道的业务人员吗?
    作者回复

    可以 因为最后谁说了都不算 代码跑起来算

    2021-06-29 09:09:04

  • 极客侠女

    2021-08-26 07:00:52

    我的总结:DDD领域驱动设计,是解决业务系统中,业务方和技术方沟通协同的问题。
    它是从业务出发,以业务问题域为焦点,构造出与业务强相关的模型。
    1.该模型既要关联软件开发,使得对模型的修改,就是对代码的修改。
    2.又要关联统一语言,将业务方成为模型的使用者,统一语言驱动需求描述,驱动测试设计等。
    3.通过技术方和业务方不断地交流与反馈中,提炼知识的循环,逐步完成对模型的淬炼。
    作者回复

    nice

    2021-08-27 08:36:34

  • xtepCool

    2021-07-21 17:57:46

    麻烦大了,看不懂。
    作者回复

    慢慢来

    2021-07-21 18:45:33

  • fzhichao

    2021-06-30 08:49:13

    我在实践中认为统一语言必须使用双语(中文和英文)。业务人员可以使用统一语言写story卡,技术人员也可以使用统一语言写代码。
  • 赵晏龙

    2021-06-28 23:56:42

    领域驱动设计我的理解是:以模型为中心和桥梁,连接并同步需求与实现,同时不断试错并修正的设计方式。
    作者回复

    nice

    2021-06-29 09:10:06

  • Oops!

    2021-06-26 10:05:41

    印象深刻的一点是领域语言建立了技术反馈业务的途径。不过在实操方面,就是实际工作中如何建立领域语言,有哪些技巧、方法和工具可以应用呢?
    作者回复

    敬请期待7-9节

    2021-06-27 12:34:36

  • DeenJun

    2022-10-23 19:44:32

    有个很关键的问题: 业务方为什么要参与进来呢?如果我是业务方,我提完需求就行了,至于开发那是你们的事情。如果排期过长,我会找你们老板,然后你们自己去加班。至于模型不合理,那是你们设计有问题,侧面反应你们团队技术不行,你们自己加班证明自己吧。
    为什么要陪着你们玩什么统一语言和模型?我说我的,你听不懂是你理解能力有问题。
    说白了,站在业务方的角度来说,把DDD嵌入自己的工作流程对自己有任何好处吗
  • fzhichao

    2021-06-30 08:52:31

    技术重构代码(其实应该不是重构第二版描述的重构了,即便有测试覆盖,很大程度都是重写了),重新抽象模型,从而推动统一语言甚至需求解决的变化,这个在工作中深有体会。好的技术人员应该做到这一点。
  • Tom Yang

    2021-06-26 10:14:45

    以前读书的时候学习管理信息系统时书中有提到系统的设计视角是 社会 - 技术 视角,统一语言就是那个 社会 的要达到的共识吧。
    作者回复

    good point

    2021-06-27 12:34:02

  • .benxiaohai52

    2021-11-15 16:52:00

    什么是统一语言,统一语言是不是就是对需求中的概念大家形成统一的认知,有明确的释义。
  • 花花

    2021-09-01 18:28:42

    描述:
    针对大型、复杂系统开发流程的一种解决方案。
    领域驱动设计在逻辑设计上类似于结构化设计,自顶向下设计各个领域,由领域指导实现。

    前置条件:
    为实现领域驱动开发过程需各相关方人员在一起以业务需求出发建立统一语言,该语言是一个在组织环境、系统描述中各方各方都能接受的语言,
    是在该组织或该项目下独有的且语义明确清晰的。

    应用:
    在确定统一语言后则可以进一步的以统一建模语言为基础提取出各方都确认的领域模型,由该模型的逻辑结构指导系统的实现,以达到实现与模型与需求相一致的目的。
    作者回复

    nice

    2021-09-02 10:37:10

  • 小毛球

    2021-06-29 08:27:17

    我理解的DDD是击穿业务和技术的隔阂,让双方有共同的需要,减少业务和实现的偏差,技术更改了模型以后也能即使反馈给业务。另外一个是富含知识的代码,在显示中缺少业务和技术的文档,甚至代码注释都少,遗留系统非常难以维护,DDD能解决一部分的问题
    作者回复

    光靠富含知识的代码可能还是不太够

    2021-06-29 09:11:18

  • 重庆森林

    2021-06-28 17:22:17

    一个合适的系统隐喻怎么进行恰当的提取,有规律性的方法吗?
    作者回复

    没有 这需要点创造力

    2021-06-29 09:08:35

  • 新生\

    2024-08-27 12:19:41

    我来了
  • 6点无痛早起学习的和尚

    2023-12-14 10:05:34

    2023年12月14日10:04:46,根据文中的例子,用统一语言实践了工作内容
    实体:
    ● 客户
    ● 客户添加的受益人
    业务逻辑:
    ● 客户可以添加多个受益人,并指定比例
    添加
    修改
  • Geek_有心

    2023-11-04 16:26:54

    统一语言可以极大的可以减少沟通成本,让需求方和实现方快速沟通
  • 法兰克

    2022-11-16 09:12:35

    课后作业:硬软件的存在都是为了解决上游的需求,这个上游可以是测试,开发,产品,业务。业务系统是为了更直接有效的解决业务问题,所以这里面参与的角色众多,大家对于需求转化成系统的过程所用的认知和实现路径均有所差异,然而这种差异势必会引入分歧,反复,趋于失真。那么DDD的出现,它所提及的领域,聚合根,大泥球等概念是一种新的方法论集合,这种方法论出现是为了统一认知,共同参与,降低失真,萃取知识,提取模型,转化代码。说白了就行端到端拉通认知和实现。
  • JianXu

    2022-09-24 07:12:25

    我们公司流量管理正在演进,运维人员和开发人员需要使用同一种语言,我们需要构建一个环境以使得可以一期迭代到统一语言。