前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DDD究竟是个啥?怎么落地?

DDD究竟是个啥?怎么落地?

作者头像
ImportSource
发布2018-07-25 17:10:52
1.2K0
发布2018-07-25 17:10:52
举报
文章被收录于专栏:ImportSourceImportSourceImportSource

领域驱动设计(Domain Driven Design,以下简称DDD)这个话题,经常会出现在各大技术圈。特别是微服务出现后,海内外的大佬们又把微服务和DDD放到了一起说事情。

当“领域驱动设计”映入我的眼帘时,我心想“领域”这个词我熟悉。

但“领域驱动设计”一下子就感觉高端了许多。

于是好奇的查了些资料,发现了vo,pojo,domain之类的。看到这里时,我的心头是一脸不屑,这不就是我每天都在使用的吗?

我们每天新建的三层项目不是就老是出现domain目录,还有vo目录,还有service目录吗??这不就是这么点事情吗?!

什么是“领域”?

嗯,另外“领域”这个词,说的就是每个领域都有自己的领域语言,那么我们开发软件的时候,也应该沿用所属行业的领域语言,比如银行系统有银行系统的特定的一套语言,这套语言你不能打破,因为这是人家多少年积累的约定俗成的行业语言。比如支付系统有支付系统的语言,虽然互联网支付是最近些年才慢慢发展壮大,但现在它也发展出了一套自己专门的语言,你没看每家的支付系统都会说订单、商品、产品、库存等等,这已经慢慢形成了一门专属的行业语言,也就是领域语言。

总之,我要说的是,你在构建软件时,请一定记住,先起名字,先起领域名字。这应该DDD的第一步。没错,我说的就是这么赤裸裸,起名字就是DDD的第一步

这就是大概我理解的DDD。也是我目前能够想到的。

但,我想着DDD这事绝对没有我想的这么简单,我得去查查资料好好学学,以下是一些上面我没有说到的一些点以及对上面的一些概念的细化以及如何落地的基本思路。

一步步来。

领域映射

“领域”这个两个字,具体怎么落地呢?

很简单,就是把现实中(一般指线下)的约定俗成的现成行业术语映射到你的静态和动态设计中。静态设计指的是你的实体类的起名问题。动态设计是指你的业务类(也就是service)的方法名起名问题。现实中的动作名对应service中的方法名。

领域专家

领域专家这个角色是一个抽象的泛指。你可千万别专门较真去招聘一个领域专家来。你心目中懂那一行的人就是你的领域专家。比如你去走访一个银行柜员,你去问一个清洁工,或者你去问一个程序员(这个程序员在某行业开发多年早可能就是这方面的专家了,只是人家恰好写代码而已。)或者是产品经理等等。总之,白猫黑猫,懂那一行的人就是你的“领域专家”

领域分层

这里的分层主要是DDD的历史。就是最早大师们提出来的领域驱动设计这事,是一个更加抽象和底层的概念。后来由于领域驱动设计的日益发展,人们又封装出来了一套基于这些底层领域概念的更高层的高级领域概念。就好比变成语言的底层语言和高级语言之分一样。

最早的人们只是抽象出了最主要的两个概念。一个是领域(Domain),一个是领域逻辑(Domain Logic)。是不是够抽象,是不是看了以后根本无法直接落地,是不是像哲学 ,需要你好好的悟和实践。

后来随着发展,人们在此基础上又发明了新的更加高级和可落地的概念。比如Entity、ValueObject、Aggregate、Service等等,还有一些你可能很少用的一些,比如:Repositories、Factories、Domain Event这些概念。

嗯,通过这样的分层,你就知道了这些概念,哪些概念属于底层概念,哪些属于高级概念。核心就是抽象和具体、底层和高级。

高级落地概念

这里说的高级不是歧视那个Context,哈哈,是指的high-level。

Entity 有唯一标识的。就对应于你的实体类。

Value Object 可以没有唯一标识的。对应于你的返回数据格式类。一般只是为了前端显示方便,只负责返回数据用的,官方说法:immutable object。

Domain Event 对Domain进行各种的操作的事件。在如今的微服务当下,你可以理解为CQRS里的Command,用来同步数据的。

Aggregate 是Entity和Value Object的集合。用来返回展示用的。通常用一个id,就可以获取到一个Aggregate。有关这个概念你可以看一下mongodb的设计思路。

Service 就是你三层里的那个service,里边一堆领域逻辑,一堆的操作和动作。对应于底层领域概念的Domain Logic,属于动态(Domain属于静态)。

Repositories 这里的repositories不是版本控制系统里说的仓库的意思。而是指的对于聚合中的entity和value object的单独访问,这里你就对应于dao层好了。很多时候,我们的dao就是负责对entity的单独而直接地访问。而且这个概念早被引入了Spring框架了,就是那个用来做数据访问的@Repository注解。

有图有真相:

Factories 这里的Factories就是设计模式里的那个工厂模式。之所以DDD把工厂模式也拉拢过来,就是因为DDD的大师们认为工厂模式是一个牛逼的设计模式,它能把创建一个对象变得如此简单,调用者不需要关心内部细节就可以使用一个对象了,所以建议大家多使用工厂模式来践行DDD。事实证明,Spring框架中大量的使用了工厂模式,也许就是对DDD中Factories这个概念的践行。

领域抽象

之所以有这一节,主要是我们很多时候并不能把领域一下子就定义的一步到位。如果按照前面所说的你完全按照现实中的领域名词来一比一映射来构建你的代码可能会出现一些重复的代码。所以这时候就需要你对现实的领域进一步抽象,从而让你的代码足够的简洁。当然如果你从定义领域的时候就一眼看破了其中的本质,那自然也就无需专门的领域抽象了。

领域驱动吵架

这个小节里,我们主要介绍一些吵架时专用的一些概念。领域驱动设计的过程中,你难免要和别的团队以及产品经理等等吵架,那么DDD也为你抽象了吵架可以用到的一些方法论。

Context

相信看这篇文章的人肯定听过Context。是不是很熟悉?好学的同学,肯定也听说过Model、Ubiquitous Language、Bounded Context。那么这些是用来做什么的呢?其中一个主要功能就是吵架。没错,领域驱动吵架。你是不是经常说:“我们说的xxx不是你说的那个xxx”。这显然两个没在一个Context下讨论事情。或者还有“你这个功能不是xxx系统应该提供的,而应该是yyy系统来做,要不然就乱了。”等等。这些其实都是在说Context。我拜读过不少有关领域驱动设计的文章,他们一上来就向你介绍一通Context。他们一般都是这样介绍的:“上下文。xxxxxxxxxxx。。。。。。”。说实在的,你说上下文我并不知道你在说什么。其实Context的意思很简单,就是大家都在同一个语境下愉快聊天(或者“在一个范畴下”,或者“在一个大前提下”)。

Model

其实和Domain是有点接近的,相信你肯定看到一些项目代码的目录中有的写的是model,有的写的是domain,然后他们目录下其实都是那些实体类。但Model和Domain还是有一点不同。Domain是领域的一个更广的层面。而Model是解决Domain下特定问题的一些模型,也就是类似子集的概念。在具体的编程中有些时候是差不多的,此时你的Domain下有唯一的一个最大子集Model,就是Domain本身。但有时候一个Domain下可能有多个Model来共同成就一个Domain。这其实是一个粒度问题,得具体问题具体分析。

Ubiquitous Language

统一术语。大家都使用同一套行业话语体系,比如下单,预算单等等。这套话语体系也是衍生于“领域(Domain)”这个核心概念。并且是团队内部成员之间以及团队与团队之间大家沟通的统一标准。

Bounded Context

这个概念核心就是Bounded,划清界限,你是你,我是我,这么做不是自私,而是一种明晰的分工体现。常用于跨团队共同完成一个Context下的事情时。前面我们说的Context是一个没有被标清边界的Context,因为我们默认是没有团队协作的。但当涉及到团队协作就需要一个有明确界限的Context,也就是BoundedContext。

比如一个大的系统,下面有一些子系统(subsystem),那么这个子系统就是一个Bounded Context。另外比如我们的整个系统的一部分是由指定的另外的一个团队来做,那么这个团队做的事情就是一个Bounded Context。

那么这四个概念仅仅只是服务于吵架吗?显然不是,他还负责一个更高端的任务,那就是划分系统边界,特别适合分布式系统、微服务的拆分。这也是为什么最近人们又开始讨论DDD的原因之一吧。

实际代码怎么写的?

DDD,我个人理解更多的是一门哲学。正如上面领域分层一节中说的那样。DDD在最开始的时候,它是一个抽象的概念,这些抽象的概念你自己只能去领悟,直接后来,人们考虑到了技术人员喜欢二话不说上手的特点,决定进一步封装成更高级的概念,这样就好落地了,于是就有了entity、vo、aggregate等等。所以,如果这个问题你是希望更快上手,那么就是后面的这些概念散落在了你的三层代码中,entity目录啦,service目录了之类的。但DDD不仅仅这些。

DDD和微服务

可以说DDD和微服务是绝配。DDD本身就是一门哲学,它指引着你朝着美好的代码结构不断向前。如果说单体应用中,你可以不分青红皂白的,马马虎虎,拉拉扯扯,黏黏糊糊的就可以写完,那么在微服务架构下,拆分的过程,以及拆分后的各自衔接的边界划分则是一项复杂的工程。恰好,DDD的核心就是用来划分和理清边界的。

配合使用

DDD的各种概念不是孤立存在的。你得配合起来使用。比如Context下是Domain,然后子系统是Bounded Context(有关Bounded Context的具体概念,你可以移步上面的“领域驱动吵架”那一节)。

为了让你感受下Bounded Context以及和其他的概念的配合,上个图:

有没有体会到那么一丝的韵味?

总结

好了,我们说了这么多。总之你就记住DDD里边有很多的概念。但这些概念是可以分类的。有的概念是DDD的底层概念,比如Domain、Domain Logic。有的概念是高级概念,是后来基于底层概念开发的新概念,为了落地,比如Entity、Service、Value Object,Repositories等。还有一些概念是为了吵架和适应分布式系统的。比如Context、Bounded Context。通过这样分类,你会发现,这么多概念其实也蛮好理解的。还有就是,DDD,这个概念很早就有了,至少可以追溯到2004年,那个时候你是不是还在上小学。而且Spring框架里的好多概念和实现都是对DDD的一种践行,值得去好好研究一番,光看看他的那些注解你就能感觉到了。对了,你的DDD旅程,别忘了从命名开始。

通过这次的整理学习,我明白了两件事情:DDD真简单,其实我们早就在使用了;DDD不简单,它是一门哲学,简单的形而上学的使用只是规范了你的代码目录,但涉及到更高层面的逻辑抽象,则需要在具体的代码构建中慢慢体悟!

以上只是我个人观点,欢迎拍砖!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ImportSource 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
Prowork 团队协同
ProWork 团队协同(以下简称 ProWork )是便捷高效的协同平台,为团队中的不同角色提供支持。团队成员可以通过日历、清单来规划每⽇的工作,同时管理者也可以通过统计报表随时掌握团队状况。ProWork 摒弃了僵化的流程,通过灵活轻量的任务管理体系,满足不同团队的实际情况,目前 ProWork 所有功能均可免费使用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档