共计 2410 个字符,预计需要花费 7 分钟才能阅读完成。
依稀记得我第一次设计一个零碎的时候,画了一堆 UML(Unified Modeling Language,对立建模语言)图,面对 Class Diagram(其实就是畛域模型),纠结了良久,不晓得如何落地。因为,如果依照这个类图去落数据库的话,看起来很奇怪,有点繁琐。可是不依照这个类图落库的话,又不晓得这个类图画了有什么用。
扪心自问,你有多久没有画数据模型和畛域模型了?
当初回想起来,我过后的纠结源自于我对畛域模型和数据模型这两个重要概念的不分明,先前看过 DDD(畛域驱动设计),外面一句话我感觉讲的很不错,一个类型能够充当多个角色,这个角色能够是显式的(实现了某个接口或基类),也能够是隐式的(承当的具体职责和上下文决定)。
然而每次在新的需要下来,出设计方案的时候在数据模型和畛域模型上会耽搁一些工夫,根本原因在于对这两个概念混同。也因为如此,在设计方案或者在开发过程中会频繁批改数据模型的设计,因为如果底层的逻辑、概念、实践根底没搞清楚的话,其构建在其上的零碎也会呈现问题,十分重大的问题。
借鉴 DDD(畛域驱动设计)的一些设计准则,我感觉有必要花工夫认真清晰这两个概念,帮忙大家在工作中,更好的做设计决策。
一 概念定义
数据模型:面向长久化,数据的载体。关注的是畛域常识,是业务畛域的外围实体,体现了问题域外面的要害概念,以及概念之间的分割。畛域模型建模的要害是看模型是否显性化、清晰的表白业务语义,扩展性是其次。
畛域模型:面向业务,行为的载体。关注的是数据存储,所有的业务都离不开数据,都离不开对数据的 CRUD,数据模型建模的决策因素次要是扩展性、性能等非功能属性,无需过分思考业务语义的表征能力。
一个强调的是实体,另一个强调的是关系,再细想下咱们当初建模的时候都是用啥的啥图 -ER 图,这下子就被缓缓带偏了。设计的数据模型外面带了实体申明也带了业务关系,两者开始混同。
是的,二者确实有一些共同点,有时候畛域模型和数据模型会长的很像,甚至会趋同,这很失常。但更多的时候,二者是有区别的。正确的做法应该是无意识地把这两个模型区别开来,别离设计,因为他们建模的指标会有所不同。
如下图所示,数据模型负责的是数据存储面向 DB,其要义是扩展性、灵活性、性能。而畛域模型负责业务逻辑的实现,其要义是业务语义显性化的表白,以及充分利用 OO 的个性减少代码的业务表征能力。
途中标识灰色的局部其实还能够细分,业务到模型之间也可进行拆分,波及到一些命名,这里就不做开展。感兴趣的能够查阅:PO、VO、DAO、BO、DTO、POJO 能分清吗?
在日常开发过程中,咱们在很多的零碎业务设计上,并没很好的解决数据模型和畛域模型的关系,反而在设计的时候一个是把数据模型当畛域模型,另一个是把畛域模型当数据模型。
二 错把畛域模型当数据模型
最近在优化低代码那块的元数据优化,外面波及到一些元数据存储、拓展问题。这块逻辑大抵能够简略概括:
数据表单设计时候,用户能够动静配置列的属性以及对列属性依据对应的数据类型动静匹配相应函数。
对于这个规定,畛域模型很简略,就是提供了列根本配置信息和属性配置信息配置数据,如下图所示:
如果依照这个思路上来就会存在两张表 meta_field_definition、meta_field_attribute 两张数据表,一张用来存储列的根底定义,另一张用来定义列的属性配置以及拓展。
如果咱们这个干了,咱们就犯了把畛域模型当数据模型的谬误,这里设计一张数据表足够。在原来的元数据列定义表外面加属性配置字段 fd_attribute 以 Json 的模式存储,再根底表单的根底上加拓展表 fd_extend_feature(以后业务用不上作为根底保留的拓展字段)
调整后有什么益处:
首先,一张表单的保护老本必定比多张表的保护成本低
其次,其数据的扩展性更好。比方:针对某种数据类型要反对某种定制的业务配置和函数反对,如果是一张表,咱们就须要往属性表外面持续增加新的业务反对配置。然而如果咱们批改为一张表在原有的元数据中放弃不变在属性拓展外面以 JSON 格局增加配置即可。
可是,在业务代码外面,如果是基于 JSON 在做事件可不那么美妙。咱们须要把 JSON 的数据对象,转换成有业务语义的畛域对象,这样,咱们既能够享受数据模型扩展性带来的便捷性,又不失畛域模型对业务语义显性化带来的代码可读性。
三 错把数据模型当畛域模型
确实,数据模型最好尽量可扩大,毕竟,改变数据库可是个大工程,不论是加字段、减字段,还是加表、删表,都波及到不少的工作量。
拿下面的案例来讲
能够留神到 fd_extend_feature 拓展表所创立的,便于对表的垂直拓展补充。JSON 字段也好,垂直表也好,尽管能够很好的解决数据存储扩大的问题,然而,咱们最好不要把这些扩大(features)当成畛域对象来解决,否则,你的代码基本就不是在面向对象编程,而是在面向扩大字段(features)编程,从而犯了把数据模型当畛域模型的谬误。更好的做法,应该是把数据对象(Data Object)转换成畛域对象来解决。然而在解决改字段的时候,如果频繁操作 addFdExtendFeature、getFdExtendFeature 是一种典型的把数据模型当畛域模型的谬误示范。
四 总结
在日常设计和开发中咱们应该是把畛域模型、数据模型区别开来,让他们各司其职,从而更正当的架构咱们的利用零碎。其中,畛域模型是面向畛域对象的,要尽量具体,尽量语义明确,显性化的表白业务语义是其首要任务,扩展性是其次。而数据模型是面向数据存储的,要尽量可扩大。
回归到主题一个类型能够充当多个角色,这个角色能够是显式的(实现了某个接口或基类),也能够是隐式的(承当的具体职责和上下文决定),
- 数据模型:面向长久化,数据的载体。
- 畛域模型:面向业务,行为的载体。
【原文地址】:原文跳转
【欢送关注】:码农架构
专一于零碎架构、高可用、高性能、高并发类技术分享