一 领域驱动设计-运用领域模型-消化知识

目录
  • 运用领域模型-消化知识

    • 示例

    • 有效建模的要素

    • 知识消化

    • 持续学习

    • 知识丰富的设计

    • 深层模型

运用领域模型-消化知识

非原创,感谢《领域驱动设计》这本书

有效建模的要素

(1) 模型和实现的绑定。最初的原型虽然简陋,但它在模型与实现之间建立了早期链接,而且在所有后续的迭代中我们一直在维护该链接。

(2) 建立了一种基于模型的语言。随着项目的进展,双方都能够直接使用模型中的术语,并将它们组织为符合模型结构的语句,而且无需翻译即可理解互相要表达的意思。

个人理解:定义专业词语的字典解释,保证每个人对每个术语的理解都是一样的

(3) 开发一个蕴含丰富知识的模型。对象具有行为和强制性规则。模型并不仅仅是一种数据模式,它还是解决复杂问题不可或缺的部分。模型包含各种类型的知识。

(4) 提炼模型。在模型日趋完整的过程中,重要的概念不断被添加到模型中,但同样重要的是,不再使用的或不重要的概念则从模型中被移除。当一个不需要的概念与一个需要的概念有关联时,则把重要的概念提取到一个新模型中,其他那些不要的概念就可以丢弃了。

(5) 头脑风暴和实验。语言和草图,再加上头脑风暴活动,将我们的讨论变成“模型实验室”,在这些讨论中可以演示、尝试和判断上百种变化。当团队走查场景时,口头表达本身就可以作为所提议的模型的可行性测试,因为人们听到口头表达后,就能立即分辨出它是表达得清楚、简捷,还是表达得很笨拙。

正是头脑风暴和大量实验的创造力才使我们找到了一个富含知识的模型并对它进行提炼,在这个过程中,基于模型的语言提供了很大帮助,而且贯穿整个实现过程中的反馈闭环也对模型起到了“训练”作用。这种知识消化将团队的知识转化为有价值的模型。

知识消化

金融分析师要消化理解的内容是数字。他们筛选大量的详细数字,对其进行组合和重组以便寻求潜在的意义,查找可以产生重要影响的简单表示方式——一种可用作金融决策基础的理解。

高效的领域建模人员是知识的消化者。他们在大量信息中探寻有用的部分。他们不断尝试各种信息组织方式,努力寻找对大量信息有意义的简单视图。很多模型在尝试后被放弃或改造。只有找到一组适用于所有细节的抽象概念后,工作才算成功。这一精华严谨地表示了所发现的最为相关的知识。

知识消化并非一项孤立的活动,它一般是在开发人员的领导下,由开发人员与领域专家组成的团队来共同协作。他们共同收集信息,并通过消化而将它组织为有用的形式。信息的原始资料来自领域专家头脑中的知识、现有系统的用户,以及技术团队以前在相关遗留系统或同领域的其他项目中积累的经验。信息的形式也多种多样,有可能是为项目编写的文档,有可能是业务中使用的文件,也有可能来自大量的讨论。早期版本或原型将经验反馈给团队,然后团队对一些解释做出修改。

在传统的瀑布方法中,业务专家与分析员进行讨论,分析员消化理解这些知识后,对其进行抽象并将结果传递给程序员,再由程序员编写软件代码。由于这种方法完全没有反馈,因此总是失败。分析员全权负责创建模型,但他们创建的模型只是基于业务专家的意见。他们既没有向程序员学习的机会,也得不到早期软件版本的经验。知识只是朝一个方向流动,而且不会累积。

个人理解:现在依然有公司在这样做,业务需求人员定义需求,再由架构师或者组长进行翻译,之后直接分配给程序员任务,最后做出的程序往往和需求偏差较远,大部分会议是组行和业务参加,真正实现功能的程序员没有参与到会议讨论中来。

有些项目使用了迭代过程,但由于没有对知识进行抽象而无法建立起知识体系。开发人员听专家们描述某项所需的特性,然后开始构建它。他们将结果展示给专家,并询问接下来做什么。如果程序员愿意进行重构,则能够保持软件足够整洁,以便继续扩展它;但如果程序员对领域不感兴趣,则他们只会了解程序应该执行的功能,而不去了解它背后的原理。虽然这样也能开发出可用的软件,但项目永远也不会从原有特性中自然地扩展出强大的新特性。

好的程序员会自然而然地抽象并开发出一个可以完成更多工作的模型。但如果在建模时只是技术人员唱独角戏,而没有领域专家的协作,那么得到的概念将是很幼稚的。使用这些肤浅知识开发出来的软件只能做基本工作,而无法充分反映出领域专家的思考方式。

在团队所有成员一起消化理解模型的过程中,他们之间的交互也会发生变化。领域模型的不断精化迫使开发人员学习重要的业务原理,而不是机械地进行功能开发。领域专家被迫提炼自己已知道的重要知识的过程往往也是完善其自身理解的过程,而且他们会渐渐理解软件项目所必需的概念严谨性。

有这些因素都促使团队成员成为更合格的知识消化者。他们对知识去粗取精。他们将模型重塑为更有用的形式。由于分析员和程序员将自己的知识输入到了模型中,因此模型的组织更严密,抽象也更为整洁,从而为实现提供了更大支持。同时,由于领域专家也将他们的知识输入到了模型中,因此模型反映了业务的深层次知识,而且真正的业务原则得以抽象。

模型在不断改进的同时,也成为组织项目信息流的工具。模型聚焦于需求分析。它与编程和设计紧密交互。它通过良性循环加深团队成员对领域的理解,使他们更透彻地理解模型,并对其进一步精化。模型永远都不会是完美的,因为它是一个不断演化完善的过程。模型对理解领域必须是切实可用的。它们必须非常精确,以便使应用程序易于实现和理解。

个人理解:对于业务和开发来说,最大的问题是思维想法的同步,同步最大的问题是交流沟通,程序员大部分相对内向沉默,业务有时候也会厌烦重复的表述,造成理解偏差。建立模型并共同改进精化可以很好的解决这个问题,既然开发人员的思维方式(机器思维)和业务人员的思维方式(功能结果导向思维)不同,那么就使用一个中间翻译的语言,这个语言就叫做模型,也是抽象的模型。是大家一起来制定的一种抽象表达方式,每个人都要参与其中,并且不断进行更新。模型也充当了业务转化为开发逻辑的一种中间过程表示。

持续学习

当开始编写软件时,其实我们所知甚少。项目知识零散地分散在很多人和文档中,其中夹杂着其他一些无关信息,因此我们甚至不知道哪些知识是真正需要的知识。看起来没什么技术难度的领域很可能是一种错觉——我们并没意识到不知道的东西究竟有多少。这种无知往往会导致我们做出错误的假设。

同时,所有项目都会丢失知识。已经学到了一些知识的人可能干别的事去了。团队可能由于重组而被拆散,这导致知识又重新分散开。被外包出去的关键子系统可能只交回了代码,而不会将知识传递回来。而且当使用典型的设计方法时,代码和文档不会以一种有用的形式表示出这些来之不易的知识,因此一旦由于某种原因人们没有口头传递知识,那么知识就丢失了。

个人理解:团队的解散,人员的离职或变更,文档的丢失和散乱,都会使项目组丢失知识,有时候代码写完了但是没有文档或者注释(程序员黑话:先开发产品功能,后写文档,其实就是懒得写),别人接手需要经历非常大的痛苦,然后疯狂吐槽以前的开发人员。这些都可以归于知识的丢失。

高效率的团队需要有意识地积累知识,并持续学习。对于开发人员来说,这意味着既要完善技术知识,也要培养一般的领域建模技巧。但这也包括认真学习他们正在从事的特定领域的知识。那些善于自学的团队成员会成为团队的中坚力量,涉及最关键领域的开发任务要靠他们来攻克,这个核心团队头脑中积累的知识使他们成为更高效的知识消化者。

关键的模型元素被保留下来,早期工作启动了知识消化的过程,这使得所有后续工作更加高效:团队成员、开发人员和领域专家等都学到了知识,他们开始使用一种公共的语言,而且形成了贯穿整个实现过程的反馈闭环。

个人理解:所有人都参与,制定模型,学习知识(业务逻辑或者开发思维或者处理流程等等都是知识),后期团队效率会非常高,就算人员变更,只需要理解开发过程中一起制定的模型就可以了。

知识丰富的设计

当我们的建模不再局限于寻找实体和值对象时,我们才能充分吸取知识,因为业务规则之间可能会存在不一致。领域专家在反复研究所有规则、解决规则之间的矛盾以及以常识来弥补规则的不足等一系列工作中,往往不会意识到他们的思考过程有多么复杂。软件是无法完成这一工作的。正是通过与软件专家紧密协作来消化知识的过程才使得规则得以澄清和充实,并消除规则之间的矛盾以及删除一些无用规则。

个人理解:业务或者产品如果不懂开发,会提出一些天马行空的功能,不会意识到他们的想法实现起来由多复杂。比如:产品经理要程序要开发一个功能,要求app根据手机壳的颜色而改变主题颜色(新闻有报道,产品经理被打了,哈哈哈)。大家一起紧密协作来消化知识,可以消除这些矛盾或者无用的想法。

示例

我们从一个非常简单的领域模型开始学习,基于此模型的应用程序用来预订一艘船在一次航程中要运载的货物

们规定这个应用程序的任务是将每件货物(Cargo)与一次航程(Voyage)关联起来,记录并跟踪这种关系。现在看来一切都还算简单。应用程序代码中可能会有一个像下面这样的方法

由于总会有人在最后一刻取消订单,因此航运业的一般做法是接受比其运载能力多一些的货物。这称为“超订”。有时使用一个简单的容量百分比来表示,如预订110%的载货量。有时则采用复杂的规则——主要客户或特定种类的货物优先。这是航运领域的一个基本策略,从事航运业的业务人员都知道它,但在软件团队中可能不是所有技术人员都知道这条规则。需求文档中包含下面这句话:允许10%的超订。(这个时候由问题了哈)

现在,一条重要的业务规则被隐藏在上面这段方法代码内,非常容易误解,我们主要考虑如何把这条规则更清楚地表达出来,并让项目中的每个人都能了解到它。这将使我们得到一个类似的解决方案。

(1) 如果业务规则如上述代码所写,不可能有业务专家会通过阅读这段代码来检验规则,即使在开发人员的帮助下也无法完成。

(2) 非业务的技术人员很难将需求文本与代码联系起来。如果规则更复杂,情况将更糟。

修改成下面这样:

现在所有人都清楚超订是一个独特的策略,而且超订规则的实现即明确又独立。

现在,我并不建议将这样的精细设计应用到领域的每个细节中。第15章将深入阐述如何关注重点以及如何隔离其他问题或使这些问题最小化。这个例子的目的是说明领域模型和相应的设计可用来保护和共享知识。更明确的设计具有以下优点:

(1) 为了实现更明确的设计,程序员和其他各位相关人员都必须理解超订的本质,明白它是一个明确且重要的业务规则,而不只是一个不起眼的计算。

(2) 程序员可以向业务专家展示技术工件,甚至是代码,但应该是领域专家(在程序员指导下)可以理解的,以便形成反馈闭环。

个人理解:模型要把重要的细节表达出来,不能隐藏的自己知道的认知中(就不告诉别人,说你这样做就行了,这样不好),要体现出为什么是这样的,是什么导致必须要加入这个,要让模型在成为沟通的桥梁时更加明确易懂。

深层模型

有用的模型很少停留在表面。随着对领域和应用程序需求的理解逐步加深,我们往往会丢弃那些最初看起来很重要的表面元素,或者切换它们的角度。这时,一些开始时不可能发现的巧妙抽象就会渐渐浮出水面,而它们恰恰切中问题的要害。

前面的例子大体上是基于一个集装箱航运项目,这是本书列举的几个项目之一,本书还有几个示例会引用这个项目。本书所举的示例都很简单,即使不是航运专家也能理解它们。但在一个需要团队成员持续学习的真实项目中,要想建立实用且清晰的模型则要求团队成员既精通领域知识,也要精通建模技术。

在这个项目中,由于航运从预订货运开始,因此我们开发了一个能够描述货物和运货航线等事物的模型。这是必要且有用的,但领域专家却不买账。他们有自己的考虑业务的方式,这种方式是我们没有考虑到的。

最后,在经过几个月的知识消化后,我们知道货物的处理主要是由转包商或公司中的操作人员完成的,这包括实际的装货、卸货和运货。航运专家的观点是,各部分之间存在一系列的责任传递。法律责任和执行责任的传递由一个过程控制—从托运人传递到某个本地运输商,再从这家运输商传递到另一家运输商,最后到达收货人。通常,在一些重要的步骤中,货物停放在仓库里。在其他时间里,货物则是通过复杂的物理步骤来运输,而这些与航运公司的业务决策无关。在处理航线的物流之前,必须先确定诸如提单等法律文件以及支付流程。

对航运业务有了更深刻的认识后,我们并没有删除Itinerary(航线)对象,但模型发生了巨大改变。我们对航运业务的认识从“集装箱在各个地点之间的运输”转变为“运货责任在各个实体之间的传递”。处理这些责任传递的特性不再是一些附属于装货作业的次要特性,而是由一个独立的模型来提供支持,这个模型正是在理解了作业与责任之间的重要关系之后开发出来的。

知识消化是一种探索,它永无止境。

个人理解:随着对业务的理解更加深刻以后,模型同时也要进行更新,会变得复杂,怎么办?开发容易理解的一种形式是:就相当于sql中做子查询,java开发中就小模块封装,大模块调用函数。模型也是一样,再做一个新模型,对某一部分功能做抽象,由大模型链接过去。例如:a-b-c原来是一个模型,后来增加到a-b-c-c1-c2-c3,c的功能原来越多,这个时候可以做成这样:模型1是a-b-C,模型C(独立小模型):c1-c2-c3。这就是深层模型的理解。

(0)

相关推荐

  • 领域驱动设计资料收集与简单实现(一):什么是领域驱动设计,通用语言

    什么是领域驱动设计 领域驱动设计(DDD):DDD的全称为Domain-driven Design,是一套综合软件系统分析和设计的面向对象建模方法,是针对复杂系统设计的一套软件工程方法,是一种思想. ...

  • 三 领域驱动设计-运用领域模型-绑定模型和实现

    领域驱动设计-运用领域模型-绑定模型和实现 聪明的项目组成员花费了几个月的时间进行仔细的研究并且开发出了详尽的领域模型(类图).然而对类图研究不能让我深入地了解该应用程序的代码和设计,这让我备感困扰. ...

  • 你真的会学习吗?从结构化思维说起

    一  前言 试想,接手一个新的业务方向,业务方的诉求是要求你能快速熟悉并投入,你会如何去应对这样的挑战呢?再试想,作为一名风控技术的新人,你需要在原先的防控策略上引入新的图计算技术,又该如何快速学习新 ...

  • 九章云极DataCanvas方磊:数据科学赋能组织实现未来智能

    一年一度的IDC DX Summit 数字化转型大会聚焦 "数字竞技,转战新常态",邀请各行业领域头部企业创始人和高管发表新见解,九章云极DataCanvas董事长方磊博士站在行业 ...

  • 二 领域驱动设计-运用领域模型-交流与语言的使用

    目录 运用领域模型-交流与语言的使用 书面设计文档 完全依赖可执行代码的情况 UBIQUITOUS LANGUAGE(通用语言) "大声地"建模 一个团队,一种语言 文档和图 解释 ...

  • 如何运用领域驱动设计 - 聚合

    目录 概述 何为聚合 演化案例 发现实体关系 开始划分边界吧 选取一个聚合根 通过聚合根保护你的内部对象 聚合的一些特性 通过ID引用 聚合真的是不变的吗 小的聚合 一致性 总结 概述 在前几篇的博文 ...

  • 如何运用领域驱动设计 - 工作单元

    新年伊始,祝大家喜乐如意,爱和幸福"鼠"不尽!♫. ♪♬.♩♫ 概述 在上一篇 <如何运用领域驱动设计 - 存储库> 的文章中,我们讲述了有关仓储的概念和使用规范.仓储 ...

  • 领域驱动设计适用于军用软件开发吗?

    领域驱动设计这个概念提出已经超过10年. 近些年来,国内已经有一些互联网公司开始试水领域驱动设计.作为军用软件开发来说,领域驱动设计适合吗? 领域驱动设计自其诞生之日起就是为了解决软件的复杂性的.领域 ...

  • 为什么说领域驱动设计可以提升软件的质量水平?

    领域驱动设计是一套方法论,指导我们将复杂问题进行拆分.拆分出各个子系统间的关联以及是如何运转的,帮助我们解决大型的复杂系统在落地中遇到的问题. 在学习领域驱动设计的过程中我越来越感觉到领域驱动设计可以 ...

  • DDD领域驱动设计真就一文不值?

    在互联网快速发展的这几年来,微服务.领域驱动设计等已经非常流行,并成为目前软件开发行业的主流趋势. 大家都知道,微服务划分的一个重要理论基础就是领域驱动设计.但由于 DDD 门槛高.概念多,体系庞大又 ...

  • 深入理解领域驱动设计中的聚合

    聚合模式是 DDD 的模式结构中较为难于理解的一个,也是 DDD 学习曲线中的一个关键障碍.合理地设计聚合,能清晰地表述业务一致性,也更容易带来清晰的实现,设计不合理的聚合,甚至在设计中没有聚合的概念 ...

  • 领域驱动设计(DDD)理论与方法

    DDD由来与优势 软件架构设计的真正目的是解决软件复杂度带来的问题,软件复杂度由来主要由三方面:高并发场景下的对软件高性能要求.业务场景对软件高可用要求.持续变化的业务以及业务扩张和增加需求对软件扩展 ...