一文讲清领域模型和数据模型
前言
清晰的记得我第一次接到需求开始设计一个系统时候,开始抓脑怎么清晰的表达这个系统是干什么的,拥有什么服务能力,技术架构,业务模型是怎样的,底层支撑具备什么能力等等。
你可能会想通过画UML图,利用Class Diagram模型,但是你会发现如果按照这个类图去设计数据库的画,看起来非常繁琐,也很奇怪,可是如果不按照这个类图去设计的话,又不知道这个类图画了有什么用。
其实有这个疑问的最终纠结源是对数据模型和领域模型这两个重要概念的不清楚。对这两个概念很容易混淆,其结果就是,可能会影响一些模块设计的不合理性,甚至影响像业务中台这种技术上的局限性。因为如果底层的核心逻辑、理论概念基础没搞清楚的话,其构建在它之上的系统也会出现问题,一般还是非常严重的问题。
说了这么多,可能还是对上面说的存在疑问,下面我们进行比较深入的探讨这个问题
什么是领域模型和数据模型
这两者关注的重点或者说维度不太一样。
领域模型
关注的是领域本身,是业务领域的核心实体,体现在问题域关键概念和之间的联系。构建领域模型的目标是看模型能否清晰表达业务语义、模型能否显性化,扩展性是其次。
数据模型
关注的是数据存储,在我们所有的业务中都离不开数据,离不开对数据的CRUD。构建数据模型目标是看扩展性、性能等非功能属性,业务语义的表达则是其次。
换一句话说,领域模型关注的是业务核心,数据模型关注的是技术细节,然而在我们开发中,二者都缺一不可,都很重要。之所以容易被混淆,是因为这两个模型都在强调实体(Entity)和关系(Relationship),二者的确有一些共同点,在某些情况下数据模型和领域模型会长的很像,甚至会趋同,但是在大多数的情况下还是有区别的。所以应该在需求设计时候有意识将这两个模型区分开,基于他们建模关注的目标不同分别设计。
上图清晰描述了领域和数据模型所承担的职责。数据模型负责数据存储,核心关注灵活性、扩展性,领域模型核心关注业务逻辑的实现,清晰显性表达业务语言,利用面向对象的特性增强代码的表达能力。
然而,我们如果不注意的话经常容易犯错,一是将领域模型当做数据模型,或者是将数据模型当领域模型。
错把领域模型当数据模型
举个例子,过去做的一个商品价格区间项目,这里面涉及到不同商品类型、不同类目、品牌、时间季度等维度,商家会给出不同的价格区间设置,在不超过平台的限制的前提下,商品审核通过即可设置完成价格。
思考这个需求,抽象出来就是针对不同商品我们会有一套规则,针对这个规则进行商品发布价格审核,领域模型很简单,如下图所示:
在这里插入图片描述
如果这个按照领域模型来设计存储的话,那么需要两张表:价格规则表和价格区间表,一张表用来存储具体的价格规则,另一张表用来存储规则价格区间。
如果是这样的设计的话,那么扩展性将很差,设想后续新需求需要增加一个活动商品的活动价格区间,如果是两张表的话,那么则需要在价格区间表中新增两个Field,如果上线了则会涉及到表的变更会比较繁琐,这就错把领域模型当数据模型导致变麻烦了。
而如果按照数据模型来设计存储的话,只需要一张表就够了,把价格区间作为一个json字段在规则表中存储,如下图所示:
在这里插入图片描述
如果这样设计的很明显好处就是首先维护一张数据库表比两张表的成本要小,其次数据的扩展性期更好,如果需要在价格区间中增加字段,则Json存储,则数据模型可以不变。
您可能会问,这样在业务代码基于json操作会不会不太方便?确实,所以一般会将json数据对象转成成业务语义表达的领域对象,这样的话,既满足了数据模型带来的扩展便捷性,同时又不会丢弃领域模型对业务语义显性化可读性, 岂不美哉。
错把数据模型当领域模型
上面讲到数据模型通过扩展来满足业务需求,毕竟改动数据库不管是加减字段,还是加表删表都会涉及到不少的工作量。
像阿里的业务中台这种底层数据模型设计的一定是非常合理的,可以支撑几十个业务的成千上万的不同场景,核心的商品、订单、支付、物流等。
拿商品中台IC来说,垂直类型商品类型、不同渠道类型、各种规则互斥,如何快速支撑业务迭代,就需要做到高度数据存储扩展性,比如可以采用垂直表或者fetaure字段方式。但是这种虽然可以很好的解决存储扩展问题,但是我们不能过度依赖,还是需要梳理出业务领域模型涉及,否则的话,你的代码不是在面向对象编程,而是面向扩展编程,也就是错把数据模型当领域模型。 带来的后果就是代码可读性无法看,不可维护,更好的做法应该是将**数据对象(Data Object) 转换成领域对象(Domain Object) **处理。
在具体落地的时候,这里有个方法可以借鉴,一般数据对象和领域对象之间是需要通过gateway来进行转义, 一方面可以适配两种模型过渡,另一方面还起到了解耦防腐作用,既解除了业务代码对底层数据的直接依赖,也不失对业务语言的表达准确性。从而更好的提升系统的可维护性。
什么?你可能会说这TM不对吧,我记得之前大学课本上说过在设计关系型数据库要满足3NF(三范式)
同学,该醒醒了,其实在实际工作中,我们由于各种原因就是要打破这个规则,出于对性能考虑、对扩展性考虑,查询链路可能由于为了少走访问磁盘db冗余字段处理提升访问性能。
业务场景不同,对他们的扩展粘性强度也不一样,比如数据扩展性做到了,可是查询怎么处理,总不能在json里做like查询吧,其实大可不必,倘若说数据量预估不会大的数据,完全可以处理,而像阿里商品,订单这种海量数据,当然不能,一般就需要考虑读写分离、构建搜索来处理。
领域对象是连接数据模型和领域模型之间的桥梁。 不管怎样,在面向问题域,都需要带着这两种模型来均衡思考,设计出更好的模型更好支撑业务。
最后
- 觉得有收获,帮忙关注转发下哈,感谢感谢。
- 本文以获得原作者授权,出处。
网友评论