战略设计部分:发掘核心领域业务

目录

        业务问题(Business Problem)

        知识挖掘(Knowledge Discovery )

        沟通(Communication )

        什么是统一语言?

      业务语言       

        场景

        一致性

        业务领域的模型(Model)

        什么是模型?

        有效建模

        业务领域建模

        持续努力

        工具

        挑战

         总结


目前生产上运行的功能,都是基于研发人员理解实现的,并不是核心领域专家所理解的业务知识。

It’s developers’ (mis)understanding, not domain experts’ knowledge, that gets released in
production.
        —Alberto Brandolini

基于前面一章节的学习,现在我们开始探索业务领域。我们已经学会了如何识别一个公司的核心业务以及相关的业务流程,并分析出该业务范围的边界以及业务领域类型。

        本章节的主题是更深层次的分析业务领域。该章节将聚焦到子领域内部运行情况(该领域包含了什么样的业务功能和逻辑)。我们讲学会运用一种领域驱动设计工具,帮助我们更有效的沟通和分享业务知识,它就是统一语言(the ubiquitous language)。在这里我们将用它来了解复杂的业务领域知识。本书后面我们将在软件开发中用它来建模和实现业务逻辑。

        业务问题(Business Problem)

        我们正在建造的软件系统通常是解决业务问题。在这种情况下,"problem"并不是字面意思,像是解一道数学题或者一道谜语题一样简单。在业务领域的上下文中,"problem"存在更广泛的定义。一个业务问题通常会面临优化业务工作流程、减少人工成本、资源管理优化、决策支撑、数据管理等各种方面的挑战。

            业务领域和子域都会出现业务问题。一个公司的目标是为客户服务所遇到的问题提供解决方案的,比如前面一个章节的例子 ,德邦物流,它的客户需要在有限的时间内运送包裹,那么它就通过优化运送流程达到目的。子领域则是更细粒度的业务问题域,它的目标是为特殊的业务功能提供解决方案。一个知识库子领域核心是优化存储和检索信息的过程。一个清算子领域目的是优化金融交易的执行过程。一个账单子域核心是追踪公司资金流动。

        知识挖掘(Knowledge Discovery

         为了设计一个有效的软件解决方案,我们必须至少掌握业务领域的基本知识。正如我们在第一章中所讨论的,这个知识或者技能属于领域专家:他们的工作是专门研究和理解业务领域的所有复杂之处。我们(软件技术从业者)绝不应该也不可能成为领域专家(专业、岗位、经验影响)。所以理解领域专家并使用他们使用的相同业务术语对我们来说是至关重要的。

        为了解决方案足够有效,软件必须模仿领域专家们思考问题的方式,也就是了解他们的心智模式。如果不理解业务问题和需求背后的原因,我们的解决方案将局限于将业务需求“翻译”成源代码。如果需求错过了一个关键的边界定义会怎样?或者未能描述业务概念,从而限制了我们实现需求可扩展的能力?

        正如Alberto Brandolini所说,软件开发是一个学习的过程;工作编写代码只是帮忙作用。软件项目的成功取决于领域专家和软件工程师之间知识共享的有效性。我们必须先了解这个问题然后才能解决问题。

        领域专家和软件工程师之间有效的知识共享需要有效的沟通。让我们看看软件项目中有效沟通的常见障碍。        

        沟通(Communication

        可以肯定地说,几乎所有的软件项目都需要不同角色的利益相关者的合作:领域专家、产品所有者、工程师、UI和UX设计、开发人员、项目经理、测试人员、分析人员和其他人。无论是什么合作,结果都取决于各方合作得有多好。例如,是否所有涉众都同意要解决什么问题?他们正在构建的解决方案是怎样的——他们对其功能性和非功能性需求是否有相互矛盾的假设?在所有与项目相关的事项上达成一致是项目成功的关键。

        对软件项目失败原因的研究表明,有效的沟通对于知识共享和项目成功至关重要。然而,尽管有效沟通很重要,但在软件项目落地过程中却很少关注到它。通常情况下,业务人员和软件工程师之间没有直接的互动。相反,领域知识从领域专家下推到工程师。它是通过扮演调解人(或“翻译人员”)、系统/业务分析师、产品所有者和项目经理的角色来交付的。这种常见的知识传递流程如下图所示。        

战略设计部分:发掘核心领域业务_第1张图片 软件项目中的业务知识传递流程

        在传统的软件开发生命周期中,领域知识被“翻译”成工程师更容易理解的形式,称为分析模型,但这是对系统需求的描述,而不是对背后的业务领域的理解。 虽然意图可能是好的,但这种中介对知识共享是有害的。在任何一次翻译中,信息都会丢失;在这种情况下,对于解决业务问题至关重要的领域知识在流向软件工程师的过程中丢失了。这种信息翻译不是只存在于典型的软件项目中。业务分析模型被翻译成软件设计模型(一个软件设计文档,它被翻译成实现模型或源代码本身)。正如经常发生的那样,文件很快就会过时。项目维护后期软件工程师只能用源代码进行业务领域知识的共享。下图说明了在代码中实现领域知识所需的不同形式的转换。

     

战略设计部分:发掘核心领域业务_第2张图片 模型转换形式

         这样的软件开发过程类似于儿童做游戏打电话里面的信息,或领域知识,经常被扭曲。这些信息导致软件工程师执行了错误的解决方案,或者正确的解决方案却出现了错误的问题。无论哪种情况,结果都是一样的:一个失败的软件项目。

        领域驱动设计提出了一种从领域专家向软件工程师获取知识的更好方法:统一语言(ubiquitous language)。

        什么是统一语言?

        使用通用语言是领域驱动设计的基础实践。这个想法简单而直接:如果各方需要有效沟通,而不是依赖信息翻译,他们必须使用同一种语言。 

        尽管这个概念是常识的边缘,正如伏尔泰所说,“常识并不是那么普遍。”,传统的软件开发生命周期会经历以下过程的翻译:

  • 将领域知识转化为分析模型
  • 将分析模型转化为需求 
  • 将需求转化为系统设计     
  • 将系统设计转化为源代码               

        领域驱动设计要求使用一种描述业务领域的单一语言:统一语言,而不是不断地翻译领域知识。所有与项目相关的涉众——软件工程师、产品所有者、领域专家、UI/UX设计师,在描述业务领域时都应该使用业务领域内的统一语言。最重要的是,领域专家在对业务领域进行推理时,必须能够自如地使用统一;这种语言将代表业务领域和领域专家的思维模型。

        只有通过持续使用统一语言及其术语,才能培养项目所有涉众之间的共同理解。        

      业务语言       

        这里必须强调一点,统一语言是业务语言。因此,它应该只包含与业务领域相关的术语。没有技术术语!向业务领域专家教授单例和抽象工厂则不是你的目标。统一语言旨在用易于理解的术语构建领域专家对业务领域的理解和思维模型。

        场景

        假设我们正在开发一个广告活动管理系统。考虑以下陈述:        

  • 广告活动可以展示不同的创意材料。
  • 一个活动只有在至少一个位置是活跃的情况下才能被发布。
  • 销售佣金在交易被批准后入账。

        所有这些语句都是用业务语言表述的。也就是说,它们反映了领域专家对业务领域的看法。

        另一方面,下列陈述是严格的技术性的,因此不适合统一语言的概念:

  • 广告iframe显示一个HTML文件。
  • active-placements表中至少有一个相关记录的活动才可以发布。

  • 销售佣金是基于相关的交易记录 和交易审批(approved-sales)表中的记录。

        后面这些陈述纯粹是技术性的,对领域专家来说是不清楚的。

        假设工程师只熟悉业务领域的这种技术的、面向解决方案的视图。在这种情况下,他们将无法完全理解业务逻辑或业务逻辑为何以这种方式运行,这将限制他们建模和实现有效解决方案的能力。

        一致性

        统一语言必须是精确和一致的。它应该消除假设的、含糊的需要,并且应该使业务域的逻辑清晰展示出来。由于歧义阻碍了交流,所以统一语言中的每个术语都应该有且只有一个意思。让我们来看几个术语不清楚的例子,以及如何改进它。

        模棱两可的条款

        假设在某些业务领域中,术语“策略”有多种含义:它可以指规则或契约。具体的含义可以在人与人之间的互动中根据上下文来确定。然而,软件不能很好地处理模糊性,而且在代码中建模“策略”实体可能很麻烦且具有挑战性。

        统一语言要求每个术语都有一个单一的含义,因此“策略”应该使用规则或契约这两个术语进行显式建模。

        同义术语

        在统一语言中,两个术语不能互换使用。例如,许多系统使用术语user。然而,仔细研究领域专家的术语可能会发现,user和其他术语是互换使用的:例如,user、user, visitor, administrator, account等。

        一开始,同义词似乎是无害的。然而,在大多数情况下,它们表示不同的概念。在这个例子中,“visitor”和“account”在技术上都是指系统的用户;然而,在大多数系统中,未注册用户和已注册用户代表不同的角色,具有不同的行为。例如,“visitor”数据主要用于分析目的,而“account”实际上使用的是系统及其功能。

        最好在特定的上下文中明确地使用每个术语。理解使用术语之间的差异,可以构建更简单、更清晰的业务域实体模型帮助落地实现。

        业务领域的模型(Model)


        现在让我们从一个不同的角度来看这种统一语言的使用:建模。

        什么是模型?

模型是对事物或现象的简化表示,它有意强调某些方面而忽略其他方面。有特定用途的抽象概念。

A model is a simplified representation of a thing or phenomenon that intentionally emphasi‐
zes certain aspects while ignoring others. Abstraction with a specific use in mind.
—Rebecca Wirfs-Brock

        模型不是真实世界的复制,而是帮助我们理解真实世界系统的人类构造。 

        模型的一个规范示例是地图。任何地图都是模型,包括导航地图、地形图、世界地图、地铁地图等,如图所示。        

不同类型的地图显示不同的地球模型:道路、时区、航海导航、地形、航空导航和地铁线路。

 这些地图没有一个能代表我们星球的所有细节。相反,每张地图只包含足够的数据来支持它的特定目的:解决它特殊需求的问题。

        有效建模

        所有模型都有一个目标问题要解决,而有效的模型只实现包含其目标范围内的所需的细节。例如,你不会在世界地图上看到地铁站。另一方面,您不能使用地铁地图来估计距离。每张地图只包含它领域内应该提供的信息。

        再强调一点:一个有效的模型不是真实世界的复制。相反,模型的目的是解决问题,它应该为该目的提供足够的信息。或者,正如统计学家George Box所说:“所有的模型都是错误的,但有些是有用的。”

        从本质上讲,模型是一种抽象。抽象概念允许我们通过省略不必要的细节,只专注解决当前核心问题的复杂性。另一方面,无效的抽象会删除必要的信息或者留下不需要的信息来制造干扰。正如Edsger W. Dijkstra在他的论文《卑微的程序员》中所指出的那样,抽象的目的不是模糊,而是创建一个新的语义级别,在这个级别中可以做到绝对精确。

        业务领域建模

        在开始使用统一语言时,我们正在有效地构建业务领域的模型。业务领域模型应该捕获领域专家的思维模型——关于业务如何运行,以实现其功能。模型必须反映所涉及的业务实体及其行为、因果关系和不变量。

        我们使用的统一语言不应该涵盖该领域的所有可能的细节。这相当于让每个涉众都成为领域专家。相反,模型应该只包含业务领域方面足够的内容,尽可能的实现系统需求;也就是说,解决软件想要解决的特定问题。在接下来的章节中,您将看到统一语言如何驱动低层设计和实现策略。

        工程团队和领域专家之间的有效沟通是至关重要的。这种沟通的重要性随着业务领域的复杂性而增加。业务领域越复杂,在代码中建模和实现其业务逻辑就越困难。即使是对复杂业务领域或其基本原则的轻微误解,也会无意中导致实现容易出现严重的错误。验证业务领域理解的唯一可靠方法是与领域专家进行交流,并用他们理解的语言进行交流:业务语言。

        持续努力

        统一语言的制定需要与它的自然持有者,即领域专家进行交流。只有与实际领域专家的交流才能发现不准确的、错误的假设,或者对业务领域有全面缺陷的理解。

        所有涉众应在所有与项目相关的沟通中始终使用统一语言,以传播业务领域有关的知识并促进对项目的共同理解。这种语言应该在整个项目中不断强化:需求、测试、文档,甚至源代码本身都应该使用统一语言。

        最重要的是,培养使用统一语言的习惯是一个持续的过程。它应该不断地得到验证和发展。随着时间的推移,统一语言的日常使用将挖掘出对业务领域更深层次的见解。当这种突破发生时,统一语言必须进化以跟上新获得的领域知识。

        工具

        通过一些工具可以帮忙我们轻松将统一语言落地。比如我们可以通过wiki记录统一语言的术语表格。这样的术语表减轻了新团队成员的入职后的学习过程,因为它是获取业务领域术语信息的首选场所。

        大家共同努力维护术语表,这一点很重要。当统一语言发生更改时,应该鼓励所有团队成员继续更新术语表。这与集中式管理方法相反,在集中式管理中,只有团队领导或架构师负责维护术语表。

        尽管维护与项目相关的术语表有明显的优势,但它也有固有的局限性。词汇表最适用于“名词”:实体名称、流程名称、角色名称等。虽然名词很重要,但分析出其行为是至关重要的。行为不仅仅是与名词相关的动词的列表,而是实际的业务逻辑,以及它的规则、职责和不变量。这样的概念在术语表中很难记录。因此,术语表最好与其他更适合捕捉行为的工具一起使用;例如,用例或Gherkin测试。

        用Gherkin语言编写的自动化测试不仅是捕获统一语言的好工具,而且是弥合领域专家和软件工程师之间理解偏差的好工具。领域专家可以阅读测试并验证系统的预期行为。例如,查看以下用Gherkin语言编写的测试case:

        

Feature:  Login functionality of social networking site Facebook. 
Given:  I am a facebook user. 
When: I enter username as username. 
And I enter the password as the password 
Then I should be redirected to the home page of facebook 

        Gherkin语言几个关键词如下图:

        战略设计部分:发掘核心领域业务_第3张图片

        管理一个基于gherkin的测试套件有时是具有挑战性的,特别是在项目的早期阶段。但是,对于复杂的业务领域,这绝对是值得的。最后,甚至还有静态代码分析工具可以验证统一语言术语的使用情况。比如NDepend。

        虽然这些工具很有用,但它们在日常工作交流中对于统一语言的实际使用起到的作用是次要的。使用工具来支持统一语言专业术语的管理,但不要期望文档能取代实际的用法。正如敏捷软件开发宣言所说,“个体和互动高于流程和工具。”

        挑战

        从理论上讲,使用统一语言听起来是一个简单、直接的过程。但实际上并非如此。收集领域知识的唯一可靠方法是与领域专家交谈。通常,最重要的知识是隐性的。它没有被记录或编纂,只存在于领域专家的头脑中。唯一能接触到它的方法就是提问。

        当您在这个实践过程中获取了一些经验时,您会发现这个过程不仅仅涉及发现已经存在的知识,而是与领域专家一起共同创建模型。在领域专家自己对业务领域的理解中可能存在歧义甚至盲区;例如,只定义“主逻辑”场景,而不考虑和接受推理中存在的的边缘情况。此外,您可能会遇到业务领域概念缺乏显示的定义,更有价值的信息被隐藏起来。针对业务领域内容,提出问题,通常会使这种隐性的冲突和盲区变得明显。这对于核心子域尤其常见。在这种情况下,学习流程是相互的—您也正在帮助领域专家更好地理解他们的领域。

        当将领域驱动的设计实践引入到自己负责项目中时,您会注意到该项目的利益相关者已经有一套描述业务领域知识点的术语。然而,由于DDD设计原则与该语言水土不服,因此它不一定能有效地反映业务领域。例如,它可能使用技术术语,如数据库表名。改变组织中已经在使用的语言并不容易。在这种情况下,最重要的工具就是耐心。您需要确保在容易控制的地方使用了正确的语言,比如在文档和源代码中。最后,如果公司内员工使用不同语种情况下,我们应该怎么使用统一语言。我的建议是至少使用英文名词来命名业务域的实体。这将减少在代码中出现同义术语。

         总结

        有效的沟通和知识共享对于一个成功的软件项目是至关重要的 ,为了设计和构建软件解决方案,软件工程师必须了解业务领域知识。

        领域驱动设计的统一语言是弥合领域专家和软件工程师之间知识鸿沟的有效工具。它通过培养一种所有人都能使用的统一语言来促进交流和知识共享,涉及到整个项目周期:在业务交流、文档、测试、报表、源代码中等等。

        为了保证有效的沟通,统一语言必须消除歧义和隐含的假设。一种语言的所有术语必须是一致的——没有含糊的术语,也没有同义的术语。

        养成习惯使用统一语言是一个持续的过程。随着项目的发展,将会发现更多的领域知识。重要的是,这样的新发现需要统一语言中得到反馈。

        诸如基于wiki的词汇表和Gherkin测试之类的工具可以大大减轻编写文档和维护统一语言的过程。然而,一种有效的统一语言的主要前提是使用:该语言必须在所有与项目相关的交流中一致使用。

        

      

        

你可能感兴趣的:(领域驱动,分布式,设计模式,重构)