ddd是什么意思:Thinking in DDD

DDD的落地,主要有三个方面需要理清:第一,以何种应用架构进行落地;第二,核心组件及其生命周期,相互之间的交互逻辑;第三,不同限界上下文之间如何集成。

本文将重点分析DDD落地的应用架构,其余两个方面后续会专门去展开。

DDD的实现架构有很多,有经典四层架构、六边形(适配器端口)架构、整洁架构(clean architecture)、CQRS架构等,相信很多读者跟我刚开始接触时一样,完全不知道该选择什么架构进行落地。

ddd是什么意思:Thinking in DDD

ddd是什么意思:Thinking in DDD

ddd是什么意思:Thinking in DDD

本文不会逐个去讲解这些架构,而是从我们日常的三层架构出发,带领大家思考适合我们落地的架构。

我们很多项目是基于三层架构的,其结构如图:

ddd是什么意思:Thinking in DDD

我们说三层架构,为什么还画了一层Model呢?因为Model只是简单的Java Bean,里面只有数据库表对应的属性,有的应用会将其单独拎出来作为一个maven模块。

接下来我们开始对这个三层架构进行抽象精炼。

第一步,数据模型与数据访问层(持久层)合并

ddd是什么意思:Thinking in DDD

为什么数据模型要与数据访问层合并呢?首先,数据模型与数据库表结构的字段是一一对应的,数据模型最主要的应用场景就是持久层用来进行ORM,给Service层返回封装好的数据模型,供Service执行业务;其次,数据模型的Class或者属性字段上,通常带有ORM框架的一些注解,跟持久层联系非常紧密,根据单一职责的原则,我认为数据模型就是持久层拿来查询或者持久化数据的,数据模型脱离了持久化层,意义不大。

第二步,从Service抽取业务逻辑

常见的Service方法,既有缓存、数据库的调用,也有实际的业务逻辑,整体过于臃肿。

先看现在的Service方法的伪代码:

public void businessLogic(Param param){  if(checkParam(param)){    throw new XXXException();  }  Data data=new Data();//或者是mapper.queryOne(param);    data.setId(param.getId());    if(condition1=true){    biz1=biz1(param.getProperty1())    data.setProperty1(biz1);  }else{    biz1=biz11(param.getProperty1())    data.setProperty1(biz1);  }  if(condition2=true){    biz2=biz2(param.getProperty2())    data.setProperty2(biz2);  }else{    biz2=biz22(param.getProperty2())    data.setProperty2(biz2);  }  //一堆set方法  ……  mapper.updateXXXById(data);  cache.del(data);//删除缓存  mpPublisher.publish(data);//发出消息}

这是典型的事务脚本的代码:先做参数校验,然后通过biz1、biz2等子方法做业务,并将其结果通过一堆Set方法设置到数据模型中,再将数据模型更新到数据库。

由于所有的业务逻辑都在Service方法中,造成Service方法非常臃肿,Service需要了解所有的业务规则,并且要清楚如何将基础设施串起来。同样的一条规则,例如if(condition1=true),很有可能在每个方法里面都出现。

我们知道,专业的事情就该让专业的人干。既然业务逻辑是跟具体的业务场景相关的,我们想办法把业务逻辑提取出来,形成一个模型,让这个模型的对象去执行具体的业务逻辑,即提供业务能力。这样,Service方法就不用再关心里面的if/else业务规则,只需要给业务模型执行的舞台,并提供基础设施完成用例即可。

将业务逻辑形成模型了,这样的模型,就是领域模型。

我们先不管领域模型怎么得到,总之,拿到Service方法的入参之后,我们通过某种途径得到一个模型,我们让这个模型去做业务逻辑,最后执行的结果也都在模型里,我们再将模型写回数据库,当然,怎么写数据库的我们也先不管。

抽取之后,将得到如下的伪代码:

public void businessLogic(Param param){  if(checkParam(param)){    throw new XXXException();  }  Domain domain=loadDomain(param);    domain.doBusinessLogic();  saveDomain(domain);  cache.del(domain);//删除缓存  mpPublisher.publish(domain);//发出消息}

根据代码,我们已经将业务逻辑抽取出来了,领域相关的业务规则封闭在领域模型内部。此时Service方法非常直观,就是获取模型、执行业务逻辑、保存模型,再协调基础设施完成其余的操作。

抽取完领域模型后,我们工程的结构如下图:

ddd是什么意思:Thinking in DDD

第三步,维护领域对象生命周期

在第二步中,loadDomain、saveDomain两个方法还没有得到讨论,这两个方法跟领域对象的生命周期息息相关。

不管是loadDomain还是saveDomain,我们一般都要依赖于数据库或者其他中间件,所以这两个方法对应的逻辑,肯定是要跟DAO产生联系的。而保存或者加载领域模型,我们可以抽象成一种组件,这种组件就是Repository。

注意,Repository加载或者保存领域模型,方法的入参或者出参,一定是基本数据类型或者领域内定义的类型,而不能是表数据模型。

以下是Repository的伪代码:

public interface DomainRepository{    void save(Domain domain);  Domain load(DomainId id);//假设是领域模型ID,也可能是其他的入参}

既然DomainRepository与底层数据库有关联,但是我们现在DAO层并没有引入Domain这个包,DAO层自然无法提供DomainRepository的实现,我们初步考虑可以将这个DomainRepository实现在Service中。

我们再推敲推敲,如果我们在Service中实现,势必需要在Service中操作数据模型:查询出来数据模型再封装为领域模型、或者将领域模型转为数据模型再通过ORM保存,但这个过程不该是Service层该关心的。

所以,我们决定在DAO层直接引入Domain包,并在DAO层提供DomainRepository接口的实现,DAO层的Mapper查询出数据模型之后,封装成领域模型供DomainRepository返回。

此时DAO层不再向Service返回数据模型,而是返回领域模型。

现在,我们项目的架构图是这样的了:

ddd是什么意思:Thinking in DDD

第四步,泛化

在第三步中,我们的架构图已经跟经典四层架构非常相似了,我们再把格局放大点,对整个架构进行泛化抽象。

首先,DAO层其实属于基础设施层,只不过其职责是持久化和加载聚合,所以,我们将DAO层改名为
Infrastructure-Persistence,可以理解为基础设施层持久化包。之所以采取这种Infrastructure-XXX的格式进行命名,是由于Infrastructure可能会有很多的包,分别提供不同的基础设施支持。一般的项目,还有可能需要引入缓存,例如Redis,我们就可以再加一个包,名字叫Infrastructure-Cache或者Infrastructure-Redis。

注意:为了确保领域层知识的完备,Infrastructure层应该实现Domain层定义的基础设施接口,而不是向上层提供没有在领域层定义过的组件。

然后,Controller层其实就是用户接口层,即User Interface层,我们在项目叫Interfaces。Controller层的名字有很多,有的叫Rest,有的叫Resource,考虑到我们这一层不只是有Rest接口,还可能还有一系列的拦截器,所以我一般比较随意的称之为Web。因此,我们将其改名为Interfaces-Web,即用户接口层的Web包。同样,我们可能会有很多的用户接口,但是他们通过不同的协议对外提供服务,因而被划分到不同的包中。我们如果有对外提供的RPC服务,那么其服务实现类所在的包就可以命名为Interfaces-Provider。

有时候引入某个中间件,既会增加Infrastructure也会增加Interfaces。例如,如果引入Kafka就需要考虑一下,如果是给Service层提供调用的,例如逻辑执行完发送消息通知下游,那么我们再加一个包Infrastructure-Publisher;如果是消费Kafka的消息,然后调用Service层执行业务逻辑的,那么就可以命名为Interfaces-Subscriber。

最后,Service层目前已经没有业务逻辑了,业务逻辑都在Domain层去执行了,Service只是提供了应用服务,用于将领域的业务逻辑、领域服务封装为用例,所以,我们把Service层改名为Application层。

经过第四步的抽象,其架构图为:

ddd是什么意思:Thinking in DDD

在这个架构图中,经典四层架构的四层都出现了,整个架构图长得跟六边形架构也很像。这是为什么呢?其实,不管是经典四层架构、还是六边形架构,亦或者整洁架构,都是对系统应用的描述,也许描述的侧重点不一样,但是描述的是同一个事物。既然描述的是同一个事物,长得像才是理所当然的。

对于任何一个应用,都可以看成“输入-处理-输出”的过程。

“输入”环节:通过某种协议对外暴露领域的能力,这些协议可能是REST、可能是RPC、可能是MQ的监听器,也可能是WebSocket,也可能是一些任务调度的Task;

”处理“环节:处理环节是整个应用的核心,代表了应用具备的核心能力,是应用的价值所在,应用在这个环节执行业务逻辑。

“输出”环节,业务逻辑执行完成之后将结果输出到外部。

不管我们采用的什么架构,其描述的应用的核心都是这个过程。正如《金刚经》所言:一切有为法,如梦幻泡影,如露亦如电,应作如是观;凡有所相,皆是虚妄;若见诸相非相,即见如来。

第五,完整的包结构

将第四步中出现的包进行整理,并加入启动包,则得到如下完整的包结构。

由于有很多的User Interface,所以启动类应该存放在单独的模块中,又因为application这个名字被应用层占用了,所以将启动类所在的包命名为launcher。

包结构如图所示:

ddd是什么意思:Thinking in DDD

至此,DDD项目的整体结构基本讲完了。

本文链接:https://www.dzdvip.com/36130.html 版权声明:本文内容均来源于互联网。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 395045033@qq.com,一经查实,本站将立刻删除。
(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022年7月28日 22:51
下一篇 2022年7月28日 23:18

相关推荐

  • 长沙塌楼事故原因(长沙房屋倒塌事件原因)

    从倒塌前后拍摄的照片,再结合百度街景和谷歌卫星图像等分析不难看出,该倒塌楼栋的上半身有明显的加盖现象,是经过比较严重的改装,特别楼顶有比较突出的大铁棚加盖,并且整体的改装面积也不小! 自建房倒塌 据媒体报道:湖南长沙一自建房发生倒塌,目前尚有多名人员被困和失联,在这里宇宙祝福,被困人员和失联人员,能够早日得到救援,逃出生天。在该事件发生后,党和国家高度重视,派遣了大量的专家和救援团队,亲临现场展开施救。 自建房 本文我们将深度分析,房子为何会倒塌,自建房都存在着哪些安全隐患。房子是我们所居住的唯一地方,它可以保护我们在冬天不受到寒冷的侵袭,夏天更是能够躲避酷暑的温床,那么同理,房子的安全性至关的重要,因为它不仅能够保护我们的生命,同样的也有可能会结束我们的生命。 自建房相信大家都熟悉,除了在城市里的有钱人买的房子外,几乎大部分的农村人,使用的房子都属于自建房,自建房的优势在于,在自己家中,只需要稍微的对房屋改造,或者直接拆了重建,这样可以节省更多的成本。 那么按理来说自建房应该是非常结实的。其实自建房大多数采用的是砖墙结构,这种房子的坚固性肯定无法和钢筋混凝土结构相抗衡,但是也足够一个家庭使用几十年了。 摧毁房屋 要知道,只有在大灾大难面前,房子结构才有可能遭到摧毁,比如地震,由地底释放巨大的能量,在传播到地面时候,能够造成地动山摇,超强的地震可以轻而易举的摧毁掉房屋,即使再坚固的房子,在超级地震的作用下,都有可能会被摧毁掉。 两大原因 而有些自建房在建造的过程中,会存在着诸多的问题,其一节省成本,其二胡乱改造。我们先说第一点节省成本,大多数的自建房是给我们自己家人住的,因此在建造上,我们肯定以安全为主,但是还有一部分自建房,是给别人居住的,或者是租售出去的。 偷工减料 在建造上,原本的材料可能会减少,这样就造成了房子的不稳定性。实际上,不仅仅是我们自己盖得房子,甚至有时候买的房子,宣传上说的堪称完美,到了一看,才发现全TM是扯淡。 一般房子坍塌的大多数原因,都来自于承重墙的作用。承重墙是房子最重要的位置,它承载了巨大的重量,将房子支撑起来。相信大家在网上看过一些视频,拆房子的时候,只需要将承重墙、承重柱或者承重梁直接拆掉,然后整个房子就瞬间变成一片平地了。 胡乱改造 不过值得一提的是,承重墙的能力是有限的,这也是为何专家提醒大家,不懂就别瞎改造房子。因为很多事故都…

    2022年5月2日
    71
  • 企业站SEO优化都应该了解的10个知识点

    我们知道SEO是一个经验与技术的艺术品。 基于大量的经验与SEO技巧的融合,我们才能够在短期内快速地提高整站信任度与质量。 因此,我们在做SEO项目的时候,总是会遵循一些规则。 那么,SEO人员,值得关注的10个十字箴言有哪些?根据以往SEO经验分享,蝙蝠侠IT,将通过如下内容阐述: 1、转化 我们都知道SEO是一个复杂的排名过程,但在过于完美的SEO技术,最后我们都需要面临转化的问题,在做好技术的同时,我们还是需要做好销售的相关性工作。 2、排名 不要过分地追求网页的排名策略,我们需要思考的是,每个页面参与排名的理由,有什么理由搜索引擎会将你排名在搜索结果的首页。 3、市场 搜索引擎算法总是在不断地调整的,我们在日常经验积累的同时,还需要更好的了解搜索行业的目标市场情况,这样才能合理的制定下一步计划与策略。 4、记录 对于不同网站类型的行业,我们在制定优化策略的时候,总是有一定差异化,这一点对于新手SEO而言,总是被忽略的,这就需要我们在日常工作中,记录哪些方法有效,而哪些无意义。 5、专家 并不是每一个SEO从业者,都需要变成SEO专家,我们不需要做一个全方位的从业者,你只需要专注于可以持续给你带来高效回报的行业即可。 6、思维 对于任何一个SEO从业者,我们在做排名的过程中,总是存在一些定式思维,比如:内容、结构、排名等一体化的优化策略,而偶尔缺乏创新,特别是在站内结构上。 7、优势 我们知道企业站优化是一个资源性的工作,你可能需要具备一定SEO资源,如果你刚好在某一方面有独特的资源,我们认为你需要合理的利用它,比如:高质量的新闻媒体渠道,可以建立高质量外链。 8、原理 任何一个搜索引擎排名的策略,都是基于一定搜索原理的,如果你打算长期在SEO领域工作,我们认为每一个SEO从业者都有理由去学习一下相关性的搜索引擎原理。 9、竞价 当我们谈论SEO的时候,就会必然地关联到SEM,从目前来看,搜索流量,我们是无法规避SEO SEM二者之间的关系,相反,我们则需要思考,该如何更好的利用二者。 10、创新 任何事物在长期发展的过程中,总是动态变化的,需要创新的,这一点SEO也不例外,特别是当下的搜索需求,会随着时间的推移而改变,因此,我们每隔一定时间,就需要调整一次关键词词库,重写最新搜索需求。

    2021年6月16日
    11
  • 6个高效率良心软件推荐

    高手之所以能比普通人效能更高,不仅仅是因为他们掌握了解决问题的方法论,还因为他们有快速提高效率的工具,今天给大家分享6个职业高手常用的高效率小工具,让你也能提高工作效率找到自己的工作节奏。

    2021年5月15日
    11
  • 百度将全行业切换基木鱼怎么办:百度小程序,是基木鱼的补救丹?

    去年上半年,业内就开始不断的流传百度要全面切换基木鱼全行业托管,我们也一直密切关注着行业内最新消息。
    在近日,百度正式下发通知,要求各行业开始陆续切换使用托管页,预计于9月30日逐步完成全行业托管。

    2021年4月19日
    26
  • 烟台大学是几本(烟台大学是一本大学还是二本大学)

    “ 烟台大学在山东省是一本。烟台大学(Yantai University)位于山东省烟台市,是山东省属重点综合性大学,山东省“一流学科”建设单位,山东特色名校工程重点建设高校、山东省“强特色”建设高校和“高水平学科”建设高校。” 烟台大学是几本 烟台大学是一所本科大学,它的招收层次涵盖了本科一批、本科二批和本科三批,还有预科班以及研究生教育。在录取分数线上高于二本线,在一本线和二本线之间,因此我们通常说烟台大学是二本大学。 烟台大学是山东省属重点综合性大学,烟台大学在山东省是本科普通批次招生,我们可以说烟台大学是本科大学。如果不是山东考生,烟台大学在考生所在的省份是本科第二批次招生的话,我们也可以说烟台大学是二本大学。 从录取分数线上来看,烟台大学高考招生录取的分数高于二本分数线,在一本线和二本线之间,尤其是烟台大学的王牌重点专业,如法学专业,生物科学专业,药学专业以及化学专业等,分数线都是在一本线左右甚至高于一本线。 烟台大学介绍 烟台大学坐落于国家历史文化名城、最佳中国魅力城市、山东新旧动能转换综合试验区核心区之一——烟台,是国内距海最近、拥有海岸线最长的滨海大学,是山东省属重点综合性大学。 烟台大学重点专业 国家级特色专业(4个):法学、应用物理学、药学、电子信息科学与技术。 省级品牌和特色专业(12个):电子信息科学与技术、应用化学、化学工程与工艺、国际经济与贸易、机械设计制造及其自动化、土木工程、建筑学等。 省级成人高等教育品牌专业(1个):法学专业和国际经济与贸易。 烟台大学是211还是985大学? 都不是。烟台大学既不是211大学,也不是985大学。 学校拥有一支学历结构、年龄结构、职称结构、学缘结构、学科(专业)结构比较合理的师资队伍。现有专任教师1300余人,副高级以上专业技术职务人员667人,具有博士学位者405人,占专任教师的33%,硕士以上学位人员占专任教师的78%。现有中国工程院院士1 人,”首届全国百名教学名师”1人,”新世纪百千万人才工程”国家级人选1人,享受国务院政府特殊津贴专家14人。 烟台大学有几个校区及校区地址 烟台大学现在有2个校区,分别为烟台大学东校区和烟台大学西校区。 1、烟台大学南校区 烟台大学南校区位于烟台港城东大街100号,为烟台大学附属校区。2004年为解决学生的住宿…

    2022年8月4日
    43
  • 二月二龙抬头的来历和风俗(二月二龙抬头的来历和寓意)

    农历二月初二,是民间俗说的龙抬头,也有的地方叫农事节、春耕节,或者青龙节、春龙节,处于二十四节气中的惊蛰前后。老百姓为什么把这天叫做龙抬头?应该与天象及时令有关,源于远古时代人们对自然天象的崇拜与惧怕,也是农耕文化的雏形。龙指的是二十八宿中的东方苍龙七宿星象,每年的仲春卯月(斗指正东)之处,“龙星角”就从东方地平线上升起,龙抬头由此而来,意为龙结束了冬眠的潜伏状态,醒过来了,要出现在地表面上,露出头角,也指经过冬眠,百虫复醒。从时令讲,农历二月初二,处在雨水、惊蛰、春分三个节气之中,属于仲春。农历一年分十二个月,春夏秋冬各三个月,每三个月为一季,春季正月为孟春,二月是仲春,三月为季春。冬去春来,大地复苏,阳气生发,雨水增多,万物盎然,忙碌的春耕开始了。于是,人们把这一天看作新年起始的好日子,祈求人间大地万象更新、纳祥运转、一年顺顺当当。 流传久远的民俗,包括一些民间禁忌,是人与自然历经百战进退达成的和解,也是天人相应的一个文化符号,不是古人凭空捏造的。在二月二这样特别又重要的日子里,各地的人们就想出一些具有各自特色的纪念活动,如我老家山东潍县一带的二月二剃头、吃料豆、吃面旗子、填粮仓、撒灰辟虫害等,都是非常有讲究的风俗,传至今日依然行之。二月二剃头攀附龙抬头之意,像龙那样昂起头、扶摇直上、气冲云霄,还有焕然一新、从头开始的寓意。当然,还与山东人正月里不剃头的习俗有关。有的地方说正月里剃头死舅舅,在宗亲关系中外甥与舅舅很是亲近,有了这个习俗和说法,有舅舅的外甥绝不敢贸然行事,怕舅舅知道了惨遭臭骂甚或暴打一顿。其实正月不剃头的原意并非死舅舅,而是“思旧”。一般说过年前都要剃剃头、洗洗澡,干干净净、利利索索过大年。年后人们又有一种对过去一年的恋恋不舍之情,年前剃了头的样子已属“旧貌”,留住“旧貌”便也是留住了过去的一年,是个想头。日本人过元旦新年不叫“迎新”,也不叫“辞旧”,而是叫“忘年”,字面看似有忘记的意思,实则是“不忘”“纪念”,一步三回头。每到年底,日本人会聚到一起举行“忘年会”,有的人借酒念旧,哭得稀里哗啦。一衣带水,日本的民俗或许是从山东漂洋过海而去。时到二月二,龙抬头,气象万千,讨个好口彩,与龙一起飞舞,于是,山东人纷纷剃头,“旧貌”换“新颜”。我想这应该就是山东人正月不剃头、二月二剃头的大概来历。 我是一直遵循着正月里不理发这个习俗的。我有三个舅舅,大舅去…

    2022年3月4日
    13