草庐IT

领域驱动设计实践框架-COLA的解读

剑飞的编程思维 2024-03-28 原文

引言

        Cola作为当前比较优秀的领域驱动设计最佳实践框架越来越被更多的技术人所知晓。先抛出COLA 4.0:应用架构的最佳实践_张建飞(Frank)的博客-CSDN博客_cola架构 是关于COLA4.0最新的内容介绍。然后个人对于读了这篇文章后,对于其中的架构理念和其中的各组件的设计加了一点个人解读来分享。

        主要分为两部分来进行分析,一个架构,一个组件。架构主要想分析他的分层结构对于我们做技术架构设计和模块划分有的指导意义。组件主要就是对于一些编程的方法来解耦业务的最佳方法论。

COLA架构解析

下图转载 COLA 4.0:应用架构的最佳实践_张建飞(Frank)的博客-CSDN博客_cola架构

 垂直拆分

        从上往下分别有

  • VO:ViewObject  视图 也就是给用户看的数据,也称为Controller层
  • DTO:  DomainTransferObject 领域转化对象 也就是领域对象转换后的对象,也称为Service层
  • Entity:  Entity 实体  也就是代表具体有行为的实际对象,也成为Domain层
  • DO: DomainObject  领域对象,也就是领域对象,基础设施层

        为什么会产生这样的分层呢?我从最原始的时候开始说明,解说这个演变过程。

        最早的时候还是单体服务时候,也没有领域概念,有DAO层,实体层,服务(Service)层,控制(Controller)层,视图(View)层。后来为了提升开发效率,展示层和逻辑彻底分离,就有了前后端分离的技术,就弱化了视图层。只有控制层,形成统一的MVC架构。

        后来业务发展越来越多样化,视图层对于数据结构的需求越来越多,为了响应这种变化,同时保持业务的扩展性,就得在视图层和实体层增加一层数据转化层,用来应对各种各样的场景下的视图,就形成了DAO层,实体层,DTO层,服务(Service)层,控制(Controller)层。

        紧接着互联网进一步发展,业务进一步扩大,单体服务已经不能满足需求,就有了微服务。这时候服务的能力就进而被拆分成多层,有聚合层和基础服务层。此时分层服务层需求还可以满足,但是聚合层的话就难以清晰的表达了。因为聚合层可能会涉及到多个也业务域,而不同的业务域对于聚合层来讲又不能是实体层,也不能是服务层。因为如果实体层,聚合服务内的领域边界就很难清晰。如果是服务层,那么聚合服务的本身的服务层就被污染了。所以很多微服务的框架引入了一个Model层,他直接在聚合层把不同业务域分在不同的Model里面。不过此方案对于开发工作者来说有较高的要求,需要他能很好的了解领域划分。

        后来就进行了领域驱动设计,这个要满足的就是以领域驱动,还有就是编程思想的转变,以充血模型替代原来的贫血模型。他认为对象除了有属性职位还应该有行为,有动作,从而达到完整的对象的目的。属性和行为密不可分的。所以将实体层和DAO层整合到一起形成基础设施层。当从基础设施完成了对象的构造之后就形成了领域层,就是领域对象。实体层同时也需要定义对象的实际行为,基本的增删改查等等。DTO层保留,控制层和视图层也保留。但是这个时候DTO虽然依然是进行数据转化,但是他是严格遵循业务过程中领域上下文(AddCustomerCmd)的数据转化。

@Extension(bizId = Constants.BIZ_1)
public class CustomerBizOneConvertorExt  implements CustomerConvertorExtPt {

    @Autowired
    private CustomerConvertor customerConvertor;//Composite basic convertor to do basic conversion

    @Override
    public CustomerEntity clientToEntity(AddCustomerCmd addCustomerCmd){
        CustomerEntity customerEntity = customerConvertor.clientToEntity(addCustomerCmd);
        CustomerDTO customerDTO =addCustomerCmd.getCustomerDTO();
        //In this business, AD and RFQ are regarded as different source
        if(Constants.SOURCE_AD.equals(customerDTO.getSource()))
        {
            customerEntity.setSourceType(SourceType.AD);
        }
        if (Constants.SOURCE_RFQ.equals(customerDTO.getSource())){
            customerEntity.setSourceType(SourceType.RFQ);
        }
        return customerEntity;
    }
}

此时的各个层之间的交互数据不再是对象或者其他,而只能是有领域边界定义的限界上下文。领域的划分和限界上下文的定义,请参考 猿创征文|微服务架构领域驱动设计(DDD)_剑飞的编程思维的博客-CSDN博客_微服务拆分 领域驱动设计

水平拆分

        从左往右分别有

  • VO:手机端,小程序端,浏览器端,消息,调度任务
  • DTO:  服务,执行器
  • Entity:  接口,模块,能力
  • DO: 接口实现,仓库,配置

        水平拆分的目的是在于在同一个逻辑层次,由于应用域不一样,使用的方法差别比较大,比如手机端和小程序端返回的数据差别和功能迭代差别较大,所以需要拆分到不同的类别。再就是执行器和服务,服务完成了功能,但是有时候再执行服务的时候可能会有相关联的业务操作,这个时候需要用执行器包装,但是他要跟服务解耦,所以要拆分。防腐层,模块和能力都是根据具体的业务做的一个划分,主要是是根据职责划分。践行单一职责原则,迪米特法则。

COLA组件

        组件解决是是我们再日常开发服务中经常要用到的一些功能,封装后我们可以直接复用。同时也是可以规范我们的开发能力,不会导致代码风格混乱,从而提升开发效率。

Catchlog组件

        通过定义切面,对于请求处理前后,进行日志打印,接口监控。同时定义响应体的统一处理接口,为统一处理提供一个可扩展点

Domain组件

        通过多例模式,实现了充血模型的开发。为什么要用多例?首先Spring的创建的Bean模式单例的,然后充血模型的实例中是有属性的,那么他的行为只能在当前线程中安全,如果是单例,那么线程不安全,所以必须要是多例模式。应用了工厂模式生成多例。

DTO组件

        定义数据转换的基本结构,父类ClientObject,Command,Response,DTO等等,扩展点名称等统一定义父类,形成多态,定义转化数据的基本规范和职责

Exception组件

        定义服务中的异常,系统异常,业务异常,检查异常

Extention组件

        扩展点的定义以及组装,通过函数接口,提取出扩展点,如图

 函数接口,以及starter组装,扩展点的适配缓存都是较好的编程风格

StateMachine组件

        这个状态机的核心思想就是把一些状态流程,流程化的开发通过定义全局结构,实现逻辑和代码的接口。核心的就是泛型的使用,状态流转的对象就是变更前,变更后,然后上下文主要对象。

        除了以上的组件外,在开发中我们可能对于一些基本的操作都需要封装成组件,以供开发规范使用。

总结

        分析Cola除了我们可以在开发过程中去直接引用这个框架外,更重要的是我们可以改变我们的编程思维去学习这个思考过程,学习编程方法,应用到我们实际的项目中,让我们朝着更优秀的程序员前进。

        

        

有关领域驱动设计实践框架-COLA的解读的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  4. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

  5. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  6. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  7. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  8. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  9. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  10. ruby-on-rails - Rails 中同一个类的多个关联的最佳实践? - 2

    我认为我的问题最好用一个例子来描述。假设我有一个名为“Thing”的简单模型,它有一些简单数据类型的属性。像...Thing-foo:string-goo:string-bar:int这并不难。数据库表将包含具有这三个属性的三列,我可以使用@thing.foo或@thing.bar之类的东西访问它们。但我要解决的问题是当“foo”或“goo”不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是“Whazit”的实例,只是数据不同。所以现在事情可能看起来像这样......Thing-bar:int但是现在有一个新的模型叫做“Whazit”,看起来

随机推荐