作者|仲景阅读本系列文章:《??DDD的哲学:模型的关联、演进和认知??》核心领域与主要矛盾大约在公元前800年到公元前200年之间,中国、希腊、印度、以色列的文明几乎是同一时期的崛起,被称为人类的轴心时代文明。不同的文明展现出不同的风采。中国古代文化强调辩证逻辑,重视变化、联系和综合的思维方式。同时,它还具有“无言异能神,天地外无物”的唯物主义倾向。古希腊注重严格的推理和分析,诞生了形式逻辑和公理化的数学体系。印度将辩证法、逻辑学和语言学推向了另一个方向的极端,即婆罗门和佛教哲学。以色列的先知们创造了一神论的犹太教和神权政治的社会制度。直到近代,西方才产生了系统的辩证法体系,黑格尔才是大师。马克思、恩格斯吸收了黑格尔的辩证法,摒弃了它的唯心主义成分,形成了辩证唯物主义,成为风起云涌的无产阶级革命的理论基础。后来,唯物辩证法传入中国,与中国传统文化中的辩证法、唯物主义一拍即合。为了把马克思主义中国化,毛老师写了《实践论》和《矛盾论》。《矛盾论》的第一部《宇宙的两种观点》上面已经说过了。本节我们来看第四部分“主要矛盾和矛盾的主要方面”。事物的矛盾有很多种,它们的发展变化成为事物发展的内在动力。在各种矛盾中,通常有一种矛盾占主导地位,称为“主要矛盾”。有效解决问题,必须抓住主要矛盾。例如,一家准备开业的保险公司需要开发保险核心系统。一开始,“需要快速开展新业务与处理新订单能力落后”的矛盾是主要矛盾,而“需要快速理赔与理赔能力落后”的矛盾是次要矛盾。这是因为新开业的保险公司首先面临的是新单业务的压力,而不是理赔的压力。在领域驱动设计中,领域模型包含了主要的矛盾部分,称为“核心领域”(CoreDomain)。在复杂领域模型中,识别并有效处理核心领域的过程称为“精炼”(Distillation,《领域驱动设计》第15章)。领域驱动设计还提供了“DomainVisionStatement”、“HighlightedCore”、“SegregatedCore”等模式,用于提炼过程的具体实践。随着内外因素的变化,主要矛盾和次要矛盾会发生转化。例如,新订单处理制度成熟后,成为次要矛盾,理赔成为主要矛盾。当索赔也成熟时,灵活的产品和算法的定义可能成为主要矛盾。总之,从矛盾的角度看问题,才能知道识别和应对“核心域”的必要性,同时从发展的角度看待核心域的转型。这里还有一个微妙的问题:业内不同人所指的“核心域”的含义是不一样的。如果我们把业务需求看成是“问题空间”,把软件系统的分析和设计看成是“解决空间”,那么本书中提到的核心领域《领域驱动设计》实际上就在解决空间,而另一本书《实现领域驱动设计》say的核心领域是问题空间。《领域驱动设计》,核心域在“求精”一章。其逻辑是,先有领域模型,然后当领域模型发展到一定的复杂程度时,需要从中“提炼”出核心领域。由于域模型在解空间中,所以《领域驱动设计》中的“核心域”讲的是解空间。《实现领域驱动设计》中的核心领域来自于业务问题的分解,属于问题空间,先于领域模型的建立。两级“核心域”的存在具有一定的合理性。因为矛盾无处不在,无论是在问题空间还是在解空间,都存在“主要矛盾”,所以可以说在两个层次上都有核心域。目前大多数人理解的核心领域是《实现领域驱动设计》中的语句,而没有关注《领域驱动设计》原著中的模式和做法。领域驱动设计本来是需要“统一语言”的,但是“核心领域”这个概念本身已经不统一了。这是行业需要解决的问题。在下一节中,我们将研究与统一语言相关的问题。“语言转向”统一语言与哲学上一节介绍了哲学从本体论到方法论的转变。在方法论上,洛克、休谟、帕斯卡等犹如哲学天空中的星星,黑格尔和康德是其中最亮的两颗。然而,新的问题出现了。这些哲学家的著作中往往充斥着晦涩难懂的词汇,其中很多都是自创的,在此基础上进行复杂的推演,进而产生更加晦涩难懂的语言。这些不一致的概念,后人根据各自的意思,做出了不同的解释。其后果是,不仅普通人难以一窥究竟,就连职业哲学家也会争论不休。尽管产生了大量的论文和“学术成果”,但人们逐渐意识到,大部分辩论只是关于对同一术语的不同理解,而不是解决任何实际问题。这样的哲学除了在象牙塔里自我陶醉之外,还有多少现实意义呢?到十九世纪末,人们逐渐意识到问题可能出在“语言”上,许多哲学问题都源于语言的误用。解决语言问题,解决哲学问题。由此产生了“语言哲学”,成为20世纪上半叶英美哲学的主流。如果认识论是“关于思的思”,那么语言哲学就是“关于说的说”。虽然历史上很多哲学家也很重视语言,但当时语言只是研究哲学的工具;现在,语言已经成为哲学本身。这种哲学重心的转变被称为“哲学的语言学转向”。信息技术与语言有着不解之缘。当你刚开始学习编程,知道指挥计算机工作的指令被称为计算机“语言”时,你有没有像我一开始一样惊讶?领域驱动设计中与语言直接相关的模式是“无处不在的语言”。该模式出现在《领域驱动设计》的第二章,属于《UsingDomainModels》这本书的第一部分,与《消化知识》和《模型驱动设计》一起构成了本书的大纲。“统一语言”要求业务和开发者使用一致的语言进行交流。例如,同一个概念应该使用同一个词汇,同一个词汇只能表达一个独特的概念。这个道理这么“直白”,为什么要特别强调领域驱动设计呢?因为这种做法看似不难理解,但真正要在实践中做好却不是那么容易。让我们从语言哲学的角度来看一下软件开发中与语言相关的问题。首先,语言哲学认为语言的意义体现在使用语言的过程中。上述早期哲学家的语言是为了表达自己的思想而自创的,并没有真正用于解决实际问题,因此他们没有“恰当地”使用语言,从而产生了新的哲学问题。回到软件开发,如果对软件的理解只是写在文档中,而这些文档很少阅读,并没有真正起到交流的作用,那也算是一种语言的误用。这正是敏捷软件开发所反对的。统一的语言强调不同利益相关者之间的沟通,尤其是业务人员和开发人员之间的沟通。共同语言只有在协作中才有意义。近几年流行的“事件风暴”方式也可以看作是统一语言的应用。事件风暴和经典用例分析方法解决的问题其实很相似,都是为了捕捉行为需求,为进一步的领域建模打下基础。事件风暴中的“风暴”来源于头脑风暴,这是一种常见的沟通协作方式。因此,沟通和协作是事件风暴的内在组成部分,这也是事件风暴优于传统用例分析的地方。其次,语言哲学强调语言的表达能力是有限的。正如维特根斯坦所说,“能说的,就说清楚;不能说的,就保持沉默。”前面提到的早期哲学家的另一个问题是强迫文字表达无法表达的东西。领域驱动设计认为,软件开发的过程可以看作是学习、构建和应用知识的过程。而有些知识是难以用语言表达的。然而,难以表达并不意味着不可知。例如,我们很难向没有吃过梨的人描述梨的味道,但这并不意味着梨的味道不可知,只要尝一尝就可以了。软件开发中难言的知识同样不是玄学,而是可以通过不断的交流和实践来掌握的。因此,不要指望所有的知识都通过文档来表达,而是回归到利益相关者之间的沟通和协作。第三,语言哲学认为语言只有在特定的语境(Context)中才有意义。上文提到,领域驱动设计使用限界上下文(BoundedContext)来保证概念的一致性。统一语言是针对有界上下文的,只有在它所在的上下文中才有意义。英文Context在中文中有两种译法:“语境”和“语境”。目前,《领域驱动设计》一书中采用的是“context”的翻译方式。其实翻译成“语境”可能更合适。如果把“语”用在“语境”上,意思就更和谐了。最后,语言哲学可以分为两个流派:早期的“理想语言学派”和后来的“日常语言学派”。理想语言派认为自然语言是模糊的,哲学的出路是用数理逻辑创造形式化的语言。这种语言不仅意义明确,而且可以跨越各种自然语言。这后来导致了计算机科学基础理论“形式语言与自动机”的创立。这个过程可以追溯到17、18世纪,当时莱布尼茨发明了二进制,并提出了“通用书写”(characteristicauniversalis)的概念。到十九世纪,布尔使用二进制使逻辑成为数学演算。时至今日,布尔代数仍然是计算机科学的基础。后来,现代逻辑之父弗雷格提出了一阶谓词演算。这一理论也导致了像Prolog这样的逻辑编程语言的诞生。20世纪,罗素、哥德尔等人进一步发展了数理逻辑。后来,图灵提出的“图灵机”和丘奇提出的λ演算成为算法和编程语言的数学基础。我们程序员使用的各种编程语言也可以算作形式化语言。后一派认为,自然语言天生就是精确的,之所以让人感到模糊,是因为它没有进入特定的语境。因此,应该通过研究自然语言本身来解决哲学问题,而不是求助于形式语言。这就是“日常语言学校”。对于软件开发者来说,没有必要陷入哲学家的争论中。相反,我们可以看到两者各自的合理性,以及相互联系的可能性。一方面,在计算机中运行的是二进制字节流,它又是由编程语言编译而来。机器语言和编程语言都是形式语言。另一方面,计算机要解决的业务问题,都是从日常语言或自然语言的描述开始的。因此,我们必须有自然语言和形式语言之间的转换机制。领域驱动设计中的领域建模是该机制的重要组成部分。领域模型在自然语言和程序设计语言之间架起了一座桥梁,有助于弥合两者之间的巨大鸿沟,成为开发复杂软件的重要手段。在领域驱动设计中,UML(UnifiedModelingLanguage)通常用于领域建模。严格来说,UML也是一种形式语言。但是,与编程语言相比,UML更接近于业务概念,更容易与自然语言进行转换。同时,用UML建立的领域模型可以方便地映射到编程语言和数据库设计中。UML常用于软件系统的分析和设计,而编程语言则用于编码。在分析、设计、编码过程中保持语言的统一性,是统一语言的另一层含义。总结我们在几章中探讨了领域驱动设计的哲学含义。两人的这种契合绝非偶然。哲学的主要目的是解决认识(认识论)和解释(语言哲学)世界的问题。上面提到的本体论,也可以理解为对当下世界的一种解释。计算机系统本质上是利用硬件和软件来模拟真实的事物和逻辑,进而解决真实的问题。计算机软件可以被认为是现实世界的模型。计算机中最终运行的模型是二进制流,在形式上与现实世界存在巨大差距,这是软件开发的本质复杂性之一。为了弥合现实世界和二进制模型之间的差距,软件开发方法采用增量方法。首先将现实世界映射为分析模型,然后将分析模型映射为设计模型,再映射为编程语言模型,最后编译成二进制模型。通过这种层层递进的方式,解决了软件开发的难点。领域驱动设计中提到的领域模型,主要是指上面提到的分析模型,目的是为了体现业务理念,同时也考虑到一定的开发视角。建立领域模型的过程就是理解现实世界中的概念及其发展变化逻辑的过程,这正是认识论和语言哲学的应用场景。这就是哲学指导领域建模和整个软件开发过程的原因。对领域建模的重视并不是从领域驱动设计开始的,而是从软件开发方法论的出现开始的。早期的结构化方法使用数据流图和ER图进行建模。后来,它发展成为一种面向对象的方法论,使用对象建模。领域驱动设计是面向对象方法论的归纳和发展,为面向对象方法论建立了一套模式语言,使其更易于学习和使用。领域驱动设计主要面向传统意义上的软件开发,尤其是企业应用的开发。经过几十年的发展,至少在理论上已经研究透彻,难点在于工程上的推广应用。近年来,人工智能、大数据、下一代互联网的发展带来了一系列新问题:如何保护隐私?谁拥有个人行为数据?人工智能会剥夺人类的自由意志吗?人工智能作恶的法律责任如何认定?机器人能上战场吗?个人如何应对高科技带来的焦虑?等等,这些都是伦理学和心灵哲学要讨论的问题。这些话题超出了领域驱动设计的范围,我们的讨论也可以告一段落了。
