1:领域和子域的区别
领域简单来说就是我们的目的边界。
举个例子,我们想做一个电商系统,目的就是让商家的商品尽快的销售出去,那这个商城整体就是一个领域。
子域简单来说就是为了实现目的,需要哪些模块。
商城整体需要比如订单,用户,物流,商品,营销,履约等等模块配合起来完成。那这里每一个模块都算一个子域。
为什么很多人觉得很费解?因为大部分人都是盯着自己的业务,一直在对照自己的业务在算什么,实际上自己的业务可能是领域下的某一个子域中的某一个模块的某一个功能的其中一个服务,而已。一定要跳出思维的框架,往上找,想想自己这条业务线本质是在为谁服务,最小产品是什么?
2: 通用域,核心域,支撑域又是什么?区别又在哪?
先说结论,区别就是投入的成本会有区别。
核心域:是你业务的特点,它具有不可替代性。
支撑域:有一些业务特点但你这个模块是为了服务于其他核心域的,那就是支撑域。
通用域:不具备核心竞争力也没有特点,比如鉴权,认证等。
在投入有限的情况下,重点发展核心域形成业务特色,购买现成通用域减少成本,人力外包做起支撑域。
有趣的是对于绝大多数普通开发来说,根本毫无区别,这又是一个很怪的概念。写出这些概念的人,他的层级很高,所以看得特别远,但是对于普通开发而言,他所做的一定是“核心域”,所以无需太在意这些区分。
3:通用语言和限界上下文是什么?
在某个子域内,我们通常要统一语言。这个过程需要所有产研团队的参与,开发,测试,产品,项目经理,业务专家等等。在梳理过程中,要对某些动作和行为,有一致性的称呼。不能开发叫用户,产品叫客户,测试叫参与人,这样沟通成本很高,这并没什么特别的东西,就是对一堆东西统一起名,解决交流障碍问题。当然,他另一个作用就是你的代码可读性会大大增强,即便是产品也能读懂什么意思。
限界上下文是用来确定边界的,通用语言在限界上下文内是一致的,可以理解为汉语和中国的关系。当然,对普通开发者而言,还是很抽象。我来举个例子,你设计了一个加积分的接口,那你这个就只能用来加积分,加余额决不能复用你的接口,可能在表里是一样的存储,但业务不能混用,保证自己业务的纯粹性。
4:实体和值对象的区别是什么?
实体和值对象是组成领域模型的基本单元。
从代码上看,实体就是一个小模块的属性,跟以前的对象区别就是除了属性,还会有一些跟自己业务有关的方法,比如计算规则之类的,也常被人称为充血模型。他具有唯一ID,这么说起来可能有点笼统,你可以理解为订单是一个实体,因为他有唯一订单号,无论你订单做了修改还是删除,这个订单号都不会发生变化。
值对象是什么?我们舍弃乱七八糟的概念,来点现实的例子。你创建了一个活动,活动毋庸置疑是一个实体,因为每个活动都有唯一ID,但是你在描述活动属性的时候,比如活动名称,开始时间,结束时间,活动奖品名称,活动奖品说明,活动地址省位置,活动地址市位置。平时我们肯定是每个属性都是一个值,映射数据库的字段,但是,敲黑板!你有没有发现活动奖品配置,活动地址位置相关的属性可以抽离出两个对象,这样在看活动实体的时候就会更加简洁,业务语义也更加清晰?这俩抽出来的对象,就是值对象,他用来描述实体,说白了就是把一些相同的属性抽离到单独类了嘛。很多人最好奇的一点是,你这个活动地址的位置难道就不能创建地址表?那他不就有唯一ID也就不是值对象了呀?好问题,不过你自己也说了,你还要创建实体甚至创建数据表,那我直接把这部分属性当成值对象也就是存个大json到数据库,是不是就能省去很多事?缺点肯定也有,查询的时候麻烦了,所以才要慎重考虑,如果他只是作为一个附属,用来补充实体完整性的时候,就可以用起来了,否则,你可能需要把它当成一个实体看待了。
不过还是那句话,设计之初你不用考虑太多,你尽量放开设计,不确定的话就设计成实体就行,不影响的,后续发现这个玩意既不会单独修改,又不会单独被查询的时候,你自然知道他应该是值对象了。
5:聚合和聚合根是啥?
聚合根也是一个实体,只不过他的特点是他可以管理其他实体。
聚合则是一个抽象概念,一个聚合只有一个聚合根。聚合类比你的一块独立边界的业务,比如奖品服务是一个聚合,他就代表了奖品业务,聚合根可能是一个奖品实体,他可以管理奖品的基本信息,活动的基本信息等。