9月7日-8日,相约 2023 腾讯全球数字生态大会!聚焦产业未来发展新趋势! 了解详情
写点什么

基于 DDD 设计并实现模块化单体应用

  • 2019-10-17
  • 本文字数:2086 字

    阅读完需:约 7 分钟

基于DDD设计并实现模块化单体应用

一个最近由Kamil Grzybek在 Github 发布的项目,给出了使用领域驱动设计(DDD,Domain-Driven Design)方法设计并实现一个单体(monolith)应用的详细介绍。该项目的目标,就是展示如何以模块化方式设计并实现一个单体应用。此外,Grzybek 还基于他在应用开发实践的收获,给出了一些有用的架构建议和设计模式。


Grzybek 是华沙ITSG Global的一位系统架构师,并担任团队负责人。他指出,该项目的目标并非是要创建一个极简应用,或是一个验证原型(PoC,proof of concept),而是给出一种适用于生产环境的完整实现。该项目的动机,来自于 Grzybek 对一些类似的但并未取得成功的项目的审视。在他看来,大多数示例应用过于简单,或是不够完整。他一直认为,这些应用至少在某些部分上存在着设计和实现上的问题,或是存在着相关文档缺失的问题。


Grzybek 强调指出,他的实现只是解决类似业务问题的许多方法之一。系统的软件架构需考虑多种因素,例如功能要求、质量属性和技术约束等,另一方面也会受开发人员的经验、技术约束、时间和预算等因素的影响,所有这些因素都会影响解决方案。


该应用针对的是为大多数开发人员所认可的会议组(meeting group)领域。应用实现中考虑了额外的复杂性,因此相比基于CRUD的常规应用更具意义。Grzybek 将主领域进一步划分为四个子域,即会议、支付、管理,以及用户访问。


为给出领域所需的功能,Grzybek 采用了一种称为“事件风暴”(Event Storming)的方法。该方法由Alberto Brandolini建立,用于探索复杂业务领域。Grzybek 使用该方法在主领域的各子域中发现行为和事件。


从更高层次上看,该架构中定义了一个 API 层、包含存储的四个模块(分别对应于所发现的四个子域),以及一个用于通信的公共事件总线(EventBus),如下图所示。



模块也相应地划分为四个子模块,并分别实现为独立的二进制文件,分别为:处理所有请求的 Application、实现领域逻辑的 Domain、实现基础架构代码的 Infrastructure,以及在 EventBus 上发布事件并且是模块间唯一共享组件的 IntegrationEvents。Grzybek 使用了Decorator模式,实现添加工作单元(Unit of Work)和日志等交叉关注点(cross-cutting)。


为分离应用内部的命令和查询,Grzybek 使用并实现了CQRS的一种变体。该 CQRS 变体针对命令所涉及的同一数据库表,在查询中使用了原始 SQL 和视图。虽然CQRS还具体其他变体,但 Grzybek 力图避免使应用过于复杂化。


模块间的集成是基于异步事件传输的。事件传输使用了“发件箱模式”/“收件箱模式”(outbox and inbox pattern),以及基于内存中的 EventBus 代理。为存储要发布的事件,发件箱模式在数据存储中添加了独立的表。事件的添加,实现中通过执行任务的命令,以及等同于命令的事务。此后,这些事件通过单独的流程,转发到另一个模块的收件箱中。在该项目中,事件传输是通过各模块中的后台 Worker 实现的。该实现提供了多次交付和处理。


最后,Grzybek 强调该项目仍在开发中,欢迎贡献者的加入。项目是使用 C#编写的.NET Core 应用,使用了像Autofac(用于IoC)、Dapper (一种用于读取模型的MicroORM)之类的类库。项目中还包括基于Arrang-Act-Assert模式的测试,使用NUnit实现。


在与 InfoQ 的访谈中,Grzybek 进一步详细介绍了他的设计理念。


InfoQ:相比基于微服务的设计,您如何评价单体应用的模块化设计?


Kamil Grzybek:与微服务体系架构相比,模块化单体应用的主要差别之处在于部署方法和模块间通信。

在微服务架构中,每个模块都以独立的进程运行。模块间的通信必须使用网络实现,并且通常通过同步服务 API 调用(即 RPC,远程过程调用),或是使用代理(即消息传递)实现。微服务架构是一种分布式系统,具有分布式的所有优点和缺点。

对于模块化单体应用,则无需考虑分布式系统。所有模块均以同一进程运行,无需使用网络即可相互通信。各模块可以通过方法调用直接同步引用内存中对象,或是异步地使用运行于同一进程中的某个中介者(Mediator)。


InfoQ:相比其他解决方案,例如一些消息传递平台,使用 EventBus 和发件箱/收件箱模式具有哪些优缺点?


Grzybek:模块化单体应用的主要优点,是开发人员无需使用任何消息平台,因为大多数功能都可以使用现有的设计模式在内存中实现。模块化单体应用本身可担当此类平台。当然,对于更高级的系统,使用独立的平台可能是更好的解决方案。但做出此决定时,必须谨慎。


InfoQ:您在 CQRS 模式的实现中,使用了视图和原始 SQL,而非单独的表。对此您能详细介绍一下吗?


Grzybek:我的方法虽然是一种最简单的 CQRS 实现,但其功能强大,通常完全够用。使用视图是应用和数据库之间的一种抽象和契约形式。开发人员可随时进入 CQRS 实现的下一层,读取应用逻辑可以保持不变。

下一层是物化视图。物化视图加快了读取的速度,但会导致写入性能略有下降。一些最先进的系统对于扩展性要求极高,它们引入了 CQRS 模式的最高层实现,并异步更新读取模型。这就是“最终一致性”。

每个实现层,都会增加解决方案的复杂性,因此,只有在真正需要时,我们才应去动更高的层。


原文链接:


Design and Implementation of a DDD-Based Modular Monolith


活动推荐:

2023年9月3-5日,「QCon全球软件开发大会·北京站」 将在北京•富力万丽酒店举办。此次大会以「启航·AIGC软件工程变革」为主题,策划了大前端融合提效、大模型应用落地、面向 AI 的存储、AIGC 浪潮下的研发效能提升、LLMOps、异构算力、微服务架构治理、业务安全技术、构建未来软件的编程语言、FinOps 等近30个精彩专题。咨询购票可联系票务经理 18514549229(微信同手机号)。

2019-10-17 08:003215
用户头像

发布了 391 篇内容, 共 120.7 次阅读, 收获喜欢 254 次。

关注

评论

发布
暂无评论
发现更多内容

霸榜GitHub的阿里内部Spring Boot实战文档到底有多强?

Java 架构 面试 微服务

《冰河的渗透实战笔记》电子书,442页,37万字,正式发布!!

冰河

网络安全 信息安全 渗透测试 网络攻防 互联网技术

“读万卷书,行万里路”,让你收获一个不平凡的人生

小天同学

读书 成长 旅行 5月日更

Flutter开发:Failed to retrieve the Dart SDK…的解决方法

三掌柜

5月日更

从酷睿双核到Tiger Lake-H,英特尔如何帮游戏笔记本完成蜕变

E科讯

成功产品三要素

lenka

5月日更

Rust从0到1-错误处理-panic!

rust 错误处理 Error 不可恢复错误

Golang List, Ring and Map

escray

学习 极客时间 Go 语言 5月日更

如何成为云原生技术高阶玩家?华为云最近做了这件事

华为云开发者联盟

容器 DevOps 微服务 云原生 华为云

kafka基本概念

杨四正

大数据 kafka 架构设计 消息队列 消息队列架构

详解JQuery框架的五大选择器

华为云开发者联盟

jquery 选择器 层级选择器 属性选择器 过滤选择器

飞桨前沿升级、顶级开源项目、产教融合育人,WAVE SUMMIT论坛内容先睹为快!

百度大脑

深度学习 飞桨

docker(centos系统)安装vim工具

liuzhen007

Docker 5月日更

HTTP/3 初体验

运维研习社

nginx 运维 HTTP3.0 5月日更

Dubbo 负载均衡

青年IT男

dubbo

千万级学生管理系统的<考试试卷>存储方案

唐江

架构实战营

进程内缓存助你提高并发能力!

万俊峰Kevin

缓存 微服务 本地缓存 Go 语言

【LeetCode】找出第 K 大的异或坐标值Java题解

Albert

算法 LeetCode 5月日更

让人工智能成为保险行业科技基因的一部分!

百度大脑

人工智能 保险

❄️【程序员必看系列】开源项目有盈利模式指南

洛神灬殇

开源 程序员 盈利模式 5月日更

集成学习案例一 (幸福感预测)

容光

数据处理

NumPy之:ndarray多维数组操作

程序那些事

Python Numpy 程序那些事

🚄【Redis 干货领域】从底层彻底吃透 AOF 重写 (源码篇)

洛神灬殇

redis aof Redis 协议 Redis 核心技术与实战 5月日更

分布式事务与分布式系统

邱学喆

分布式事务 raft CAP PAXOS 副本一致性

android端音频采集与播放

floer rivor

android 音视频

冈萨雷斯《数字图像处理》学习总结及感悟:第一章 绪论 百闻不如一见

老猿Python

图形图像处理 数字图像处理 冈萨雷斯

人人都在谈的图数据库到底是个啥?

华为云开发者联盟

大数据 数据结构 数据 图数据库 华为云图引擎图数据库GES

丰田汽车选用Mobileye和采埃孚的安全技术

E科讯

私有云解决方案

anyRTC开发者

音视频 WebRTC RTC sdk

论Http、Socket、WebSocket、WebService(SOAP)之间的区别

Damon

5月日更

智能视频云3.0全景图来了!深度融合视频应用共创行业新生态

百度大脑

云智一体 智能视频 云智技术

  • 扫码添加小助手
    领取最新资料包
基于DDD设计并实现模块化单体应用_研发效能_Jan Stenberg_InfoQ精选文章