DDD由来与优势
软件架构设计的真正目的是解决软件复杂度带来的问题,软件复杂度由来主要由三方面:高并发场景下的对软件高性能要求、业务场景对软件高可用要求、持续变化的业务以及业务扩张和增加需求对软件扩展性的要求,除此外,对低成本、安全、软件规模也一定程度上增加了软件设计的复杂度。
在解决每个复杂度维度上,分别有各自的应对解决方案:
-
在高性能方面,可以通过单机和集群两个维度提升系统性能:在单机方面通过多进程、多线程等技术解决单机高并发,在集群方面通过任务拆解、分解,将任务调度到每个Worker节点执行,从而进一步提升系统整体高并发与吞吐量
-
在高可用方面,可以通过冗余服务或机器节点方式来确保整体应用的高可用,常见的有计算和存储高可用(如Mysql主从集群),而高可用的状态决策是非常关键的一点,即是否由一个状态转移到另一个状态,常见决策方式有独裁、协商(如redis哨兵、主备切换)、民主(如Paxos、Raft等分布式一致性算法)
-
在扩展性方面,由于软件唯一不变就是变化这个基本定理存在,正确的预测变化、完美封装变化,本身就是一件复杂事情;在这点上,才有把变化封装起来,与稳定的不变内容进行隔离(分层、提升软件内聚性,降低耦合度),不变层通过接口去适配多变的情况(如文件系统的VFS适配多种文件格式,同时对用户提供标准化的操作接口场景)
在低成本、安全、规模方面,技术革命创新、功能和架构安全、软件规模量变引发质变(微服务就是典型例子),这些因素也增加了软件的复杂度。
然而我们往往忽略了在软件开发阶段,因为需求的理解不到位等导致的开发返工以及因为原班开发人员离职带来的交接文档的缺失,导致新人接手项目的高上手成本、高沟通成本和高维护成本。是否存在有效的方法能够在开发人员开始编码之前能解决这一问题呢?
领域驱动设计(Domain Driven Desing,简称DDD)就是在可扩展性方面将复杂多变的业务排除在稳定不变的内核业务之外,从而在多变的环境中找到不变的部分,达到以不变应万变的目标。不仅如此,DDD还能够以更优于静态文档的方式提供开发人员,业务人员所需要的业务知识,因为DDD在设计之初就要求业务人员特别是领域专家与开发人员通过双方统一的语言一起来协作设计系统,最终交付给业务人员能够“读”得懂的,符合其期望的产品,尽管这一愿望很激动人心,但实施过程并不顺利,但无论如何我们也应该坚持这一目标,就像DDD作者总结的那样,会给整个团队甚至公司带来的益处远超过因为学习DDD带来的成本,这些优势归结起来如是:
• 使领域专家和开发者在一起密切合作,这样开发出来的软件能够准确地传达业务规则。“准确传达业务规则”的意思是说,此时的软件就像是领域专家所开发出来的一样。
• 可以帮助业务人员自我提高。没有任何一个领域专家或者管理者敢说他对业务已经了如指掌了,业务知识也需要一个长期的学习过程。在DDD中,每个人都在学习,同时每个人又是知识的贡献者。
• 关键在于对知识的集中,因为这样可以确保软件知识并不只是掌握在少数人手中。
• 在领域专家、开发者和软件本身之间不存在“翻译”,意思是当大家都使用相同的语言进行交流时,每人都能听懂他人所说。
• 设计就是代码,代码就是设计。设计是关于软件如何工作的,最好的编码设计来自于多次试验,这得益于敏捷的发现过程。
• DDD同时提供了战略设计和战术设计两种方式。战略设计帮助我们理解哪些投入是最重要的;哪些既有软件资产是可以重新拿来使用的;哪些人应该被加到团队中?战术设计则帮助我们创建DDD模型中各个部件。
就像其他高回报率的投入一样,DDD需要我们在时间和精力上都有所投入。但是,考虑到我们在开发软件的过程中经常遇到的各种问题和挑战,这样的投入是值得的。
领域驱动设计分层架构
分层架构模式被认为是所有架构的始祖。在自然界中,大到宇宙天体,小到原子的运行模式。在人类社会中,大到国际组织,小到团体的组织模式,都采用层次结构。在软件架构中,从早期的网络七层协议,操作系统的内核架构到广泛使用的MVC软件开发架构,都在使用分层架构,可见分层模式经久不衰。 分层架构的好处是显而易见的,首先,由于层间松散的耦合关系,使得我们可以专注于本层的设计,而不必关心其他层的设计,也不必担心自己的设计会影响其它层,对提高软件质量大有裨益。其次,分层架构使得程序结构清晰,升级和维护都变得十分容易,更改某层的具体实现代码,只要本层的接口保持稳定,其他层可以不必修改。即使本层的接口发生变化,也只影响相邻的上层,修改工作量小且错误可以控制,不会带来意外的风险。 分层架构的一个重要原则是每层只能与位于其下方的层发生耦合。分层架构可以简单分为两种,即严格分层架构和松散分层架构。在严格分层架构中,某层只能与位于其直接下方的层发生耦合,而在松散分层架构中,则允许某层与它的任意下方层发生耦合。
下图A中所示为一个典型的DDD系统所采用的传统分层架构,其中核心域只位于架构中的其中一层,其上为用户界面层(User Interface)和应用层(Application Layer),其下是基础设施层(Infrastructure Layer)。
-
User Interface为用户界面层(或表示层),负责向用户显示信息和解释命令,业务逻辑仅仅是有关输入参数验证等的验证等,不同于领域层的业务逻辑。这里指的用户可以是另一个计算机系统,不一定是使用用户界面的人。
-
Application为应用层,定义软件要完成的任务,并且指挥表达领域概念的对象来解决问题。这一层所负责的工作对业务来说意义重大,也是与其它系统的应用层进行交互的必要渠道。应用层要尽量简单,不包含业务规则或者知识,而只为下一层中的领域对象协调任务,分配工作,使它们互相协作。 当需要创建新的聚合时,应用服务应该使用工厂或聚合的构造函数来实例化对象,然后采用资源库对其进行持久化。应用服务还可以调用领域服务来完成和领