最近再次拜读了Eric的奠定之做【Domain-Driven Design –Tackling Complexity in the Heart of Software】,还有Vernon的【Inplementing Domain-Driven Design】,虽然是java版本,但并不影响阅读,毕竟设计思想是通用的,结合我的使用DDD的一些经验,作个随谈。html
在我看来,DDD绝非什么标新立异的的思想,更多的是软件发展的天然结果。就像20世纪六七十年代出现的软件危机后,面向对象编程被搬上了舞台;瀑布式开发在快速发展的互联网时代,敏捷成为了它的救赎;而DDD更多的是对传统的以数据为中心的开发习惯的一种反思。java
若是你关心软件工艺,而不只仅是coding,那么领域驱动设计即是很是重要的一项技能。程序员
随着软件业的快速发展,软件规模愈来愈大,生命周期也愈来愈长,推倒从新开发的风险愈来愈大。这时,软件团队急需在较低成本的状态下持续维护一个系统不少年。数据库
然而,事与愿违,随着时间的推移,程序愈来愈乱,维护成本愈来愈高,软件退化成了无数软件团队的噩梦。编程
咱们的软件老是经历着这样的轮回,软件设计质量最高的时候是第一次设计的那个版本,当第一个版本设计上线之后就开始各类需求叠加和变动,这经常又会打乱原有的设计。架构
特别是当咱们许多团队都在实践敏捷开发,但敏捷开发的落地对开发团队的设计能力、设计质量,提出了很是高的要求。由于每一个敏捷周期,都是在对上一个版本的更新。若是设计质量跟不上,更新速度越快,代码退化就越快。代码质量降低了,还能敏捷得起来吗?因此咱们如何在快速进行迭代交付的同时,又能保持着高质量的软件设计呢? 分布式
长久以来,咱们程序员都是很好的技术型思考者,咱们老是擅长从技术的角度来解决项目问题。可是,一个软件系统是否真正可用,是经过它所提供的业务价值体现出来的。微服务
遗憾的是,咱们更多的开发人员,对DDD的实践都是停留在"地面"上。学习
过分拘泥于实现细节,而不是从一开始就居高临下俯视咱们的软件,会错失让咱们在天空概览的机会。spa
咱们开发人员老是在技术层面追求着高内聚,低耦合的完美设计,对不起,若是你不懂DDD在战略层面在业务系统存在的意义,凭着战术层面的指导,是实现不了这样的完美设计的。
有没有什么方式可让咱们保持软件的质量呢?有,那就是领域驱动设计!
首先DDD并非关于技术的,而是关于讨论,聆听,理解和发现业务价值。所以,与其天天钻在那些永远也学不完的技术中,何不将咱们的关注点向软件系统所提供的业务价值方向思考,这也正是DDD所试图解决的问题。
DDD的核心理念中,是划分为战略设计(天空)以及战术设计(地面)两部分的。
战略设计主要从高层“俯视”咱们的软件系统,帮助咱们精准地划分领域,明确各个领域的边界以及处理各个领域之间的关系;而战术设计则从技术实现的层面教会咱们如何具体地实施DDD。
能够看出,战略设计在整个DDD落地过程当中,是占核心地位的,它给咱们提供了高屋建瓴的宽阔视野。
DDD的战略设计帮助咱们清晰的划分不一样的业务系统和各自的业务关注点,这样能够有效的保护各自系统并实现高内聚低耦合的设计原则。
DDD理念面世这么多年了,为何业界内仍是不多实际的案例呢?我的认为有几点缘由:
1. DDD提倡的是基于现实世界的现实行为进行建模,这就限制了案例的产生,毕竟这是业界的核心业务,不太可能做为案例披露出来的。
2. 没有好的领域专家,DDD一直强调领域专家的重要性,在咱们这个行业,业务和技术都深刻的,太少了,这个行业充斥着急功近利,没有多少人真正是对某个行业进行钻研透彻的。
3. 概念繁多,对人的要求极高,特别是抽象能力,容易让直性思惟的人绕进去,学习使用成本会比较高。
4. 忽视战略层面的意义,致使不少案例胎死腹中。
即便是会面临很多的困境,但DDD仍然是诸多公司追捧的宠儿,除了它能使咱们开发者提升抽象能力以外,DDD它自己的做用是简单化,而不是复杂化。
在使用DDD时,咱们应该采用最简单的方式进行复杂领域建模,而不是使问题变得更加复杂。
当咱们在实施过程当中面临着各类各样的问题时,有哪些策略是能够指导咱们进行专项突破的点吗?
有的,从战略设计先入手。
上面提到了,咱们使用DDD,更多的是从战术设计这个”地面“着手,因此会出现了DDD-Lite的状况。而这是本末倒置的,DDD首先让咱们关注的不是技术,而是业务语言。
既然是领域驱动设计,那么咱们的设计重点确定是在领域了,以及领域模型的正确设计了。
首先领域并非很高深的词汇,它是问题域集合的代名词。咱们肯定咱们产品所属的领域后,所面临的问题是肯定的,好比说咱们是一个电商系统,它是属于电商领域,那么会遇到用户,订单,购物车,商品,交易,物流等明确的问题集合须要咱们解决,这些问题域是确切的。
在领域驱动设计中,强调对于子域的正确划分,即便是在平常开发中,咱们一般会也将一个大型的软件系统拆分红若干个子系统。这种划分有多是基于架构方面的考虑,也有多是基于业务的。
在DDD中,咱们对系统的划分是基于领域的,也明确是基于业务的。即咱们能够基于领域专家的领域业务知识,将整个系统划分红许多相对独立的业务场景(子域),而后在一个一个的子域中进行领域模型分析与建模。
而后咱们很快就发现了问题,哪些概念应该建模在哪些子域里面?咱们可能会发现一个领域模型建模在子系统A中是能够的,而建模在子系统B中彷佛也合乎情理。
如何能正肯定于模型含义呢?限界上下文!
限界上下文是一个显式的边界,领域模型便存在这个边界内,建立边界的缘由在于,每个模型概念,包括它的属性和操做,在这个边界内都是具备特殊含义的。
从这里能够看出,若是光凭名字,咱们是没法区分两个帐户的意思的,只有经过它们所在的限界上下文,咱们才能看出它们之间的区别。
限界上下文是用来为领域提供语境的,它保证在领域以内的通用语言、领域模型有一个确切的含义,没有二义性。
我一直认为,DDD中的领域模型才是一个真正意义上的OOP,它所推崇的充血模型,是映射着咱们真实世界的真实行为。咱们平时口中所谓的OOP,实体只是单纯的数据载体,没有更多的功能,DDD推荐的领域对象,是跟咱们现实生活中的概念是一致的,有具体的行为,是一个行为饱满的对象,这样才是DDD的威力所在,也是咱们实现高内聚低耦合的途径。
领域模型即业务。
从DDD的名称咱们就能够看出,领域驱动设计中,领域模型是最核心的点所在,因此在设计获得模型后,DDD要求咱们在代码中无误差地实现模型,也就是所谓模型驱动开发(Model-Driven-Design, MDD)。
行为丰富的领域模型,才是DDD最大的威力,能设计出行为丰富而且涵盖诸多现实业务的模型,就是消化领域知识的最好体现。
因为这种模型是咱们现实世界的真实描述,鉴于咱们真实世界的知识跨度的速度(参考地心说的统治时间),是能够维持软件到必定的生命周期的。这种模型的行为丰满,符合真实世界的认知,且业务纯净,减小了犯错的可能性。
要建立行为饱满的领域对象并不难,首先出发点是认真思考咱们真实世界的可靠行为,把这些行为提炼到模型中,再次咱们须要转变一下思惟,将领域对象当作是服务的提供方,而不是数据容器,结合真实世界多思考一个领域对象可以提供哪些行为,而不是数据。
这几年当DDD再次映入个人眼帘,是微服务的兴起,DDD已经面世好多年了,随着微服务的兴起,DDD从新活跃在咱们的眼中,或者说,微服务的兴起,也依赖了DDD的铺垫。它们是相辅相成的。
微服务的一个核心点就在于服务的划分,整个系统被被分红了不少个轻量的模块,它的一个原则就是划分出来的模块在于“专”(小并非微服务的重要的考虑因素,具体参看【微服务架构 - 正确的开始】),即每一个服务的松散耦合上,也就是咱们常说的高内聚,低耦合。
无独有偶,DDD也是基于高内聚,低耦合的思想来指导咱们如何划分正确的子域。
咱们上面讲了,在限界上下文中,其中的领域模型都是高内聚的存在,它们的关联性是很是强的,它们只会在同一个缘由的条件下进行软件变化,因此一般状况下,一个限界上下文下的子域是能够设计为一个微服务应用程序,而这个微服务的边界,就是这个限界上下文,服务间的关系,就是上下文映射图。
在微服务中借助DDD的思想划分服务是大概这么一个过程:
在微服务中,会面临着咱们分布式系统的常见问题,其一就是事务的一致性。在DDD中,领域事件即可以用于处理这些问题,此时最终一致性取代了事务一致性,经过领域事件的方式达到各个组件之间的数据一致性。
洋洋洒洒的聊了些我的对DDD的一些见解,其中的部分概念会后续在这个系列的博文章节里继续探讨。
正如微服务架构中的“微服务不是银弹”,领域驱动设计也会面临一样的问题。做为架构师,我始终认为咱们在任何的状况下对于任何的特定技术,均可以活学活用,因此我的使用DDD的一个理念的是,不要为了DDD而去DDD。
领域驱动设计做为面向对象编程的高级方法论,它其中的不少设计是很是美妙以及契合实际的,然而所谓设计,是要以咱们的团队的知识、经验和智慧,全面充分的考虑各类内外因素后,在设计方案中做出合理的选择的过程。
咱们的目标是什么?是追求完美的DDD吗?不是,咱们的目标是把系统作得更健壮,赋予产品强大且持久的生命力,因此咱们在真正的使用过程当中,实际上是借助了DDD不少的设计思想来指导咱们的系统设计。
没人在意你是不是一个纯正的DDD,老板以及用户注重的,是你所使用的技术带来的业务价值。
因此在使用领域驱动设计时,并不表明整个系统的方方面面都必须听从领域驱动设计的原则,须要根据实际状况,让适合的部分使用领域驱动设计,让不适合的部分使用面向过程的设计。
DDD 的真谛是领域建模,即深刻理解业务。咱们不可能一步到位深入理解业务,它是一个逐步深刻的过程。只有深刻理解业务,将对业务的深刻理解设计到领域模型中,设计出来的软件才更加专业。所以,基于每一个限界上下文进行领域建模,不断地将每一个功能加入模型中,落地每一个微服务的设计。
当业务愈来愈复杂,理解愈来愈深刻的时候,咱们要适时地调整原有的模型,就能适应新的功能。正由于 DDD 就是要应对的是软件的这样的不肯定性的复杂,才会经过结合现实世界的理解,领域建模去抽象复杂业务,让复杂业务获得简化,从而简化软件的设计,使设计始终处于高质量的水准上。
所以,咱们学习 DDD,首先就要把设计作到位,准确理解那些领域,限界上下文,聚合、仓库、领域事件等基础概念,并在设计实战中作出正确的设计。
DDD中有不少概念是相对来讲是比较抽象的,特别是对习惯逻辑思惟的程序员来讲,抠概念是比较痛苦的,因此不少技术人员在初学DDD时,更多的是关注战术层面的设计,然而过分地强调DDD的技术性将使咱们错过由战略设计带来的好处,毕竟战略层面能够升个级为整个软件的业务架构,这个架构是支撑软件生命周期重要的依据。
记住,领域模型的设计并不会一蹴而就,咱们须要反复研究领域知识,不断重构模型,才能将领域中的重要概念提炼成简单而清晰的模型。