**作者介绍: **
李全党,2021年6月入职去哪儿网,酒店供应链高档技能司理、事务架构SIG成员、公司级内训师,现在担任酒店根底信息事务。主导搭建并落地多个DDD项目,并对高并发、分布式服务高可用,有建设优化经历,2021年落地公司“大主站+微服务”战略,并取得公司“金项奖”技能类三等奖,曾在QCon+做过技能同享。
一、事例简述
跟着集团战略方向调整与事务重组,酒店供应链也面临全新的调整。酒店根底数据事务体系是从国际团队接手,归于10年前体系架构,触及20多个微服务,架构老旧、体系耦合严峻及事务鸿沟含糊,加上事务的快速开展,导致体系灵活性缺少及无法快速承接产品需求,产研合作呈现功率问题。因此,酒店供应链技能侧结合酒店BU及公司相关成功事例,在2022年初主动主张基于DDD思维的技能架构调整,完好落地战略、战术规划及体系完成,本次要点介绍重构落地进程、规划准则及总结,别的阅览本文需求对DDD的基本概念及流程有必定根底,基本概念能够参阅往期技能沙龙。
二、问题剖析
(一)事务需求杂乱
酒店根底信息事务体系开始是为去哪儿独立事务规划,主要包含酒店聚合、房型聚合、图片及城市等相关信息(见下图),开始事务区分比较明晰。2015年携程战略收购去哪儿网后,事务战略也随之发生改动,但其时并未对体系进行阻隔和重构,跟着需求迭代的不断演化,事务逻辑变得越来越杂乱,加上产品司理的流动性较大,酒店根底数据PM、DEV、QA团队短少事务专家,咱们关于原始需求短少了解,部分事务不承认能否下线等等。
(二)体系过度耦合
酒店根底数据触及微服务20多个,体系之间耦合严峻,模块彼此关联,咱们的体系越来越冗繁。有时修正一个很小的产品需求,光回溯该需求触及需求修正的体系及功用点就需求到达“天”级别,更别提修正带来的不可预知的影响面,无论仍是产品、技能需求仍是工单问题排查等,都给组内同学带来较高学习本钱和开发本钱。
下图是咱们酒店根底信息日常开发中的一个常见的体系耦合事例。
这个案列是要完成的事务功用是支持运营人员手工添加酒店图片,其时预估工时时长8pd,实际工时11pd。上图看出从运营开始上传到咱们终究将图片外网展示,全体流程触及到了4个体系。
以下这段话是其时开发这个产品需求的同学的“真情表白”:
1、需求及体系规划阶段。接到TL的排期并阅览产品PRD,发现触及4个事务体系,深入体系内部发现事务逻辑杂乱及体系耦合严峻,了解体系及编写规划方案花费3pd;
2、体系开发阶段。依照规划进行功用开发发现,除正常多事务体系调用外,事务体系内部存在兜底守时任务,需求进一步了解其作用、数据存储及影响规模,花费6pd;
3、体系自测阶段。体系自测触及多个体系间的耦合及不同的数据库版别,自测花费2pd。假如咱们的体系经过精心规划,这个事例是不需求8pd,更别说终究上线花费11pd。咱们能够看出体系过度耦合,不光下降咱们的开发功率,而且关于开发人员不够友爱,这种状况关于人员的安稳性也造成很欠好的影响,所以咱们必须要做出改动。
三、为什么挑选DDD
DDD有许多优势,咱们站在EA视点,能够绑定事务架构和体系架构,作为中间层,将问题域与运用架构相剥离;咱们站在软件杂乱度视点,能够有用处理事务杂乱度和软件杂乱度问题;还比方DDD能够有用的从事务视角对软件体系进行拆解,是微服务区分最好的实践等等,作为根底数据重构,结合咱们上面提到的事务需求杂乱和事务过度耦合问题,咱们主要从处理软件杂乱度和微服务拆分视点考虑,终究挑选DDD作为咱们项目落地的辅导准则。
(一)软件杂乱度应对
Eric Evans 以为“运用程序最主要的杂乱性并不在技能上,而是来自范畴本身、用户的活动或事务”。因此,范畴驱动规划重视的焦点在于范畴和范畴逻辑,由于软件体系的本质其实是给客户(用户)供给具有事务价值的范畴功用。那么DDD是怎么应对软件杂乱度的呢?咱们能够粗略的归为三类,分别是分而治之、重视点别离和一致言语。
1、分而治之。比起单体架构将一切功用都糅合在一同,DDD经过在其战略规划层面对限界上下文、上下文地图的区分来做到这一点。各个事务范畴内重视本身事务才干的内聚,清晰分工,不被其他范畴事务侵蚀,这不只契合“高内聚、低耦合”的架构思路,更是与微服务拆分的思维不约而同;
2、重视点别离。DDD使得范畴模型与存储模型别离,事务杂乱度与技能杂乱度别离;
3、一致言语。咱们大部分需求是横跨多个团队,需求传递低效,需求反复交流,方案产出功率低,而一致言语使得产研在事务概念、了解等方面到达一致,下降交流和了解本钱。
(二)微服务架构形式的最佳实践
微服务有9大特征,咱们这里不赘述。由于DDD能够有用的从事务视角对软件体系进行拆解,而且DDD特别契合微服务的一个特征:环绕事务才干构建。所以用DDD拆分出来的微服务是比较合理的而且能够完成高内聚低耦合。咱们之前会由于微服务不知怎么拆分评论上好几天,其实底子原因是不知道鸿沟在什么地方,而运用DDD对事务剖析的时分:
1、运用聚合把关联性强的事务概念区分在同一个限界上下文,并限定聚合和聚合之间只能经过聚合根来访问
2、聚合根底之上根据事务相关性,事务改动频率,组织结构等等束缚条件来定义限界上下文。
DDD的聚合和限界上下文,使得拆分微服务不再困难。
四、演化式技能改造
在咱们承认运用DDD作为辅导进行项目落地,一个难题是咱们怎么推动多事务体系重构上线,假如选用彻底重做的方法,摒弃原有的体系从头开发,尽管能够快速有用摆脱原有体系的前史技能债,可是也会丢失那些细微而繁杂的事务逻辑,为整个体系的改造带来巨大的项目风险,特别是像酒店聚合、房型聚合等触及多种算法的事务,严峻时会导致高额赔付。
终究咱们选用的是演化式技能改造,即运用重构在原有的体系上逐步改造。即在原有体系的根底上,经过一步一步演进式的代码调整,逐步到达技能改造的方针。每一步重构,关于中心事务功用坚持外部功用不变,要点调整程序内部结构,经过内部程序结构的优化,事务代码逐步与各个层次、各种技能解耦。能够看出,演化式技能改造的方针是完成事务代码与技能结构的解耦,经过重构将长周期的改造进程,经过事务域、重要程度等区分红一个短周期的重构,保证每次重构的正确性。酒店根底数据重构包含酒店事务、房型事务及图片事务,咱们选用分阶段上线,优先上线酒店事务。那么关于酒店事务,其又包含了酒店聚合、酒店静态信息、酒店抓取等多个子事务,为保证重构事务输出正确性及阶段成果,咱们将酒店事务又区分两阶段上线和功用验证,正是这样的进程,保证了在改造进程中,尽管修正了既有代码,但没有影响既有功用,使得改造更加平稳的进行下去。经过这一系列改造,体系的事务代码与技能结构解耦了,接口层建立起来,就能够沉着地展开真实的技能改造。
五、DDD实践及规划准则
(一)完好的DDD落地流程结构
上图为全体DDD落地流程结构,也是thought works强力推荐的流程,那么咱们本篇文章并不计划去解说流程的每个细节,而是要点介绍咱们在酒店根底信息重构进程中,所积累的落地时刻经历和准则,期望经过这些经过笼统和总结的经历,能够给各位带来一些收成和考虑,具体内容请接着往下看。
(二)DDD落地实践准则
-
产研交流,定位愿景
定位愿景的主要目的是对产品的顶层价值规划,对产品方针用户、中心价值、差异化竞争点、痛点等战略层信息在团队层面到达一致,这也是咱们做这个工作的底子。而关于部分的DDD同享文章或许咱们真实在做项目落地时,短少重视咱们的项目定位、愿景是什么,项现在期没有重视,会导致咱们在区分子域时,不清楚怎么承认是中心域、支撑域仍是通用域等,以及资源组织没有侧要点,愿景的定位十分重要,尤其在咱们新项目落地。咱们常用的定位愿景所运用的方法叫“电梯讲演”, 范畴专家与项目团队一同考虑,咱们做的项目事务规模、方针用户、中心价值和愿景,咱们与同类产品的差异和优势在哪里?整个进程是一致项目建设方向和团队思维的进程,当然假如咱们的项目是一个朴实的后端事务体系,并不是一切点都触及,也能够越过,比方下图所示的“关键的长处,难以抵抗的运用理由”,关于酒店静态信息而言,咱们的运用用户更多是咱们公司内部,那么就没有难以抵抗的运用理由了。
-
产研融合,提炼问题域
了解一个杂乱问题域以便发明简略且有用的模型,需求深入详尽的常识以及深入的见地,这些需求产、运、研、测一同协作得到。只需经过协作及同享对问题域的了解,才干有用规划范畴模型以应对事务的应战,这样也能具有足够的灵活性应对新呈现的需求。初期咱们与产运一同,经过线上画板东西(初期推荐运用BeeArt,也可运用ProcessOn)及公司白板,展开事件及指令风暴,一同探讨运用程序的运用场景。这一进程是一切参加者进行花火磕碰,取得范畴的深入见地的催化剂,经过风暴咱们提炼出范畴常识,从头整理事务流程,并构成通用言语(能够包含显现的事务规矩、范畴名词解释等,构成一致的思维地图),到达一致。下图右半部分为“酒店静态信息事务流程”,咱们本次重构从头对原有“蜘蛛网”式的事务流程进行整理,清晰事务流阶段、价值及相应显式规矩,与产运交流承认20次(微信、邮件、线下会议、腾讯会议等)。经过产研融合,提炼问题域后,承认线上低价值或无用事务占比线上总事务用例的41.9%(原始事务用例:222个,重构后保留事务用例:129个,共下掉93个事务)。
- 集中精力,专心中心域
酒店根底数据涵盖酒店、房型、图片及方位区域等多个问题域,咱们需求将问题域分而治之来下降杂乱性,由于较小的模型能够在子域的上下文中更简略被了解。并经过区分中心域、通用域及支撑域来决议研制战略(比方:视频、图片及城市等通用域事务简略且需求相对安稳,并未进行重构,坚持现状)及资源配备。信任咱们在进行项目开发的时分,必定会觉得时刻紧、任务重及资源缺少等等,那么这个时分咱们更要重视要做的项目,他的中心价值是什么(能够参阅范畴愿景),由于他代表团队或组织的价值所在,所以咱们要专心中心范畴,组织中心开发人员及做好跟踪,确保中心范畴依照预期推动。
-
运用限界上下文保护范畴模型完好
限界上下文具有从展示层到范畴逻辑层,再到耐久化,乃至到数据存储功用的垂直切片,那么产品的概念能够存在每个限界上下文中,而且包含仅对该上下文普遍存在的特性和逻辑。任何限界上下文中的改动不再具有对其他有界上下文的影响,由于限界上下文或子域是阻隔的。限界上下文具有概念上的独立性,一个限界上下文内的子概念的解释和目的都不应该超出上下文的鸿沟,若呈现以下依靠关系,需求考虑是否存在未澄清的问题:
a. 双向依靠:上下文之间短少一层未被澄清的上下文,或许两个上下文其实可被合为一个;
b. 循环依靠:任何一个上下文发生改动,依靠链条上的上下文均需求改动;
c. 过长的依靠:本身依靠的信息不能直接从依靠者获取到,需求经过依靠者从其依靠的上下文获取并传递,依靠链 路过长,依靠链条上的任何一个上下文发生改动,其链条后的任何一个上下文均或许需求改动。
别的咱们要掌握好范畴责任,范畴之外的事不要管,一起范畴之间的数据交互,需求经过“防腐层”将范畴外的方针转换为范畴内方针。举个比方:下图是咱们酒店的抓取解析流程,重构前不只做了抓取和解析,还做了特别特点处理、视频处理等非自己范畴的工作,所以咱们重构后,将这两个工作让给了“酒店静态信息上下文”去处理,并构成抓取解析上下文,只做一件工作:从外部抓取数据,并将数据转换为Qunar内部方针。
-
运用程序架构落地COLA
现在比较盛行的运用架构,都会遵从一些一同形式,不管是六边形架构、洋葱圈架构、整齐架构、仍是COLA架构,都发起以事务为中心,解耦外部依靠,别离事务杂乱度和技能杂乱度。咱们终究挑选了COLA架构,有几点原因:
-
清晰的分层架构
一切的杂乱体系都会呈现出层级结构,运用体系处理杂乱事务逻辑也应该是分层的,基层对上层屏蔽处理细节,每一层各司其职,别离重视点
1、适配层:针对不同端、协议的适配,包含酒店根底信息指令执行、查询及适配回来等;
2、运用服务层:酒店根底信息事务用例辨认,并担任调用范畴层才干,对用例进行拼装、编列及回来成果;
3、范畴服务层:供给酒店根底信息相关事务才干,并针对杂乱或跨聚合事务供给范畴服务才干,供运用服务层调用;
4、根底设施层:主要处理技能细节问题的处理,包含范畴外部服务访问防腐层完成,数据库DB、缓存等耐久化。
扩展:咱们在整个战术规划的进程中,运用奥卡姆剃刀原理(是指如无必要,勿增实体,即“简略有用原理”)的思维,引入DP(Domain Primitive 是 Value Object 的进阶版,在原始 VO 的根底上要求每个DP具有概念的全体,而不只仅是值方针)并把实体特点归类,为 VO 的 Immutable 根底上添加了 Validity 和无状态行为,防止将过多的特点拍平到实体。
-
契合演进式架构规划
分层是归于大粒度的责任区分,咱们有必要往下再down一层,细化到包结构的粒度,才干更好的辅导咱们的工作。COLA架构除了有分层标准以外,对每一层内部的包结构也有清晰标准,即“聚合分包,功用分类”,这样的规划能够更好的应对未来需求改动的不承认性,契合演进式架构(演进式架构便是以支持增量的、非破坏的改动作为榜首准则,一起支持在运用程序结构层面的多维度改动。那怎么判断微服务规划是否合理呢?跟着事务的开展或需求的改动,在不断从头拆分或许组合成新的微服务的进程中,不会大幅添加软件开发和保护的本钱,而且这个架构演进的进程是十分轻松、简略的)。
COLA架构,本质上没有什么严厉的束缚,关于事务代码,仍是有十分好的辅导主张,不必定非要严厉的依照结构的要求来执行,但必定要有标准的思维,这才是中心的。实际开发中,咱们并没有彻底依照CLOA架构的辅导要求来,比方扩展组件并没有运用,适合自己的才最重要。信任只需咱们做好分模块,分层次,做好命名标准+必定的充血模型,代码就能做到简练易懂。
六、事例成果总结
(一)事例重构成果
1、事务杂乱度方面,咱们共整理188个事务用例,重构后保留109个,共下掉79个,事务平均下掉42%,关于下降产运研事务学习带来较大协助;
2、瘦身服务及减链路方面,酒店根底信息事务触及21个运用微服务,经过DDD范畴区分后下降到13个,微服务减少33%,对应代码下降状况统计,平均代码下掉58.3%,大大下降研制学习及硬件本钱;
3、事务专家方面,经过事件、指令风暴,关于项目成员对酒店根底信息事务更加有全局观,与产研构成一致言语和常识,减少产、运、测、研交流本钱,在事务专家方面添加2名研制事务专家,让咱们更多站在事务视角去考虑和处理问题,而不是来了需求首先想到的是工时问题;
4、功率提高方面,问题处理,工单处理下降50%。
(二)项目重构常见问题
-
没有范畴专家怎么办?
咱们都知道,事务范畴专家和开发团队之间的协作是DDD必不可少的部分,特别是战略、战术规划阶段。不过,寻觅到当时事务范畴中是专家以及能够为问题域供给深入见地的人,可谓是少之又少。那么假如没有范畴专家怎么办呢?作为替代,能够寻觅关于咱们当时工作范畴具有多年经历和了解的产品一切者、用户、研制或其他任何人,不必在意他们是不是权威,是不是管理者等等。
以咱们当时的重构项目为例,酒店根底信息产品流动率高,没有对应的产品事务专家,终究咱们寻觅到具有多年工作经历的资深研制和事务QA作为咱们的范畴专家,终究取得的作用也是十分不错的。咱们推荐的事务范畴专家顺序为:事务产品团队->技能担任人->事务开发担任人->事务QA。
-
简略问题杂乱化
1、DDD的价值在于协助管理显著优势的杂乱问题域,请不要小看MVC形式,由于并非体系一切的部分都要被精心规划。
咱们的酒店根底信息重构项目,有酒店、房型、图片等多个问题子域,以房型子域为例,有房型抓取、落地及房型聚合等多个限界上下文,其中房型聚合事务逻辑简略,明晰明了,所以咱们并没有选用DDD分层架构形式进行完成,而是运用MVC形式,不只缩短工期,且能够快速上线验证作用,所以咱们要避免将范畴模型运用到每个限界上下文。
2、处理方案并不总是技能层面。
当遇到项目问题时,咱们大部分人的思维是从完成上进行处理,比方技能完成考虑高并发、高可用及高性能,可是真的有必须要吗?这让我想起一句话:事务架构是灵魂,技能架构是容器,脱离灵魂得容器是没有意义的!以咱们的重构项目为例,咱们在进行事件风暴前的事务用例整理时,咱们把事务进行归类,关于非中心事务咱们会找相关事务运用方进行交流承认,是否能够下线,是否能够兼并,是否能够简化操作等等,终究咱们在事务杂乱度方面下降43%,节省很多的产研交流和研制本钱。
-
非中心范畴占用很多精力
咱们或许由于没有运用范畴愿景来描绘咱们项目的中心竞争力,导致咱们缺少对项目成败中心是什么的重视,而咱们的资源是有限的,时刻是有限的,咱们只需把有限的资源投入到最重要的区域-中心范畴,才干更好的服务于企业战略,完成商业价值。以咱们重构项目为例,咱们项目开始则高亮咱们的愿景,清晰中心范畴,把资深人员组织在中心的方位,保证中心范畴的研制和交付质量。在项目最重要的区域分摊太少的资源便是反形式。
-
产品不重视是否运用DDD,只重视需求是否如期上线
关于产品只重视自己的需求是否如期上线,这种状况十分常见,所以需求咱们要支付一些尽力来到达咱们做DDD重构的方针,我以为能够从以下几个方面下手:
1、讲清楚体系现状,以及运用DDD重构后所带来的价值,到达价值一致(与产品,必要或许需求跟产品的上级);
2、资源严重状况下,重要需求正常排期,非重要与产品交流延迟上线;
3、优先处理体系中心价值域问题,分阶段成果发布;
4、研制资源闭环和同享形式共存。关于闭环和同享解释如下(摘自“人人都是产品司理”):
闭环:便是和事务需求方绑定,专门做此类改动快的需求开发,其他的都不做;而同享则相反,将研制资源同享成一个池,一切的事务需求也汇总在一个或多个优先级队列里,排队开发。
同享:有利于充分运用研制资源,规模化、专业化,提高吞吐,但或许也下降了平均呼应时刻,更适合于进入成熟期,安稳渐进开展的事务。闭环,优先考虑专属事务需求的呼应,但也失去了规模与专业化效应,更适合快速开展期的立异事务,而过了事务高速期,专属的研制就会构成资源糟蹋,对个体的成长也有不利因素。
七、总结
本文以酒店根底信息DDD重构实践为事例,介绍了咱们为什么挑选DDD,完好的DDD落地流程结构,以及运用很多篇幅和比方介绍咱们项目落地实践的准则,最终介绍了事例成果和项目重构进程中常见的问题及处理方案,信任咱们对DDD有了更加明晰的认识,一起在项目落地时也有了一些清晰的辅导准则,避免踩坑。可是DDD不是灵丹妙药,更不是“银弹”,最终有几点主张送给咱们:
1、DDD是思维,是一种事务范畴建模方法论、事务架构规划方法论,是辅导开发进程的方法论。
2、DDD是事务+技能的一同深度参加,开发人员需求有考虑方法的改变,所以实践能否成功,不只仅是技能的问题,更是贯彻实施的问题。
3、战略规划阶段归于整个DDD中心阶段,范畴鸿沟区分关于团队的笼统才干有必定应战,请不要为了“省事”,最终做成了“精简版”的DDD。
好了,就写到这里,期待咱们都能够有机会运用DDD作为项目辅导和落地的方法论,并取得DDD所带来的价值体验~