传统模式秉持以数据(库)为中心的理念,而领域驱动设计则转向以领域模型为中心,这是根本性的设计转变。DDD通过四重边界划分问题空间和解空间,确定核心、通用、支撑三类子领域,在界限上下文内部,通过分层(基础层-领域层-应用层-展现层)实现内外隔离,应用层形成了一种保护层,有效地隔离了业务复杂度与技术复杂度。将领域层作为整个系统稳定而内聚的核心,是领域驱动设计的关键特征。
回顾软件工程发展过程中涌现的各种主义,每一个流行的思潮都有一套自圆其说的理论,都声称完美解决了某些问题,但又无一例外的陷入另一个框架陷阱,但又都无一能够终结软件工程的无序设计。我们无法跳出自娱自乐般无休止重构循环的怪圈,我们依然置身于充满各种技术债的困境,所以,跳出各种框架模式的精神枷锁,回过头来,我们不妨重新审视设计的本质,我们不妨想一想应对软件复杂性的根本原则。
可将解决大规模复杂软件问题的方法,简单归为几点:抽象,分解,隔离。
抽象就是归类,归类是为了复用。抽象的意义是通过表现找到事物背后的本质,抽象的目的是为了减轻认知负担,避免重复思考和劳动,精简问题空间,让人关注更高层次的事物,建模是提炼心智模型的过程,本质就是一种抽象。
分解是把一个复杂问题分割为更小的易于解决的小问题,拆分问题的过程即是简化问题的过程,问题分解之后,还需要协作,这其实就是分治的理念,库、组件化、微服务无不闪烁着分治理念的智慧的光芒。拆分有两种方式:技术维度和业务维度,微服务和DDD就是从业务维度做问题拆分。拆分可以遵循AKF原则和康威定律,高内聚低耦合是评价拆分好坏的标准,让上帝的归上帝,让凯撒的归凯撒。
隔离是为了解耦,建立松耦合的系统一直是工程师们孜孜以求的目标,分层是实现隔离的有效手段,每层专注于自己的功能实现,上层使用下层的能力,下层为上层提供服务,上下层之间通过约定的接口交互,不紧邻的层之间完全透明。外部世界的规则是契约、通信以及系统级别的架构风格和模式,而内部世界的规则是分层、协作以及类级别的设计分格和模式。
在软件变革的滚滚洪流中,软件工程的先驱和贤哲们,提出了各种各样的编程思想和方法论,但无一从根本上彻底解决问题,《人月神话》第16章提出,因为软件工程是超级复杂的系统,所以断言没有银弹,不仅没有包治百病的灵药,更指出在未来十年不可能有提升十倍效率的方法。
回顾历史,每一种完美方案都从怼已有的方案和宣称解决所有问题开始,然后传播布道,把大众带入自己精心设计的逻辑闭环,然后追随者以一种宗教般的虔诚,将理论生搬硬套到项目中去,最后交付的代码依然充斥各种模糊不清、污浊不堪,任何演进都可能便引起偶然不变性的瞬间坍塌,剩下一地鸡毛,而那些新颖的理论,最终都会像袅烟一样,飘散在历史的浩瀚天空中。
古人云:人生而无知,却并不愚蠢,是教育使人愚蠢。古人又云:学而不思则怠。所以,我们应该意识到思辨的重要性,对于知识,我们学习它研究它,但不盲从它。那对待软件工程,我们应该秉持怎样的原则呢?
首先,人是关键,软件开发没有终极解,因为软件就是人思想的外化,而人本身充满缺陷。我们必须认可人这种生物在抽象过程中的一些必然缺陷,以及人抽象能力的差异,这将意味着,相比于规则和流程,人其实才是软件实施过程中的灵魂,思想和法则可以给人提供指引,但它们无法神奇的解决软件工程中的所有问题,影响软件开发质量的关键因素是人,而不是设计方法。注重形式而不是内容,注重文档而非交付的代码,都是本末倒置的。
其二,实事求是,具体问题具体分析,软件涵盖的范围实在太广的,这就意味着每一种具体实施细则都有它的局限性,不能用僵化的标准困住手脚,不可拘泥于规则而使之成为教条,不可用倚天剑剪指甲,不要用屠龙刀剃胡子。比如最简单的业务CRUD模型可能就够了,而有些可能适用CQRS、六边形架构,有些贫血领域对象也可以,有些可能事件风暴模式更好,有时候数据和操作应该分离,甚至读写也应该分离,而有时候数据和操作封装在一起更好,脱离实际的牛刀杀鸡只会徒增笑耳。