依稀记得当初设计系统的时候,画了一堆UML(UnifiedModelingLanguage,统一建模语言)图。面对ClassDiagram(其实是领域模型),纠结了半天,不知道怎么解决。降落。因为,如果按照这个类图去数据库,看起来很奇怪,有点繁琐。但是如果不按照这个类图去做,就不知道这个类图有什么用。问问自己,你有多久没画过数据模型和领域模型了?现在回想起来,我当时的纠结源于对领域模型和数据模型这两个重要概念的无知。之前看过DDD(DomainDrivenDesign),一句话觉得非常好。一个类型可以扮演多个角色,这个角色可以是显式的(接口或基类的实现)或隐式的(特定职责和上下文决定)。但是每次有新的需求下来,在设计方案出来的时候,数据模型和领域模型都会耽误一些时间。根本原因是混淆了这两个概念。正因为如此,数据模型的设计在设计方案或开发过程中会经常修改,因为如果底层逻辑、概念、理论基础不清晰,建立在其上的系统也会出现问题,这很严重。问题。借鉴DDD(DomainDrivenDesign)的一些设计原则,我觉得有必要花时间仔细理清这两个概念,以帮助大家在工作中做出更好的设计决策。1概念定义数据模型:面向持久化,数据载体。它侧重于作为业务领域核心实体的领域知识,体现了问题领域中的关键概念和概念之间的联系。领域模型建模的关键是看模型是否能够显式、清楚地表达业务语义,其次是可扩展性。领域模型:面向业务,行为载体。重点是数据存储。所有的业务都离不开数据,离不开数据的增删改查。数据模型建模的决策因素主要是可扩展性和性能等非功能属性。无需过多考虑业务语义的表示能力。一个强调实体,另一个强调关系。当我们思考我们在建模时使用了什么样的图——ER图时,我们就逐渐被偏颇了。设计的数据模型包含实体声明和业务关系,两者开始混淆。是的,两者确实有一些共同点。有时候领域模型和数据模型看起来会很相似,甚至会收敛,这很正常。但通常情况下,两者之间存在差异。正确的做法应该是有意识地区分这两种模型,分别进行设计,因为它们的建模目标会有所不同。如下图所示,数据模型负责面向DB的数据存储,其本质是可扩展性、灵活性和性能。领域模型负责业务逻辑的实现,其本质是业务语义的显式表达,充分利用OO特性增加代码的业务表示能力。途中标注的灰色部分其实是可以细分的,也可以在业务和模型之间拆分。涉及到一些命名,这里就不展开了。在日常的开发过程中,我们在很多系统业务设计中都没有处理好数据模型和领域模型的关系。而是在设计的时候,一个把数据模型当作领域模型,一个把领域模型当作数据模型。2把领域模型误认为是数据模型最近在优化低代码区的元数据优化,涉及到一些元数据存储和扩展的问题。这段逻辑可以简单概括为:用户在设计数据表单时,可以动态配置列属性,根据对应的数据类型,动态地将对应的函数匹配到列属性上。对于这个规则,领域模型很简单,就是提供基本的列配置信息和属性配置信息配置数据,如下图所示:如果按照这个思路,就会有两个表meta_field_definition和meta_field_attribute。一个用于存放列的基本定义,一个用于定义列的属性配置和扩展。如果这样做,我们就会犯将领域模型用作数据模型的错误。这里设计一个数据表就够了。在原元数据列定义表中增加属性配置字段fd_attribute并以Json形式存储,然后在基础形式的基础上增加扩展表fd_extend_feature(目前业务没有使用预留的扩展字段作为基础).调整后有什么好处:第一,一张表格的维护成本肯定比多张表格要低。其次,它的数据扩展性更好。例如:要支持某种自定义的业务配置和某种数据类型的功能支持,如果是表,我们需要在属性表中继续增加新的业务支持配置。但是如果我们修改成一张表,原来的元数据不变,可以在propertyextension中添加JSON格式的配置。但是,在业务代码中,如果是基于JSON的,就没有那么漂亮了。我们需要将JSON数据对象转化为具有业务语义的领域对象,这样既可以享受数据模型可扩展性带来的便利,又不失领域模型显式业务语义带来的代码可读性。三将数据模型误认为领域模型事实上,数据模型应该尽可能地可扩展。毕竟改数据库是个大工程。无论是加字段、减字段、加表、删表,都涉及到大量的工作。.以上例为例,可以注意到创建了fd_extend_feature扩展表,方便表的纵向扩展。不管是JSON字段还是垂直表,虽然可以解决数据存储扩展的问题,但是最好不要把这些扩展(特征)当做领域对象,否则,你的代码根本就没有面向性。对象编程,而是针对扩展领域(特性)编程,从而犯了把数据模型当作领域模型的错误。更好的做法应该是将数据对象(DataObject)转化为领域对象进行处理。但是,在处理变化的字段时,如果频繁操作addFdExtendFeature和getFdExtendFeature,就是典型的将数据模型作为领域模型的错误示范。四小结在日常的设计和开发中,我们应该区分领域模型和数据模型,让它们各司其职,这样才能更加合理地构建我们的应用系统。其中,领域模型是面向领域对象的。它应该尽可能具体并具有清晰的语义。显式表达业务语义是其首要任务,其次是可扩展性。数据模型面向数据存储,应尽可能具有可扩展性。回到主题一个类型可以扮演多个角色,这个角色可以是显式的(实现接口或基类),也可以是隐式的(由具体职责和上下文决定),数据模型:面向持久化,数据的载体。领域模型:面向业务,行为载体。
