> DDD 实战1 - 基础代码模型
> DDD 实战2 - 集成限界上下文(Rest & DubboQ?/a>
> DDD 实战3 - 集成限界上下文(消息模式Q?br />> DDD 实战4 - 领域事g的设计与使用
> DDD 实战5 - 实体与值对?br />> DDD 实战6 - 聚合的设?br />> DDD 实战7 - 领域工厂与领域资源库
> DDD 实战8 - 领域服务与应用服?br />> DDD 实战9 - 架构设计
> DDD 实战10 - 战略设计
当h们要做一个Y件系l时Q一般L因ؓ遇到了什么问题,然后希望通过一个Y件系l来解决?/p>
比如Q我是一家企业,然后我觉得我现在U下销售自q产品q不够,我希望能够在U上也能销售自q产品。所以,自然而然想到要做一个普通电商系l,用于实现在线销售自׃业品的目的?/p>
再比如,我是一家互联网公司Q公司有很多pȝ对外提供服务Q面向很多客L讑֤。但是最q由于各U原因,D服务l常出故障。所以,我们希望通过各种措施提高服务的质量和E_性。其中的一个措施就是希望能做一个灰度发布的q_Q这个^台可以提供灰度发布的服务。然后,当某个业务系l做了一些修改ƈ需要发布时Q可以用我们的灰度发布q_来非常方便的实现灰度发布的功能。比如在灰度发布q_上方便的定制允许哪些特定的客L才会讉K新服务,哪些客户端l用老服务。灰度发布^台可以提供各U灰度的{略。有了这L灰度发布机制Q那即便pȝ的新逻辑有什么问题,受媄响的面也不会很大Q在可控范围内。所以,如果公司里的所有对外提供服务的pȝ都接入了灰度q_Q那q些pȝ的发布环节就可以更加有保障了?/p>
MQ我们做M一个Y件系l,都是有原因的Q否则就没必要做q个pȝQ而这个原因就是我们遇到的问题。所以,通过问题Q我们就知道了我们需要一个什么样的系l,q个pȝ解决什么样的问题。最后,我们很自然的得Z一个目标,即知道了自己要什么。比如我要做一个论坛、一个博客系l、一个电商^台、一个灰度发布系l、一个IDE、一个分布式消息队列、一个通信框架Q等{?/p>
DDD的全UCؓDomain-driven DesignQ即领域驱动设计。下面我从领域、问题域、领域模型、设计、驱动这几个词语的含义和联系的角度去阐述DDD是如何融入到我们qx的Y件开发初期阶D늚。要理解什么是领域驱动设计Q首先要理解什么是领域Q什么是设计Q还有驱动是什么意思,什么驱动什么?/p>
前面我们已经清楚的知道我们现在要做一个什么样的系l,q个pȝ需要解决什么问题。我认ؓM一个系l都会属于某个特定的领域Q比如论坛是一个领域,只要你想做一个论坛,那这个论坛的核心业务是确定的Q比如都有用户发帖、回帖等核心基本功能。比如电商^台、普通电商系l,q种都属于网上电商领域,只要是这个领域的pȝQ那都有商品览、购物R、下单、减库存、付ƾ交易等核心环节。所以,同一个领域的pȝ都具有相同的核心业务Q因Z们要解决的问题的本质是类似的?/p>
因此Q我们可以推断出Q一个领域本质上可以理解为就是一个问题域Q只要是同一个领域,那问题域q同。所以,只要我们定了系l所属的领域Q那q个pȝ的核心业务,卌解决的关键问题、问题的范围边界基本确定了。通常我们_要成Z个领域的专家Q必要在这个领域深入研I很多年才行。因为只有你研究了很多年Q你才会遇到非常多的该领域的问题Q同时你解决q个领域中的问题的经验也非常丰富。很多时候,领域专家比技术专家更加吃香,比如金融领域的专家?/p>
DDD中的设计主要指领域模型的设计。ؓ什么是领域模型的设计而不是架构设计或其他的什么设计呢Q因为DDD是一U基于模型驱动开发的软g开发思想Q强调领域模型是整个pȝ的核心,领域模型也是整个pȝ的核心h值所在。每一个领域,都有一个对应的领域模型Q领域模型能够很好的帮我们解军_杂的业务问题?/p>
从领域和代码实现的角度来理解Q领域模型绑定了领域和代码实玎ͼ保了最l的代码实现׃定是解决了领域中的核心问题的。因为:1Q领域驱动领域模型设计;2Q领域模型驱动代码实现。我们只要保证领域模型的设计是正的Q就能确定领域模型可以解决领域中的核心问题;同理Q我们只要保证代码实现是严格按照领域模型的意图来落地的,那就能保证最后出来的代码能够解决领域的核心问题的。这个思\Q和传统的分析、设计、编码这几个阶段被割裂(q且每个阶段的物也不同Q的软g开发方法学形成鲜明的对比?/p>
上面其实已经提到了,是Q?Q领域驱动领域模型设计;2Q领域模型驱动代码实现。这个就和我们传l的数据库驱动开发的思\形成Ҏ了。DDD中,我们L以领域ؓ边界Q分析领域中的核心问题(核心x点)Q然后设计对应的领域模型Q再通过领域模型驱动代码实现。而像数据库设计、持久化技术等q些都不是DDD的核心,而是外围的东ѝ?/p>
领域驱动设计QDDDQ告诉我们的最大h值我觉得是:当我们要开发一个系l时Q应该尽量先把领域模型想清楚Q然后再开始动手编码,q样的系l后期才会很好维护。但是,很多目Q尤其是互联|项目,Z赶工Q都是一开始模型没x楚,一上来开始徏表写代码Q代码写的非常冗余,完全是过E是的思考方式,最后导致系l非帔R以维护。而且更糟p的是,出来hL要还的,前期的领域模型设计的不好Q不够抽象,如果你的pȝ会长期需要维护和适应业务变化Q那后面你一定会遇到各种问题l护上的困难Q比如数据结构设计不合理Q代码到处冗余,改BUG到处引入新的BUGQ新人对q种代码上手困难Q等。而那时如果你再想重构模型Q那要付出的代h会比一开始重新开发还要大Q因Zq要考虑兼容历史的数据,数据q移Q如何^滑发布等各种头疼的问题。所以,导致我们最后天天加班?/p>
虽然Q我们都知道q个道理Q但是我也明白,人的习惯很难改变的,大部分h都很难从面向q程式的惛_哪里写到哪里的思想转变为基于系l化的模型驱动的思维。我惻Iq或许是DDD很难在中国或国外行h的原因吧。但是,我想q不应该成ؓ我们攑ּ学习DDD的原因,对吧Q?/p>
上面我们通过W一步,虽然我们明确了要做一个什么样的系l,该系l主要解决什么问题,但是ph们还无法开始进行实际的需求分析和模型设计Q我们还必须我们的问题q行拆分Q需求进行细化。有些时候,需求方Q即提出问题的hQ很可能自己不清楚具体想要什么。他只知道一个概念,一个大的目标。比如他只知道要做一个股交易系l,一个灰度发布系l,一个电商^収ͼ一个开发工P{。但是他不清楚这些系l应该具体做成什么样子。这个时候,我认为领域专家就非常重要了,DDD也非常强调领域专家的重要性。因为领域专家对q个领域非常了解Q对领域内的各种业务场景和各U业务规则也非常清楚QMQ对q个领域内的一切业务相关的知识都非怺解。所以,他们自然有能力表达出系l该做成什么样子。所以,要知道一个系l到底该做成什么样子,到底哪些是核心业务关注点Q只能靠沉淀领域内的各种知识Q别无他法。因此,假设你现在打做一个电商^収ͼ但是你对q个领域没什么了解,那你一定得先去了解下该领域内主的电商q_Q比如淘宝、天猫、京东、亚马逊等。这个了解的q程是你沉淀领域知识的过E。如果你不了解,q你领域徏模的能力再强Q各U技术架构能力再Z是不上力。领域专家不是某个固定的角色Q而是某一cMhQ这cMh对这个领域非怺解。比如,一个开发h员也可以是一个领域专家。假设你在一个公司开发和l护一个系l已l好几年了,但是q个pȝ的品经理(PDQ可能已l换q好几Q了,q种情况下,我相信这几Q产品l理都没有比你更熟悉q个领域?/p>
上面我们明白了,领域建模的基是要先理解领域,让自己成为领域专家。如果做Cq点Q我们就打好了坚实的基础了。但是,有时一个领域往往太复杂,涉及到的领域概念、业务规则、交互流E太多,D我们没办法直接针对这个大的领域进行领域徏模。所以,我们需要将领域q行拆分Q本质上是把大问题拆分为小问题Q然后各个击破的思\。然后既然把一个大的领域划分ؓ了多个小的领域(子域Q,那最关键的就是要理清每个子域的边界;然后要搞清楚哪些子域是核心子域,哪些是非核心子域Q哪些是公共支撑子域Q然后,q要思考子域之间的联系是什么。那么,我们该如何划分子域呢Q我的个人看法是从业务相x的角度L考,也就是我们^时说的按业务功能为出发点q行划分。还是拿l典的电商系l来分析Q通常一个电商系l都会包含好几个大块Q比如:
上面q些中心看v来很自然Q因为大家对电子商务的这个领域都已经非常熟悉了,所以都没什么疑问,好像很自然的样子。所以,领域划分是不是就是没什么挑战了呢?昄不是。之所以我们觉得子域划分很单,是因为我们对整个大领域非怺解了。如果我们遇C个冷门的领域Q就没办法这么容易的d分子域了。这需要我们先d力理解领域内的知识。所以,我个Z来不怿什么子域划分的技巧什么的东西Q因为我觉得q个工作没有M诀H可以用。当我们不了解一个东西的时候,如何L解它Q当我们Ҏ个领域有一定的熟悉了,了解了领域内的相关业务的本质和关p,我们p然而然的能划分出合理的子域了。不qƈ不是所有的pȝ都需要划分子域的Q有些系l只是解决一个小问题Q这个问题不复杂Q可能只有一两个核心概念。所以,q种pȝ完全不需要再划分子域。但不是l对的,当一个领域,我们的关注点来多Q每个关注点我们x的信息越来越多的时候,我们会不pȝ去进一步的划分子域。比如,也许我们一开始将商品和商品的库存都放在商品中心里Q但是后来由于库存的l护来复杂,D揉在一起对我们的系l维护带来一定的困难Ӟ我们׃考虑两者进行拆分,q个是所谓的业务垂直分割?/p>
通过上面的两步,我们了解了领域里的知识,也对领域q行了子域划分。但q样q不够,凭这些我们还无法q行后箋的领域模型设计。我们还必须再进一步细化每个子域,q一步明每个子域的核心x点,即需求细化。我觉得我们需要细化的斚w有以下几点:
从上面这4个方面,我们从领域概c业务规则、交互场景、业务流E等l度梳理了我们到底要什么,整理了整个系l应该具备的功能。这个工作我觉得是一个非常具有创造性和有难度的工作。我们一斚w会主观的定义我们惌什么;另一斚wQ我们还会思考我们要的东西的合理性。我认ؓq个是产品l理的工作,产品l理必须要负赯责,把他的品充分设计好Q从各个斚w去考虑Q如何设计一个品,才能更好的解决用L核心诉求Q即领域内的核心问题。如果对领域不够了解Q如果想不清楚用户到底要什么,如果思考问题不够全面,谈何设计Z个合理的产品呢?
关于领域概念的梳理,我觉得可以采用四色原型分析法Q这个分析法通过pȝ的方法,概念划分ؓ不同的种c,Z同种cȝ概念标注不同的颜艌Ӏ然后将q些概念有机的组合v来,从而让我们可以清晰的分析出概念和概念之间的关系。有兴趣的同学可以在|上搜烦?a target="_blank" style="color: #1d58d1; text-decoration: none;">四色原型?/p>
注意Q上面我说的q四点,重点是梳理出我们要什么功能,而不是思考如何实现这些功能,如何实现是Y件设计h员的职责?/strong>
q部分内容,我想学习DDD的h都很熟悉了。DDD原著中提Z很多实用的徏模工P聚合、实体、值对象、工厂、仓储、领域服务、领域事件。我们可以用这些工P来设计每一个子域的领域模型。最l通过领域模型囑ְ设计沉淀下来。要使用q些工具Q首先就要理解每个工L含义和用场景。不要以为很单哦Q比如聚合的划分是一个非常具有艺术的zR同一个系l,不同的h设计出来的聚合是完全不同的。而且很有可能高手之间的最后设计出来的差别反而更大,实际上我认ؓ是世界观的相互碰撞,呵呵。所以,要领域徏模,我觉得每个h都应该去学学哲学知识Q这有助于我们更好的认识世界Q更好的理解事物的本质?/p>
关于q些建模工具的概念和如何q用我就不多展开了,我博客里也有很多q方面的介绍。下面我再讲一下我认ؓ比较重要的东西,比如到底该如何领域徏模?步骤应该是怎么LQ?/p>
通过上面我介l的l化子域的内容,现在再来谈该如何领域建模Q我觉得方便很多了。我的主要方法是Q?/p>
下图是我最q做个一个普通电商系l的商品中心的领域模型图Q给大家参考:
需要特别注意的是,领域模型设计只是整个软g设计中的很小一部分。除了领域模型设计之外,要落C个系l,我们q有非常多的其他设计要做Q比如:
{等。上面这些都需要我们^时的大量学习和积累。作Z个合格的开发h员或架构师,我觉得除了要会DDD领域驱动设计Q还要会上面q么多的技术能力,实是非怸Ҏ的。所以,千万不要以ؓ会DDD了就以ؓ自己很牛|实际上你会的只是软g设计中的冰山一角而已?/p>
本文的重ҎZ我个人对DDD的一些理解,希望能整理出一些自己ȝ出来的一些感悟和l验Qƈ分nl大家。我怿很多人已l看q太多DDD书上的东西,我L感觉书上的东西看似都?#8221;正规“Q很多时候我们读了之后很难消化,q理解了书里的内容Q当我们惌q用到实践中ӞL感觉无从下手。本文希望通过通俗易懂的文字,介绍了一部分我对DDD的学习感悟和实践心得Q希望能l大家一些启发和帮助?/p>