DDD - 来自听众的16个DDD问题,美团技术团队是这样回答的

简介: DDD - 来自听众的16个DDD问题,美团技术团队是这样回答的

DDD的框架和组织管理

1. 如何从代码框架上约束CQRS经领域模型走仓储和规约,不要在应用层上同级别互调用。跨过领域自己在应用层写实现,读时不要应用走缓存和API请求,这些没有框架的硬件约束很难管控程序员的配合。如果纯粹靠行政又很奇葩,还是有一套体系+团队结构配合。

领域驱动设计的目的是为了帮我们解决复杂业务的分析,架构和代码落地问题。虽然理论上可以建立架构规范进行编码约束,如引入Sonar规则扫描来规范代码的架构分层和调用依赖,但部分场景下一些简单的需求也遵循从仓储-领域-应用-接口这种分层,会比较重。我们团队的实践是有一定复杂度的业务要沉淀领域模型,但对于一些简单的场景,如后端日志,简单的配置数据管理,省略领域层未尝不可。

毕竟采用领域驱动设计是为了帮我们解决问题,而不是在简单问题上强制某种规范来限制我们。

2. 有没有一套通用的DDD 落地框架?

目前还没见到过,DDD都是要结合业务上下文进行实践的,是方法而不是工具。所谓方法是需要结合实际场景来使用的,而工具往往解决特定问题,可以直接使用。

3. 如何驱动专家们参与到领域设计流程?

人人都是领域专家,最重要的是对业务认知达成共识。可以技术主导来进行概念抽取,把描述业务的词汇进行沉淀和统一管理,有意识的在沟通中使用这些词汇描述业务,如产品文档、技术文档和面向业务的培训资料等,逐渐落地。

4. DDD团队实践分享,如何在组内推广落地实施?

从统一语言做起,尝试用统一语言来描述我们的业务需求。

DDD如何在老系统上使用或者迁移

5. 快速业务迭代压力下,老项目如何快速转变思维和方式,带来的时间成本影响怎么测算?

领域驱动设计是一种将复杂业务抽象为系统模型的方法,没有额外的成本,任何时候都可以开始。但的确会有思维方式上的转变,可以循序渐进,先从统一语言做起。

6. DDD如何以最小代价应用在历史系统上?

DDD是一个帮我们进行业务分析,将业务映射为模型的方法,使用它没有额外的代价,它会帮助我们构建描述业务的概念体系,建立起更加合理的领域模型,至于是否要重构历史系统,在代码层面实现领域模型,完全是一种项目抉择,哪怕不重构系统,它在分析业务,抽象模型上的价值依然存在。

DDD的落地实践细节

7. 接口返回给前端的是领域对象Domain还是根据前端页面定义的VO?操作数据返回的是Entity,数据转换用的DTO,返回前端是VO,Domain什么时候用?VO\Entity\DTO\Domain具体是怎么用的?

不同公司的代码规范里按架构分层定义了PO,BO,VO,DTO等很多概念,这些概念都承载了特定团队在编码上的一些规范。

首先,不要被这些概念所束缚,而是针对自己的项目,确定适合自己的规范是什么;

其次,再来看哪些O是可以拿来参考和使用的,比如DTO,Entity是简单对象只有数据而无行为,仅用于传输数据(对外交互用DTO,访问数据库通常用Entity),其他的O是不是真的有必要做那么精细的区分值得商榷。

我们团队采用的是贫血模型,虽然用BO来处理Domain层的实体,但也仅仅是个简单的对象,并不包含行为方法,与Entity相差不大,如果实体和表结构相同,就复用Entity(这种复用是有代价的,未来当Entity与领域模型不能一一对应时,需要重构)

8. 事务是怎么处理的?数据新增更新落库是怎么处理的?事件溯源是怎么实现的?联表查询时数据转换怎么处理?

原则上事务在应用层处理,数据更新,查询这种都在仓储层处理,联表查询能避免就避免,不能避免的要仔细评估必要性(Base Table + Extension Table这种反映类继承关系的数据模型可以接受联表查询)。

在仓储层对跨多个表的聚合根进行组装。

9. 聚合遇到审批流该如何划分?聚合的CURD如何处理?DDD一般开发套路是什么?DDD有推荐学习的网站吗?有没有复杂业务用DDD实现的开源项目推荐?

实体的状态变化最终要提交到数据库(CRUD),如果是充血模型,可以通过插件生成动态SQL,在仓储层对实体提交进行封装。但我们的实践并没有完全采用这种模式,部分实体状态的更新是直接更新到具体字段的,这样在代码上比较直白和明确。

推荐DDD的两本经典书《实现领域驱动设计》,《领域驱动设计 软件核心复杂性应对之道》,另外领域驱动设计属于方法范畴,避免拿来主义,生搬硬套,而要结合业务和系统实际情况进行应用。

10. 落地实现的方式,是在领域服务层做业务编排还是聚合根做业务编排?

不管是聚合根还是领域服务,其核心职责是封装,封装的目的是复用;

领域服务与聚合根的差异:领域服务主要处理哪些不适合放在聚合根里的逻辑,例如:活动,规则,人群,通过三个实体(聚合根)实现,当规则发生修改时,如果要变更活动状态,此时可以在领域服务里分别操作规则和活动两个实体。

应用层的职责是编排,编排的目的是灵活组装领域层的能力应对流程变化,解决不同场景下的流程差异问题。

有时候这里面的边界很模糊,需要依据具体情况来取舍。

11. 领域模型的分离,如何确定领域模型更准确?

领域驱动设计最根本的是要关注业务,对业务进行抽象,在用户,产品,技术之间达成共识,这种共识本质上就是领域知识,然后基于这个领域知识来设计系统,将其线上化。

验证领域模型的常用方法是场景走查,通过业务发展趋势来确定未来可能出现的场景,来验证当前模型是否具备扩展性。

12. 实战型的DDD代码到底如何写呢?DDD带来的问题是什么?

更多的用DDD来抽象模型,在代码实现上并没有去追求一个完美的充血模型,但未来会进行这块的探索。在spring单例模式下构建充血模型有一定的理解成本,学习曲线比较陡峭。

DDD带来的最大问题是容易陷入DDD本身的概念体系而跳不出来,反而被这些概念束缚和折磨。这不是DDD的问题,而是我们使用的姿势不对。

13. 遗留代码如何分节奏落地DDD?

先看有无必要,如果需要基于遗留代码来迭代新的业务能力,可以结合遗留代码的业务功能和新的需求来尝试进行抽象。第一步先统一语言,遗留系统解决什么问题,涉及哪些业务概念,新需求解决什么问题,涉及哪些业务概念,尝试进行抽取和统一;接着,这些概念进行进一步细化分析,确定概念的构成与分类,构建类层次;在落地代码时,适时进行代码重构,让新老代码反映这些概念。

其它

14. DDD和微服务的关系,以及落地的方法。

个人理解DDD和微服务是互相成就的关系,2004年Eric Evans在《领域驱动设计》中首次提出了DDD的概念,提出之后并未得到很好地推广,直到2014年Martin Fowler在《Microservices》提到微服务之后,DDD才真正开始发挥它的价值。主要是因为微服务架构虽然得到了大家的认可,但对于如何划分微服务、该划分到什么粒度一直都没有很好的标准和答案,而DDD刚好为此提供了一套指导方法和指导思想。

DDD里面的限界上下文从业务视角来看,它是语言的边界和模型的边界,从技术视角来看,它也是应用的边界和技术的边界,所以我们可以从业务问题出发,分析领域模型,划分限界上下文,然后再从技术视角考虑质量属性、功能复用以及服务集成等一些技术因素对限界上下文做进一步识别,最后划分出来的限界上下文也会作为微服务划分的主要参考。

15. 想了解下DDD的经典实践,用走过的弯路。

分享一个走过的弯路:对内协作时称我们在搞领域驱动设计,沟通时言语中满是聚合根、实体、值对象、限界上下文、事件风暴等高级词汇,发现这不仅没有帮助到我们的工作,反而增加了聊天的难度。不妨抛开这些具体的招式,和产品与用户坐下来好好聊聊需求,需求中涉及到哪些业务概念,这些概念之间有什么关系,概念有哪些状态,关键属性是什么等等。

16. DDD一直都知道也在运用,知道最终整体目的,但落地实际优秀案例加代码结构的案例培训和参照的太少,建议尽量以简单代码块说清楚每个知识点的意义和愿景。

对于偏业务流程和数据操作的管理信息系统而言,按照DDD的概念体系来构建系统,在系统实现上采用完美的面向对象充血模型,并非DDD要追求的核心目标。我们的实践中更多的是通过DDD来帮助梳理业务,抽象合理的领域模型;落地上,依然采用了相对简单的贫血模型,未来可能会进行一些充血模型方面的探索。

本文摘自:@美团技术团队

相关文章
|
前端开发 测试技术 人机交互
DDD - 理论到落地从统一语言开始
DDD - 理论到落地从统一语言开始
827 0
真下饭!字节技术官DDD(领域驱动设计)手册,拆解业务代码首选
至少20年前,一些顶尖的软件设计人员就已经认识到领域建模和设计的重要性,但令人惊讶的是,这么长时间以来几乎没有人写出点儿什么,告诉大家应该做哪些工作或如何去做。尽管这些工作还没有被清楚地表述出来,但一种新的思潮已经形成,它像一股暗流一样在对象社区中涌动,我把这种思潮称为领域驱动设计(domain-driven design)。
|
SQL 缓存 Java
殷浩详解DDD系列 第三讲 - Repository模式
# 第三讲 - Repository模式 **写在前面** 这篇文章和上一篇隔了比较久,一方面是工作比较忙,另一方面是在讲Repository之前其实应该先讲Entity(实体)、Aggregate Root(聚合根)、Bounded Context(限界上下文)等概念。但在实际写的过程中,发现单纯讲Entity相关的东西会比较抽象,很难落地。所以本文被推倒重来,从Repository
37692 8
|
缓存 前端开发 中间件
DDD 领域驱动设计落地实践系列:工程结构分层设计
前面几篇文章中,笔者给大家阐述了 DDD 领域驱动设计的三大过程,重点围绕如何通过战略设计与战术设计进行 DDD 落地实践进行了详细的讨论,但是还没有涉及到工程层面的落地。实际上所有的这些架构理论到最后都是为了使得我们代码结构更加清晰,从而开发出 bug 少、扩展性强、逻辑清楚的应用。因此本文就是为了解决 DDD 领域驱动落地实践最后一公里问题,将我们分析出来的领域模型通过与工程结构的映射实现真正的落地。
DDD 领域驱动设计落地实践系列:工程结构分层设计
|
微服务 测试技术 Java
阿里技术专家详解 DDD 系列- Domain Primitive
关于DDD的一系列文章,希望能继续在总结前人的基础上发扬光大DDD的思想,但是通过一套我认为合理的代码结构、框架和约束,来降低DDD的实践门槛,提升代码质量、可测试性、安全性、健壮性。
61895 17
阿里技术专家详解 DDD 系列- Domain Primitive
|
设计模式 弹性计算 人工智能
阿里技术专家详解DDD系列 第四讲 - 领域层设计规范
在一个DDD架构设计中,领域层的设计合理性会直接影响整个架构的代码结构以及应用层、基础设施层的设计。但是领域层设计又是有挑战的任务,特别是在一个业务逻辑相对复杂应用中,每一个业务规则是应该放在Entity、ValueObject 还是 DomainService是值得用心思考的,既要避免未来的扩展性差,又要确保不会过度设计导致复杂性。
|
存储 设计模式 缓存
DDD领域驱动设计实战-分层架构及代码目录结构(下)
DDD领域驱动设计实战-分层架构及代码目录结构
1974 0
DDD领域驱动设计实战-分层架构及代码目录结构(下)
|
12月前
|
关系型数据库 MySQL Java
DDD面试题:DDD聚合和表的对应关系是什么 ?(来自蚂蚁面试)
尼恩,一位40岁的资深架构师,分享了其读者群中关于DDD(领域驱动设计)的面试题及解答,涵盖DDD架构落地、微服务拆分、聚合与MySQL表的对应关系等内容。尼恩通过系统化的梳理,帮助读者在面试中展现强大的技术实力,让面试官印象深刻。此外,他还提供了《尼恩Java面试宝典》等多本技术圣经PDF,助力读者提升架构、设计和开发水平。关注【技术自由圈】公众号,获取更多资源。
DDD面试题:DDD聚合和表的对应关系是什么 ?(来自蚂蚁面试)
|
设计模式 架构师 数据建模
DDD建模系列(四)
DDD建模系列(四)
DDD建模系列(四)
|
敏捷开发 存储 前端开发
【美团技术】领域驱动设计DDD在B端营销系统的实践
【美团技术】领域驱动设计DDD在B端营销系统的实践