本文上回书接《这是DDD建模最难的部分(其实很简单)》,欢迎关注我的同名公众号。
https://mp.weixin.qq.com/s/HZKMLF0_I10iczzp2mAR-w
 

故事背景

2013年中,我们的Java后端团队为了落地DDD,全面引入了dotnet技术栈,具体过程和成果,可以看我的B站频道《Java8 到 .NET8,团队升级报告 - 第二弹》https://www.bilibili.com/video/BV14YgYedE1f
 
在近半年的时间,我将自己落地DDD的实践经验进行提炼和总结,以公众号文章和B站视频的方式分享出来,与更多的网友建立链接和交流,得到了很多肯定反馈,也因为大家提供的视角,使得我自己对DDD的认知有了更深层次的迭代。
 
目前我们借助dotnet强大的生态以及csharp优良的语言设计,已经可以非常丝滑地用代码表达模型和业务,整个软件交付的体验和效率,获得了前所未有的进步。我们netcorepal-cloud-framework框架在这个过程中也得到了进化和可用性验证,我们坚信找到了一套更加务实的软件设计认知和方法论。
 

Javaer太难了

由于我们团队实际上还是Java和csharp双技术栈,于是我们萌生了一个想法,是否可以让我们的Java项目交付过程也如此地丝滑?带着这个想法,我们开始在Java生态中寻找可以帮助我们构建出类似csharp框架效果的组件:
 
  • Web框架: aspnetcore vs springboot
  • ORM:EntityFrameworkCore vs JPA
  • 中介者模式:MediatR vs ?
  • 事件的最终一致性实现:CAP vs ?
 
其中“中介者模式”和“事件的最终一致性”实现我们没有找到合适的替代品,经过分析,“中介者模式”并不是必须的,虽然最终实现起来,没有csharp那么优雅,但并不影响对建模设计的实现,但“事件的最终一致性”这个组件,我们认为是必不可少的,我们建模最底层的模型就是“命令-事件”模型,没有事件处理的健壮性,意味着最终系统的健壮性无法保障,最终无法满足业务对可用性的要求。
 

事件的最终一致性

 
在我们的建模模型中,是在命令处理逻辑中,由领域模型发出事件,而事件如果要在微服务间传递,我们期望达到的效果如下:
 
  1. 如果命令处理逻辑成功,即对应的数据库事务提交成功,则确保事件一定能够发出;
  2. 如果命令处理逻辑失败,即对应的数据库事务回滚,则确保事件一定不发出;
 
在需求层面,我们并不要求系统确保事件“确定只发一次”,我们知道,这个要求的技术实现难度远远大于前面的两个要求,而且业务可以做幂等处理解决重发的问题。
 
下图展示了我们csharp版本中关于“命令-事件”的建模实现,以及事务的具体实现:

 
在我们csharp的版本,我们使用了比较流行的CAP组件,https://github.com/dotnetcore/CAP,这个组件本质上是实现了outbox模式,通常也叫“发件箱模式”,借助这个组件,我们很轻易就实现了对于事件的最终一致性。
 
下图来自CAP组件的介绍页面,展示了发件箱模式的具体工作原理:
 
 
 
 
 
 
 
 
 
 
 
 
 
从原理上看,发件箱模式并不是一个复杂的能力,我们认为一向以生态好为优点的Java生态,也一定有类似且流行的组件,很不幸的是,我们在互联网以及能够触达的Java圈子里调研一番之后,得出了如下结论:
  1. Java生态有关于分布式事务的实现,例如:JEE,JBoss等,但目前基本没有团队在用了;
  2. Java生态没有现成的类似CAP这样的组件可以开箱即用;
 
上述结论仅表示我们目前的认知和信息渠道,如果有大佬能够给指个路,不甚感激!
 

cap4j

 
基于前面的结论,为了实现Java项目的DDD代码体验实践,我们开源了一个cap4j项目,期望能将CAP项目的能力移植到Java生态,项目地址:https://github.com/netcorepal/cap4j
该项目目前实现了JPA+RocketMQ的组合,我们规划在未来支持更多的ORM和MQ中间件,同时也会支持与CAP组件的协议兼容,以实现Java、dotnet异构架构的进一步融合。也欢迎大家为项目贡献代码和想法。
 

最后

 
关于技术生态这件事,可以说Java的生态好,但其它语言的生态我认为也都不差,在各自的领域都有非常多的优点。我在各个评论区,总是能看到各种不切实际的偏激言论,感受到种种的恶意。期望各个语言的技术栈从业者,能够更友好地交流,大家都是软件工程师,满足业务需求,实现商业价值,才是大家的更应该关注的。

为了给Javaer落地DDD,我们不得不写开源组件的更多相关文章

  1. freemarker写select组件(一)

    freemarker写select组件 1.宏定义 <#macro select id datas> <select id="${id}" name=" ...

  2. freemarker写select组件(五)

    freemarker写select组件 1.宏定义 <#macro select id datas value="" key="" text=" ...

  3. freemarker写select组件(四)

    freemarker写select组件 1.宏定义 <#macro select id datas value="" key="" text=" ...

  4. freemarker写select组件(三)

    freemarker写select组件 1.宏定义 <#macro select id datas value="" key="" text=" ...

  5. freemarker写select组件(二)

    freemarker写select组件 1.宏定义 <#macro select id datas value=""> <select id="${id ...

  6. django-admin 仿写stark组件action,filter筛选过滤,search查询

    写在StandLi里面的方法都是通过ModelSubject这个类里面的stand_li方法,在它里面用StandLi这个类实例化出来一个对象,这个实例化出来的对象把数据传给前端HTML模板进行渲染, ...

  7. vue-class-component 以class的模式写vue组件

    vue英文官网推荐了一个叫vue-class-component的包,可以以class的模式写vue组件.vue-class-component(以下简称Component)带来了很多便利: 1.me ...

  8. 使用docsify 写开源文档

    使用docsify 写开源文档 官网:https://docsify.js.org/#/ docsify 是一个动态生成文档网站的工具.不同于 GitBook.Hexo 的地方是它不会生成将 .md ...

  9. 手写开源ORM框架介绍

    手写开源ORM框架介绍 简介 前段时间利用空闲时间,参照mybatis的基本思路手写了一个ORM框架.一直没有时间去补充相应的文档,现在正好抽时间去整理下.通过思路历程和代码注释,一方面重温下知识,另 ...

  10. 手把手教你提交Jar包到Maven公共仓库 | 萌新写开源02

    在上一篇文章中,我介绍了自己的SpringBoot Starter项目,可以让我们使用注解的方式轻松地获取操作日志,并推送到指定数据源. 之前,我的项目开源在Github上,大家想要用我的项目,还得把 ...

随机推荐

  1. 笔记:Sublime Text3配置

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 笔记:Sublime Text3配置 日期:2017-12 ...

  2. Hive怎么调整优化Tez引擎的查询?在Tez上优化Hive查询的指南

    目录 在Tez上优化Hive查询的指南 调优指南 理解Tez中的并行化 理解mapper数量 理解reducer数量 并发 案例1:未指定队列名称 案例2:指定队列名称 并发的指南/建议 容器复用和预 ...

  3. iOS开发流程总结(新坑持续更新)

    [上线前流程] 将测试环境修改成正式环境 修改版本号,而且build version比version多一位,如version设置为1.0.1,那么build就设置成1.0.1.x:这么做的理由是,当你 ...

  4. spring使用jdk17运行出现编码问题

    遇到一个比较奇怪的问题. 这个问题别人也遇到过. https://blog.csdn.net/gao_chuan_g/article/details/115117712 一.情况简介 使用jdk17+ ...

  5. 最新扣子(Coze)实战案例:扣子卡片的制作及使用,完全免费教程

    ‍♂️ 大家好,我是斜杠君,手把手教你搭建扣子AI应用. ☘️ 本文是<AI应用开发系列教程之扣子(Coze)实战教程>,完全免费学习. 关注斜杠君,可获取完整版教程. 如果想学习AI应用 ...

  6. selenium无头浏览器

    from selenium.webdriver import Edge # 在这里导入浏览器设置相关的类 from selenium.webdriver.edge.options import Opt ...

  7. 逆向通达信 x 逆向微信 x 逆向Qt

    本篇在博客园地址https://www.cnblogs.com/bbqzsl/p/18252961 本篇内容包括: win32窗口嵌入Qt UI.反斗玩转signal-slot.最后 通达信 x 微信 ...

  8. 树莓派4B安装64位桌面版ubuntu20

    [准备] 硬件: 电脑.树莓派4B.显示器(hdmi线Micro HDMI转标准HDMI).鼠标.键盘.读卡器.TF卡.网线 软件:ubuntu20(x64桌面版).官方烧录工具Raspberry P ...

  9. yb课堂实战之订单和播放记录事务控制 《十六》

    开启事务控制 启动类:@EnableTransactionManagement 业务类,或者业务方法@Transactional 默认事务的隔离级别和传播属性 启动类上加注解 Service层加注解

  10. 微信小程序车牌键盘输入组件(支持单个删除更改,支持赋值,支持新能源)

    网上一搜一大堆类似但大多都相对简单,适用的场景并不多.多数也不支持赋值 不支持单个删除更改 我就借鉴了以下文章的思路,为了达到自己想要的效果做了相对应的更改. 借鉴文章链接:> https:// ...