领域驱动设计

网友投稿 250 2022-11-04


领域驱动设计

想了解一下什么是领域驱动设计,没想到一大堆新奇的名词汹涌而出,查资料查到手软,仿佛捅了马蜂窝。

一、什么是领域驱动设计

二、领域驱动设计的优缺点

三、领域驱动适用场景

以上三个问题,只能是列出问题,而无答案,变成问题三连。因为我搜了很多文章,都搞不清楚这个所谓的领域驱动是个啥,有啥好处,用在何种场景。所有文章都说了一大堆,包括标题带有“浅析”字样的文章,但我怎么都读不懂,不明就里。

真相可能就是,所谓的领域设计纯属扯淡。凡自己都扯不清的东西,要么是作者本人没有真正理解,要么是这个东西行不通。就好比九阴真经最高层,其实是作者自己的臆想,根本没有经过实践检验。我怀疑这个领域设计也是如此,没见过哪个项目是用领域驱动设计架构的。这里仅做些记录,姑妄听之,将信将疑。

领域驱动设计(Domain-Driven Design,简称DDD),顾名思义,就是由领域,即业务,来主导信息系统的设计。信息系统用于满足业务的需求,而在通常的开发过程中,不管啥业务,基本上开发的套路,系统所采用的架构,都是一样的,比如分层结构,系统分为UI层、逻辑层、服务层、数据持久层等等。这听起来,就好像有点削足适履,因果颠倒了。领域驱动设计反其道而行之,意图立规矩,要技术适应业务,而不是业务适应技术。

具体点,领域驱动设计似乎要实现的是,因应业务的特点来选择合适的架构(据说有一种敏捷开发方法叫水晶方法,特点就是项目类型不同,开发方法就不同,与之点相似)。对于同一领域的信息系统,要千方百计抽象出一个领域层,就是这种业务的核心的、共性的东东。这层东东,对于该种业务来说,是相对稳定、极少变化的,抽象出来,不管你采用什么技术来实现,怎么优化,都不会影响到这一层。而在我们常用的分层架构中,上层依赖下层,而包含业务性的东西,往往处于很下面的层次,里面包含了许多的调用、实现,所以程序重构、优化,往往首当其冲。而领域驱动设计里,不是分层,而是采用六边形架构,领域层处于核心,通过依赖注入来解耦外层对它的影响。

软件系统从来都不是凭空而来,而是以软件的形式解决特定的问题。当我们面临现实世界的复杂问题时,如何以软件的形式落地?领域驱动设计是一套方法论,指导我们将复杂问题进行拆分、拆分出各个子系统间的关联以及是如何运转的,帮助我们解决大型的复杂系统在落地中遇到的问题。

Evic Evans(领域驱动设计的提出者)在著作中将软件系统的设计分为2个部分:战略设计和战术设计。在战略设计层面提出了域、子域、限界上下文等重要概念;在战术设计层面提出了实体、值对象、领域服务、领域事件、聚合、工厂、资源库等重要概念。如图1所示:

图1 战略设计与战术设计

战略设计部分指导我们如何拆分一个复杂的系统,战术部分指导我们对于拆分出来的单个子系统如何进行落地,在落地过程中应该遵循哪些原则。

四、相关名词

1、贫血、充血模型 【失血模型】模型仅仅包含数据的定义和getter/setter方法,业务逻辑和应用逻辑都放到服务层中。这种类在Java中叫POJO,在.NET中叫POCO。

【贫血模型】贫血模型中包含了一些业务逻辑,但不包含依赖持久层的业务逻辑。这部分依赖于持久层的业务逻辑将会放到服务层中。可以看出,贫血模型中的领域对象是不依赖于持久层的。

【充血模型】充血模型中包含了所有的业务逻辑,包括依赖于持久层的业务逻辑。

【胀血模型】胀血模型就是把和业务逻辑不想关的其他应用逻辑(如授权、事务等)都放到领域模型中。感觉胀血模型反而是另外一种的失血模型,因为服务层消失了,领域层干了服务层的事,到头来还是什么都没变。

在领域驱动设计中,采用充血模型。

2、六边形架构

一般我们都采用分层架构,如下图。但由于业务逻辑负责实现,与更底层的数据持久层交互,被上面的服务层(或叫应用层)所依赖,当服务层调整或优化时,可能会导致业务逻辑层也会被改动。按道理,业务逻辑层只负责业务,现在被其他因素导致变动,城头失火,殃及池鱼,不够合理。为了将业务与具体实现做分离,可以采用依赖倒置的手段去重构。

方法就是我们的架构就不再是分层的结构(从上往下调用),而是将业务逻辑抽象出一个domain层(领域层),将细节全部往应用层(application)和基础层(infrastructure)堆,领域层居于中心位置,通过接口形式调用应用层和基础层的方法,依赖倒置,运行时通过注入对象方式来实现。

领域层越抽象越稳定,越能减少外层变动对领域层的冲击。其实,这也是领域驱动设计的核心思想。

【适合场景】 读/写比较大的场景 对查询实时性要求不高的场景 内部状态改变会触发各种数据的同步,如课程完成,课程发布等等等等。。。 外部实现可替换,如mq可以随意替换实现

【不适合场景】: 只有简单CRUD的业务,没有重的业务逻辑,不适合搞那么复杂,因为没必要抽出domain层

3、GRASP(通用职责分配软件模式) GRASP(General Responsibility Assignment Software Patterns,通用职责分配软件模式)

说到模式,最有名的莫过于GOF设计模式了。按我的理解,这里的GRASP,是系统分析阶段的建模模式,GOF是系统设计、开发阶段的设计模式。

GRASP能够帮助我们理解基本对象的设计,提高面向对象设计(OOD)的觉悟。GRASP的9个模式企图解决的问题只有一个:如何建模,如何划分、设计对象,一个系统应该有多少个对象,每个对象应该包括哪些功能,不应该包括哪些功能,对象之间应该建立怎样的关系。通用职责分配软件模式,顾名思义,一个对象应该实现哪些功能由其承担的职责决定,即职责驱动对象设计。

创建者(Creator) 信息专家(Information Expert) 低耦合(Low coupling) 控制器(Controller) 高内聚(High Cohesion) 多态性(Polymorphism) 纯虚构(Pure Fabrication) 间接性(Indirection) 防止变异(Protected Variations)

设计阶段,除了设计模式,还有设计SOLID原则,大家耳熟能详。它们与上面的GRASP有相似的地方。

Single Responsibility Principle:单一职责原则 Open Closed Principle:开闭原则 Liskov Substitution Principle:里氏替换原则 Law of Demeter:迪米特法则 Interface Segregation Principle:接口隔离原则 Dependence Inversion Principle:依赖倒置原则

4、CQRS(命令查询职责分离) CQRS(Command Query Responsibility Segregation,命令查询职责分离)。意思就是查询与命令(增删改)分开,各使用不同的模型。

一般来说,我们对数据库的操作CRUD,都用同一种模型。而CQRS 则做了改变,将这个模型拆分成命令和展示两部分,分别叫做 Command 和 Query。把模型拆开来,这意味着可以用不同的逻辑进程、不同的硬件来做这两部分事情了。一个 WEB 上的例子,用户查看页面的时候使用查询模型;而如果要改变数据,这种改变会解析成若干命令模型来执行操作,操作完毕后通知状态的更新。

好处是在操作层面上读写分离,提高针对性,降低复杂度。

5、关注点分离 关注点分离(Separation of concerns,SOC)是处理复杂性的一个原则。由于关注点混杂在一起会导致复杂性大大增加,所以把不同的关注点分离开来,分别处理就是处理复杂性的一个原则,一种方法。

日常生活和生产中,关注点分离是广泛使用的、解决复杂问题的一种系统思维方法。大体思路是,先将复杂问题做合理的分解,再分别仔细研究问题的不同侧面(关注点),最后综合各方面的结果,合成整体的解决方案。

关注点分离也是计算机科学和软件工程在长期实践中确立的一项方法论原则。模块化就是其中的代表。同时它也是面向对象的程序设计的核心概念。

2021.05.10 我觉得微服务架构也算是关注点分离的一个实例。微服务架构,将原本庞大的单体项目,分解成若干个小系统,解决了问题的复杂性。

​​领域驱动设计​​​​领域驱动设计的优点和挑战​​​​说说领域驱动设计和贫血、失血、充血模型​​​​领域驱动设计详解:是什么、为什么、怎么做?​​​​六边形架构和分层架构的区别​​​​GRASP模式概述​​​​DDD 中的那些模式 — CQRS​​

2022.07.05 我感觉,如果真的存在一个所谓领域共性的东西,那它就不应该跟其他代码挤在一个项目里,而是采用微服务,或者SOA架构,将领域层单独做成一个服务。把业务共性的东西,放在每个项目里,本身就不是设计之道,反而去扯什么信息开发技术适应业务,根本就是搞错了方向。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:使用SpringBoot跨系统调用接口的方案
下一篇:MFC菜单设计错误
相关文章

 发表评论

暂时没有评论,来抢沙发吧~