背景
在和组内业务老员工沟通,或带校招同学时,都发现很多人对于合理业务数据模型,如何进行定义、拆分大多是有问题的,尤其是在业务迭代的过程中,怎样随业务发展,去阶段性设计,是需要一定技巧的。所以,其实不是工作时间长,就一定清晰。归根究底,还是认知不够清晰导致的。周围工作多年的老同事、朋友, 对我在数据模型,协议的设计上尚且比较认可,所以这里简单从我个人的工作经验里,总结下,怎么对业务数据模型,进行合理理解、设计、拆分。望各位远方来客,可以一起讨论,共同提升和成长~
什么样的业务模型好?什么又是坏的?
首先,对业务模型的设计,需要遵循MECE原则,对事物进行拆解。即:对事务进行不重叠、不遗漏的分类。保证类与类之间,都是相互独立、完全穷尽的。
从MECE原则反向推导,很容易得出,什么是坏的业务模型。
- 重叠性高、边界不清:比如同一个字段定义,在整个系统中存在二义性的;又或者是字段A和字段B的含义有交集。
- 存在遗漏:这个字段不足以描述当前的业务功能,后续新接手的人,可能又会创建新字段,导致新老字段部分重叠。
1和2,最终都会导致和数据模型,相关的操作接口,同时维护在多个字段上,或者模糊不清,一团乱麻。
重新认识数据模型
什么是数据模型?
本质上,是描述客观载体。
在Golang中,可以简单理解成一个结构体。
打个比方,鸟的身体结构,由翅膀、脚、头部、啄等等组成。我们可以根据身体结构,定义一种结构体,用于描述鸟。
再做进一步抽象,动物都有基本的身体结构,比如眼睛、脚(尾)、头、手(翅膀)组成,我们又可以定义一个更基础的数据模型,描述动物本身。
什么时机去拆分、合并,数据模型?
基于业务需求
- 原则:如果业务里,对数据使用需求不同,就拆分;需融合多类数据模型做逻辑,或新业务拓展让原模型难适应时,就合并。
- 举例:外卖平台,配送环节关注配送地址、时间、骑手位置,商家环节关注菜品、库存、销量,将订单数据按配送和商家维度拆分,方便各环节业务处理。平台要分析用户消费习惯,就把用户点餐、评价、收藏等数据合并,全面了解用户。
基于数据特征
- 原则:数据复杂,信息多且性质不同就拆分;数据简单但分散,查询分析成本高就合并;关联性弱的拆,强的合。
- 举例:在线教育平台的 “课程详情”,含介绍、大纲、教师、价格、评价等复杂信息,拆成 “课程基础”“教学安排”“师资”“评价与价格” 等小模型。多个简单的用户签到表,分别记录不同日期签到,合并成一个 “用户签到总表”,方便统计分析。用户学习记录和课程资料,关联性弱可拆分;用户学习记录和学习进度,关联性强就合并。
基于系统性能
- 原则:读写频繁有性能瓶颈,大字段含不常用信息影响速度就拆分;关联查询复杂影响查询效率,就合并相关模型;数据冗余多占空间就合并去冗余,模型过大难管理就拆分。
- 举例:电商大促时订单数据读写频繁,“订单详情” 大字段包含不常用的历史优惠规则,影响速度,拆成 “常用订单信息” 和 “历史优惠信息”。商品、库存、价格分属不同模型,关联查询多,合并为 “商品综合信息”,减少关联操作。用户多表有重复基本信息,合并去冗余;用户行为数据量太大难管理,按时间拆成多个小表。
过多拆分,可能会分裂出大量小模型,变得难以维护,怎么解决?
通过DDD(领域驱动设计),一定程度上可以解决。可以通过明确数据模型边界、建立统一语言(简化数据模型)、有界限上下文、聚合与聚合根、分层架构等方式,对数据模型尽可能地抽象、复用。