领域驱动设计

译者序

相信大家对这本书都不陌生,它已经成为软件设计书中的经典

在网上搜索一下,读者对它 好评如潮,我再多说一句赞美的话都是多余的。而我能想到的也唯有“经典”二字,它堪称经典中的经典。

 

我们对“领域”这个概念都很熟悉,但有多少人真正重视过它呢?软件开发人员几乎总是专注于技术,把技术作为自己能力的展示和成功的度量。而直到Eric Evans出版了他的这部巨著之 后,人们才真正开始关注领域,关注核心领域,关注领域驱动的设计,关注模型驱动的开发。相信在读完本书后,你会对软件设计有全新的认识

 

本书广泛适用于各种领域的软件开发项目。在每个项目的生命周期中,都会有一些重大关头或转折点。如何制定决策,如何把握项目的方向,如何处理和面对各种机会和挑战,将对项 目产生决定性的影响。让我们一起跟随大师的脚步,分享他通过大量项目获得的真知灼见和开发心得吧。

有很多因素会使软件开发复杂化,但最根本的原因是问题领域本身错综复杂。如果你要为一家人员复杂的企业提高自动化程度,那么你开发的软件将无法回避这种复杂性,你所能做的只有控制这种复杂性

 

控制复杂性的关键有一个好的领域模型,这个模型不应该仅仅停留在领域的表面,而是要透过表象抓住领域的实质结构,从而为软件开发人员提供他们所需的支持。好的领域模型价值连城,但要想开发出好的模型也并非易事。精通此道的人并不多,而且这方面的知识也很难传授。

 

本书终于实现了一个宏伟抱负,即描述并建立了领域建模艺术的词汇库。它提供了一个参考框架,人们可以用它来解释相关活动,并用它来传授这门难学的技艺。本书在写作过程中,也带 给我很多新想法,如果哪位概念建模方面的老手没有从阅读本书中获得大量的新思想,那我反而该惊诧莫名了。

 

Eric还对我们多年以来学过的知识进行了归纳总结。首先,在领域建模过程中不应将概念与实现割裂开来。高效的领域建模人员不仅应该能够在白板上与会计师进行讨论,而且还应该能与程序员一道编写Java代码。之所以要具备这些能力,一部分原因是如果不考虑实现问题就无法构建出有用的概念模型。但概念与实现密不可分的最主要原因在于,领域模型的最大价值是它提供 了一种通用语言,这种语言是将领域专家和技术人员联系在一起的纽带。

 

我们将从本书中学到的另一个经验是领域模型不是按照“先建模,后实现”这个次序来工作的。像很多人一样,我也反对“先设计,再构建”这种固定的思维模式。Eric的经验告诉我们, 真正强大的领域模型是随着时间演进的,即使是最有经验的建模人员也往往发现他们是在系统的 初始版本完成之后才有了最好的想法。

前言

本书为作出设计决策提供了一个框架,并且为讨论领域设计提供了一个技术词汇库。本书将人们普遍接受的一些最佳实践综合到一起,并融入了我自己的见解和经验。面对复杂领域的软件开发团队可以利用这个框架来系统性地应用领域驱动设计。

复杂性的挑战

很多因素可能会导致项目偏离轨道,如官僚主义、目标不清、资源缺乏等。但真正决定软件复杂性的是设计方法。当复杂性失去控制时,开发人员就无法很好地理解软件,因此无法轻易、 安全地更改和扩展它。而好的设计则可以为开发复杂特性创造更多机会。

 

领域驱动设计是一种思维方式,也是一组优先任务,它旨在加速那些必须处理复杂领域的软件项目的开发。为了实现这个目标,本书给出了一整套完整的设计实践、技术和原则。

设计过程与开发过程

本书将设计和开发实践结合起来讨论,并阐述领域驱动设计与敏捷开发过程是如何互相增强的。在敏捷开发过程中使用成熟的领域建模方法可以加速开发。过程与领域开发之间的相互关系 使得这种方法比任何“纯粹”真空式的设计更加实用。

本书面向的读者

本书主要是为面向对象软件开发人员编写的。软件项目团队的大部分成员都能够从本书的某 些部分获益。本书最适合那些正在项目上尝试这些实践的人员,以及那些已经在这样的项目上积 累了丰富经验的人员。

 

第一部分 运用领域模型

地图就是模型,而模型被用来描绘人们所关注的现实或想法的某个方面

模型是一种简化。它是对现实的解释——把与解决问题密切相关的方面抽象出来,而忽略无关的细节。

每个软件程序是为了执行用户的某项活动,或是满足用户的某种需求。这些用户应用软件的问题区域就是软件的领域。

 

为了创建真正能为用户活动所用的软件,开发团队必须运用一整套与这些活动有关的知识体系。所需知识的广度可能令人望而生畏,庞大而复杂的信息也可能超乎想象。模型正是解决此类信息超载问题的工具。模型这种知识形式对知识进行了选择性的简化和有意的结构化。适当的模型可以使人理解信息的意义,并专注于问题。

 

领域模型并非某种特殊的图,而是这种图所要传达的思想。它绝不单单是领域专家头脑中的知识,而是对这类知识严格的组织且有选择的抽象。图可以表示和传达一种模型,同样,精心书写的代码或文字也能达到同样的目的。

模型在领域驱动设计中的作用

在领域驱动的设计中,3个基本用途决定了模型的选择

(1) 模型和设计的核心互相影响

  正是模型与实现之间的紧密联系才使模型变得有用,并确保我们在模型中所进行的分析能够转化为最终产品(即一个可运行的程序)。模型与实现之间的这种紧密结合在维护和后续开发期间也会很有用,因为我们可以基于对模型的理解来解释代码。 (参见第3章)

(2) 模型是团队所有成员使用的通用语言的中枢

  由于模型与实现之间的关联,开发人员可以使用该语言来讨论程序。他们可以在无需翻译的情况下与领域专家进行沟通。而且,由于该语言是基于模型的,因此我们可借助自然语言对模型本身进行精化。(参见第2章)

(3) 模型是浓缩的知识

  模型是团队一致认同的领域知识的组织方式和重要元素的区分方式。 透过我们如何选择术语、分解概念以及将概念联系起来,模型记录了我们看待领域的方式。当开发人员和领域专家在将信息组织为模型时,这一共同的语言(模型)能够促使他们高效地协作。 模型与实现之间的紧密结合使来自软件早期版本的经验可以作为反馈应用到建模过程中。(参见 第1章)

软件的核心

软件的核心是其为用户解决领域相关的问题的能力。所有其他特性,不管有多么重要,都要 服务于这个基本目的。当领域很复杂时,这是一项艰巨的任务,要求高水平技术人员的共同努力。 开发人员必须钻研领域以获取业务知识。他们必须磨砺其建模技巧,并精通领域设计。

 

开发人员可以采用一些系统性的思考方法来透彻地理解领域并开发出有效的模型。还有一些设计技巧可以使毫无头绪的软件应用变得井井有条。掌握这些技能可以令开发人员的价值倍增, 即使是在一个最初不熟悉的领域中也是如此。 

第一章 消化知识

1.1 有效建模的要素

以下几方面因素促使上述案例得以成功。

(1) 模型和实现的绑定。

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

(2) 建立了一种基于模型的语言。

  最初,工程师们不得不向我解释基本的PCB问题,而我也 必须向他们解释类图的含义。但随着项目的进展,双方都能够直接使用模型中的术语,并将它们 组织为符合模型结构的语句,而且无需翻译即可理解互相要表达的意思。

(3) 开发一个蕴含丰富知识的模型。

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

(4) 提炼模型。

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

(5) 头脑风暴和实验。

  语言和草图,再加上头脑风暴活动,将我们的讨论变成“模型实验室”, 在这些讨论中可以演示、尝试和判断上百种变化。当团队走查场景时,口头表达本身就可以作为 所提议的模型的可行性测试,因为人们听到口头表达后,就能立即分辨出它是表达得清楚、简捷, 还是表达得很笨拙。 正是头脑风暴和大量实验的创造力才使我们找到了一个富含知识的模型并对它进行提炼,在 这个过程中,基于模型的语言提供了很大帮助,而且贯穿整个实现过程中的反馈闭环也对模型起 到了“训练”作用。这种知识消化将团队的知识转化为有价值的模型。

1.2 知识消化

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

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

 

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

 

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

 

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

 

模型永远都不会是完美的,因为它是一个不断演化完善的过程。模型对理解领域必须是切实可用的。它们必须非常精确,以便使应用程序易于实现和理解。

1.3 持续学习

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

高效率的团队需要有意识地积累知识,并持续学习[Kerievsky 2003]。对于开发人员来说,这意味着既要完善技术知识,也要培养一般的领域建模技巧(如本书中所讲的那些技巧)。但这也包括认真学习他们正在从事的特定领域的知识。

1.4 知识丰富的设计

通过像PCB示例这样的模型获得的知识远远不只是“发现名词”。业务活动和规则如同所涉及的实体一样,都是领域的核心,任何领域都有各种类别的概念。知识消化所产生的模型能够反 映出对知识的深层理解。在模型发生改变的同时,开发人员对实现进行重构,以便反映出模型的 变化,这样,新知识就被合并到应用程序中了。

1.5 深层模型

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

 

第2章 交流与语言的使用

领域模型可成为软件项目通用语言的核心。该模型是一组得自于项目人员头脑中的概念,以及反映了领域深层含义的术语和关系。这些术语和相互关系提供了模型语言的语义,虽然语言是为领域量身定制的,但就技术开发而言,其依然足够精确。正是这条至关重要 的纽带,将模型与开发活动结合在一起,并使模型与代码紧密绑定。

2.1 模式:通用语言

要想创建一种灵活的、蕴含丰富知识的设计,需要一种通用的、共享的团队语言,以及对语 言不断的试验——然而,软件项目上很少出现这样的试验。

通过团队的一致努力,领域模型可以成为这种公共语言的核心,同时将团队沟通与软件实现紧密联系到一起。该语言将存在于团队工作中的方方面面。

开发人员应该使用基于模型的语言来描述系统中的工件、任务和功能。这个模型应该为开发 人员和领域专家提供一种用于相互交流的语言,而且领域专家还应该使用这种语言来讨论需求、 开发计划和特性。语言使用得越普遍,理解进行得就越顺畅。

2.3 一个团队,一种语言

有了UBIQUITOUS LANGUAGE之后,开发人员之间的对话、领域专家之间的讨论以及代码本身所表达的内容都基于同一种语言,都来自于一个共享的领域模型。

2.4 文档和图

每当我参加讨论软件设计的会议时,如果不在白板或画板上画图,我就很难讨论下去。我画 的大部分是UML图,主要以类图和对象交互图为主

 UML图无法 传达模型的两个最重要的方面,一个方面是模型所表示的概念的意义,另一方面是对象应该做哪些事情

图是一种沟通和解释手段,它们可以促进头脑风暴。简洁的小图能够很好地实现这些目标,而涵盖整个对象模型的综合性大图反而失去了沟通或解释能力.

务必要记住模型不是图。图的目的是帮助表达和解释模型

2.5 解释性模型

本书的核心思想是在实现、设计和团队交流使用同一个模型作为基础

为了学习领域,还可以引入其他视图,这些视图只用作传递一般领域知识的教学工具。出于此 目的,人们可以使用与软件设计无关的其他种类模型的图片或文字。

解释性模型提供了一定的自由度,可以专门为某个特殊主题定制一些表达力更强的风格。

解释性模型不必是对象模型,而且最好不是。

第3章 绑定模型和实现

由于模型是“正确的”,这是经过技术分析人员和业务专家大量协作才得到的结果,因此开 发人员得出这样的结论:无法把基于概念的对象作为设计的基础。于是他们开始进行专门针对程 序开发的设计。他们的设计确实用了一些原有模型中类和属性的名称进行数据存储,但这种设计 并不是建立在任何已有模型的基础上的。

这个项目虽然建立了领域模型,但是如果模型不能直接帮助开发可运行的软件,那么这种纸上谈兵的模型又有什么意义呢?

3.1 模式:模型驱动设计

那些压根儿就没有领域模型的项目,仅仅通过编写代码来实现一个又一个的功能,它们 无法利用前两章所讨论的知识消化和沟通所带来的好处。如果涉及复杂的领域就会使项目举 步维艰。

另一方面,许多复杂项目确实在尝试使用某种形式的领域模型,但是并没有把代码的编写与模型紧密联系起来。这些项目所设计的模型,在项目初期还可能用来做一些探索工作,但是随着项目的进展,这些模型与项目渐行渐远,甚至还会起误导作用。所有在模型上花费的精力都无法保证程序设计的正确性,因为模型和设计是不同的

如果整个程序设计或者其核心部分没有与领域模型相对应,那么这个模型就是没有价值的,软件的正确性也值得怀疑。同时,模型和设计功能之间过于复杂的对应关系也是难于理解的,在 实际项目中,当设计改变时也无法维护这种关系。若分析与和设计之间产生严重分歧,那么在分 析和设计活动中所获得的知识就无法彼此共享。

(模型驱动设计)不再将分析模型和程序设计分离开,而是寻求一种能够满足这两方面需求的单一模型。不考虑纯粹的技术问题,程序设计中的每个对象都反映了模 型中所描述的相应概念。这就要求我们以更高的标准来选择模型,因为它必须同时满足两种完全 不同的目标。

要想创建出能够抓住主要问题并且帮助程序设计的单一模型并没有说的那么容易。我们不可能随手抓个模型就把它转化成可使用的设计。只有经过精心设计的模型才能促成切实可行的实现。想要使代码有效地描述模型就需要用到程序设计和实现的技巧(参见第二部分)。知识消化人员需要研究模型的各个选项,并将它们细化为实用的软件元素。软件开发于是就成了一个不断精化模型、设计和代码的统一的迭代过程(参见第三部分)。

3.2 建模范式和工具支持

为了使MODEL-DRIVEN DESIGN发挥作用,一定要在可控范围内严格保证模型与设计之间的一致性。要实现这种严格的一致性,必须要运用由软件工具支持的建模范式,它可以在程序中直接创建模型中的对应概念。

面向对象设计是目前大多数项目所使用的建模范式,也是本书中使用的主要方法

3.3 揭示主旨:为什么模型对用户至关重要

如果程序设计基于一个能够反映出用户和领域专家所关心的基本问题的模型,那么与其他设计方式相比,这种设计可以将其主旨更明确地展示给用户。让用户了解模型,将使他们有更多机 会挖掘软件的潜能,也能使软件的行为合乎情理、前后一致。

3.4 模式:HANDS-ON MODELER(亲身实践的建模者)

人们总是把软件开发比喻成制造业。这个比喻的一个推论是:经验丰富的工程师做设计工作, 而技能水平较低的劳动力负责组装产品。这种做法使许多项目陷入困境,原因很简单——软件开发就是设计。虽然开发团队中的每个成员都有自己的职责,但是将分析、建模、设计和编程工作过度分离会对MODEL-DRIVEN DESIGN产生不良影响。

在MODEL-DRIVEN DESIGN中,代码是模型的表达,改变某段代码就改变了相应的模型程序员就是建模人员,无论他们是否喜欢。所以在开始项目时,应该让程序员完成出色的建模工作。

 

posted on 2024-06-17 17:23  anpeiyong  阅读(9)  评论(0编辑  收藏  举报

导航