<<领域驱动设计-软件核心复杂性应对之道>>:全书围绕着设计和开发实践,结合若干真实的项目案例,向读者阐述如何在真实的软件开发中应用领域驱动设计。书中给出了领域驱动设计的系统化方法,并将人们普遍接受的一些最佳实践综合到一起,融入了作者的见解和经验,展现了一些可扩展的设计最佳实践、已验证过的技术以及便于应对复杂领域的软件项目开发的基本原则。适合各层次的面向对象软件开发人员、系统分析员阅读。 <<代码精进之路从码农到工匠>>:共有13章内容,主要分为技艺部分、思想部分和实践部分。技艺部分详细介绍了编程技巧和方法论,并配以详尽的代码案例,有助于读者提高编写代码的能力,优化代码质量。思想部分主要包括抽象能力、分治思想,以及程序员应该具备的素养等内容。实践部分主要介绍了常见的应用架构模式,以及COLA架构的设计原理。 DDD的革命性在于领域驱动设计是面向对象分析的方法论,它可以利用面向对象的特性(封装、多态)有效地化解复杂性,而传统J2EE或Spring+Hibernate等事务性编程模型只关心数据。这些数据对象除了简单的setter/getter方法外,不包含任何业务逻辑,业务逻辑都是以过程式的代码写在Service中。这种方式极易上手,但随着业务的发展,系统也很容易变得混乱复杂。 学习、理解及应用领域驱动设计建议先有以下几个基础条件
随着软件系统越来越庞大,需求越来越模糊,代码越来越混乱,测试越来越困难,技术演进基本不可能,而其中大型复杂的软件项目更容易走向系统老化的过程,形成需求难、开发难、测试难、创新难,单体架构局部业务膨胀可以拆成微服务,那么微服务局部业务膨胀又应该怎么做?DDD之所以火,即能解决微服务解决不了的问题。DDD是为了解决快速变化、复杂系统的设计问题。
如何解决系统老化问题使得重新崛起的DDD领域驱动设计成了业界最大的希望乃至目前阶段最理想的方式,积极践行DDD,搭建的每一个应用,实现的每一个功能,写的每一行代码,都是在精修架构思维的内功。过去系统分析和系统设计都是分离的,DDD则打破了这种隔阂,提出了领域模型概念,统一了分析和设计编程,使得软件能够更灵活快速跟随需求变化。先来理解几个概念:
传统架构的设计逻辑从数据库出发,先进行数据库设计、建表、字段不合理再调整,表和对象进行管线。而DDD是把数据库当成与其他组件相等的一环,可以解决现有系统因为数据库,而导致系统耦合问题。而适应快节奏的需求变更频繁的敏捷开发的出现,更是对传统架构的设计产生较大影响,架构师作为架构设计文档和图形的载体。
DDD中的设计主要指领域模型的设计。为什么是领域模型的设计而不是架构设计或其他的什么设计呢?因为DDD是一种基于模型驱动开发的软件开发思想,强调领域模型是整个系统的核心,领域模型也是整个系统的核心价值所在。每一个领域,都有一个对应的领域模型,领域模型能够很好的帮我们解决复杂的业务问题。领域模型设计只是整个软件设计中的很小一部分。除了领域模型设计之外,要落地一个系统,我们还有非常多的其他设计要做,比如容量规划、架构设计、数据库设计、缓存设计、框架选型、发布方案、数据迁移、同步方案、分库分表方案、回滚方案、高并发解决方案、一致性选型、性能压测方案、监控报警方案等。
一般系统设计分为概念设计、逻辑设计、物理设计三个阶段。
一个领域本质上可以理解为一个问题域,只要是同一个领域,那问题域就相同。任何一个系统都会属于某个特定的领域,比如论坛是一个领域,只要你想做一个论坛,那这个论坛的核心业务是确定的,比如都有用户发帖、回帖等核心基本功能;传统电商领域的问题无非就是订单、商品、支付、物流、库存之类,而社交电商除了传统电商的属性外,也会附加社交、通讯相关的功能。所以同一个领域的系统都具有相同的核心业务,因为他们要解决的问题的本质是类似的。
只要我们确定了系统所属的领域,那这个系统的核心业务,即要解决的关键问题、问题的范围边界就基本确定了。通常我们说,要成为一个领域的专家,必须要在这个领域深入研究很多年才行。因为只有你研究了很多年,你才会遇到非常多的该领域的问题,同时你解决这个领域中的问题的经验也非常丰富。很多时候,领域专家比技术专家更加吃香,比如金融领域的专家。
领域划分以事件风暴的形式(Event Storming),列出所有的用户故事(Use Story),用户故事可通过6W模型来构建,即描写场景的 Who、What、Why、Where、When 与 hoW 六个要素。然后圈选功能相近的部分,就形成了领域,领域又根据职能不同划分为:核心域、支撑域、通用域,
领域驱动领域模型设计,领域模型驱动代码实现。这个就和我们传统的数据库驱动开发的思路形成对比了。DDD中,我们总是以领域为边界,分析领域中的核心问题(核心关注点),然后设计对应的领域模型,再通过领域模型驱动代码实现。而像数据库设计、持久化技术等这些都不是DDD的核心,而是外围的东西。
领域驱动设计(DDD)的最大价值:当我们要开发一个系统时,应该尽量先把领域模型想清楚,然后再开始动手编码,这样的系统后期才会很好维护。但是,很多项目(尤其是互联网项目,为了赶工)都是一开始模型没想清楚,一上来就开始建表写代码,代码写的非常冗余,完全是过程是的思考方式,最后导致系统非常难以维护。而且更糟糕的是,出来混总是要还的,前期的领域模型设计的不好,不够抽象,如果你的系统会长期需要维护和适应业务变化,那后面你一定会遇到各种问题维护上的困难,比如数据结构设计不合理,代码到处冗余,改BUG到处引入新的BUG,新人对这种代码上手困难,等。而那时如果你再想重构模型,那要付出的代价会比一开始重新开发还要大,因为你还要考虑兼容历史的数据,数据迁移,如何平滑发布等各种头疼的问题。所以,就导致我们最后天天加班。从面向过程式的想到哪里写到哪里的思想转变为基于系统化的模型驱动的思维很难,这或许是DDD很难在中国或国外流行起来的原因吧。
DDD中的设计主要指领域模型的设计,DDD是一种基于模型驱动开发的软件开发思想,强调领域模型是整个系统的核心,领域模型也是整个系统的核心价值所在。每一个领域,都有一个对应的领域模型,领域模型能够很好的帮我们解决复杂的业务问题,从领域和代码实现的角度来理解,领域模型绑定了领域和代码实现,确保了最终的代码实现就一定是解决了领域中的核心问题的。
子域可以理解为更加细分的领域,甚至可以把子域进行更新划分,分成更多的子域。比如把电商平台看成是一个领域,那么订单、仓储、物流都可以是子域,而仓储可以划分为本地仓储、三方仓储、异地仓储等子域。子域可以划分为三种类型
能够正确的、简单的、清晰的表达业务,并让项目的参与人员都能够达成共识的语言。统一语言是提炼领域知识的输出结果,也是进行后续需求迭代及重构的基础,统一语言的建立有以下几个要点:
语义问题,苹果不大好吃这句话可以理解为苹果,不大好吃,也可以理解为苹果不大,好吃。限界上下文用来封装封装通用语言和领域对象,提供上线文环境,保证在领域内的一些术语、业务相关对象等有一个确切的含义、没有二义性,这个边界定义模型的使用范围。那上面例子来说,苹果不大好吃,下次再也不买了。
限界上下文包含两部分:上下文(Context)是业务目标,限界(Bounded)则是保护和隔离上下文的边界。限界上下文没有统一的划分标准,需根据自己的业务场景来甄别如何划分。一个上下文中包含了相同的领域知识,角色在上下文中完成动作目标;边界体现在以下几方面:
战略设计是一种用高层次的视野来审视软件系统的方式,战略设计也可以出现建模的方式问题、频繁进行战略改动问题。UML建模,适合小范围。关联关系、引用关系,解决复杂问题如四色建模法、限界纸笔法、事件风暴。
领域模型是对领域内的概念类或现实世界中对象的可视化表示。包括业务对象模型、业务对象之间的引用关系。
业务对象模型就是业务逻辑流转的过程中需要的所有角色,甚至还包括你的业务逻辑流转本身。业务模型在DDD大概实现有四种方式
失血模型和涨血模型是现在不太推荐的使用的模型,贫血模型是用的最多的,而充血模型对于程序员的要求非常高。贫血模型的对象会被各种Service调用,分布在不同业务中,对于业务理解难度加大。而充血模型每个实体操作自己实体的变化,跨实体的变化通过领域服务实现,领域服务调用实体方法完成状态改变。