数据需求
软件系统的核心本质,是对现实世界的对象和规则进行抽象与整理。软件系统设计的难点,恰恰在于合理总结客观世界的对象和关系,并实现最基本的数据模型设计。只有总结并设计出正确的数据模型之后,才能思路清晰地完成功能模块与交互操作的设计。
业务数据建模,也叫数据建模或实体建模,是指将业务的核心数据对象特征进行提炼、归纳,并设计对应底层数据模型的过程。
业务数据建模是数据库设计中最重要的部分,会影响数据库表结构的设计,体现了设计者对业务本质的理解和认知,所以一定要在设计细节方案初期就进行业务数据建模。
业务调整的灵活性取决于软件系统的灵活性,而软件系统的灵活性又取决于业务数据模型的可拓展性。
在现实世界中,多对多关系是一种合理的存在,但并不是所有对象之间的关系都设计成多对多就行了。产品经理在设计之初就要做好预判,尤其是面对多客户开发的商业化软件产品,必须在底层设计时就保留好拓展能力。这样在面临不同客户的诉求时,可以在应用层面做开关配置。产品经理可以在应用层面将复杂的系统逻辑简化呈现。但如果有可能,尽量在数据底层保持逻辑的严谨性。这样虽然会带来底层设计的复杂度,但可以保证系统在应用层面设计的灵活性。
做产品设计,重要的是能想清楚所有的业务场景和问题,然后基于研发资源和实现周期,做出一个综合评估后的合理方案。这是一个先做加法、再做减法的过程。如果数据关系不对,那么不仅可能会限制功能,还可能会限制业务。所以,业务数据建模错误会导致灾难。
领域建模的核心目的在于理清系统中应该引入哪些业务数据,以及它们之间是什么关系。因此,业务数据越多、越复杂,领域建模工作就越重要。
对于开发团队而言,如果系统涉及的问题域是新的、相对不熟悉的,那么为了更好地理解业务术语的意义和关系,就应该执行领域建模工作。
另外,如果系统中涉及的业务数据比较多,或者直接进行数据库设计比较困难,也应该执行领域建模。设计的业务数据在 50 个以上时,就必须进行领域建模。
对象是对现实事物的抽象,是一个具有边界、包括属性、状态和行为的实体。
类是对一组具有相同属性、操作和关系的对象描述。结构良好的类具有清晰的边界和关系。类是对具有共性的一组对象的描述,对象是类的一个实际例子。对象的同义词是类的实例,所谓实例,就是指实际的一个例子。
可以从多个角度来抽象类,从什么角度来抽象类,也是构建系统的重点。
类表达的是信息结构和信息之间的关系,用类梳理出来的信息关系可以指导原型图的绘制。类也是产品设计的基础,必须谨慎处理,避免出现问题。尤其对于一个大系统,其信息结构复杂,必须梳理清楚。
在类图里,类是最基本的元素,表示一个具体的业务数据,用长方形来表示,分为类名、属性、操作这三栏。在领域建模里,操作这一栏是空的,因为那是设计阶段的产物。
在类图里,类之间的数量关系通过关联两端的符号来定义。这种关系描述了一个类的对象实例可以与另一个类的多少个对象实例相关联。
最常见的符号包括:“1” 表示唯一一个;“0..”表示零个或多个;“1..”表示一个或多个,而“0..1”表示零个或一个。解读这些关系的时候,需要从关联的某一端看向另一端。
如果产品经理、研发人员对类的属性比较熟悉,那么类图可以不加属性项。但通常建议还是写上几个属性项,便于读者理解这个类是什么。特别是大家对业务都比较陌生的时候,加上属性项可以帮助大家理解业务。
在类图里,还可以在每个属性项后面加上属性值类型。属性值类型可以是时间格式、文本格式或者数字格式等。通常在梳理业务的时候,类图里只加入属性项即可,不必加入属性值类型。加入属性值类型可以帮助产品经理理清原型图中的交互关系。
但是在原型图里面直接写出类型,直接写出数据的类型,并描述清楚限制条件也是可以的。
在类图里,另一个基本元素就是类间的关系,用来描述各个业务数据,或称为领域类之间的横向联系,采用不同类型的线来表示。
UML 规范里定义了 18 种,但是在领域建模阶段,最常用的只有 4 种:
-
关联。
-
整体部分(松散)。
-
整体部分(聚合)。
-
类别。
要判断是聚合还是组合,关键在于个体是否能够独立于整体而存在。
关系是针对特定问题域或系统而言的,离开了系统环境谈关系是没有意义的。
未知业务流程下的数据建模工作相对更复杂,因为流程未知、表单未知,产品经理没有切入点和参照物,需要在建模的同时设计业务模式和机制。
首先是识别过程数据。领域类数据分为过程数据、自然数据、角色数据、描述类数据四种,使用红、绿、黄、蓝这四种颜色的便利贴来标注。使用时一般先标识过程数据,再标识自然数据,同时考虑角色数据,最后标识描述类数据。
其次是识别自然数据。自然数据是问题域中涉及的参与者、地点和东西,也就是物品和服务。识别自然数据时,还需要考虑是否需要引入角色。针对每个过程数据,需要思考:有人吗?这些人需要抽象成角色吗?有地点吗?有东西吗?如果有些数据可以从其他主过程数据中关联得到,就无需再抽象一次。
然后是识别描述类数据。描述类数据使用的场合最典型的有两种:第一种是概述类,第二种是规则类,也就是想使用数据库表配置的相关规则。
进行到这里,还需要对模型进行回顾。自问四个问题:
-
缺红色吗?系统中不可能没有需要记录的动作,这些动作未来通常会转化成一张或多张数据库表,而且在系统初始化时通常是空表。
-
缺绿色吗?系统中总会涉及一些人、地点、东西等自然数据,这些自然数据未来通常也会转化成一张或多张数据库表,而且在系统初始化时通常会有一些基础数据,也会随着系统应用而不断增加记录。
-
缺黄色吗?黄色最终通常会转化为数据库表中的一个字段;当然,如果不同黄色字段不同,那么也可能变成多张表。
-
缺蓝色吗?蓝色通常也会转化成数据库表,而且在系统初始化时就有内容,并且会不断改变。
对这几个问题进行检查之后,就可以整理领域类图片段,合并出系统领域模型。
对于一个包括大量业务数据的问题域或系统而言,要一口气把整个领域类图画出来是十分困难的。因此这种情况适合采用自底向上的思维逻辑,也就是找出所有主业务流程,针对每个流程绘制领域类图片段,然后将它们合并成整个系统的领域模型。
要合并不同名但实际相同的类,因为大家在分头给每个业务流程做领域模型片段的时候,对同一个业务数据可能会使用不同的类名称,因此需要将它们合并。
在合并成总图的时候,有时候会出现传递依赖等复杂关系,因此需要适度简化、适度优化,并补充各个领域类的关键字段。
最终需要输出领域类图片段文档,包括三个部分:
-
领域类图片段。
-
业务数据说明:指出别名,说明意义。
-
布局规则:写一些与数据相关的规则。
已知流程的数据建模,首先要梳理出所有的类,以此避免前后台信息重复,同时明确信息之间的数量关系。可以从前台信息中获得,也可以从业务调研中获得。梳理步骤:
-
先梳理核心流程。
-
提取所有名词。
-
找到关键表单。表单是流程里要填写的信息单据明细,是业务型系统设计里的重要概念,驱动作业流程的执行。
-
提炼围绕关键表单的人、事、物。
梳理出所有的类之后,接下来要理清数量关系。梳理类之间的数量关系,有利于考虑清楚一项业务是否可以更加灵活。
类之间数量关系的分析需要从双向进行思考:
-
从类 A 的角度出发,思考一个类 A 的对象实例可以对应多少个类 B 的对象实例。这个视角会确定关联关系中靠近类 B 那一端的数量符号。
-
从类 B 的角度进行逆向思考,分析一个类 B 的对象实例又可以对应多少个类 A 的对象实例。这个思考会决定关联线中靠近类 A 那一端的数量符号。
最后将这两个角度的思考结果结合起来,就能构成一条完整的关联线。这条线的两端分别标有各自的数量符号,从而精确定义了类 A 和类 B 之间所有可能的数量关系组合。
理清数量关系之后,就可以再梳理类之间的关联关系。类之间的关联关系描述了不同类的对象之间存在的某种有意义的具体联系或者交互。这种关系超越了单纯的数量对应,指明了对象之间以何种方式彼此连接。
用于描述关联关系的词通常是动词或者动词短语,应该尽可能清晰地表达出类之间的操作和互动行为。虽然没有严格的用词规定,但是优先使用那些能体现动态动词的词,比使用描述静态状态的词更能体现出代码中的交互意图。
有些关联更多表达的是一种结构上的包含或者从属,而不是明确的操作。在这种情况下,关联线上不标注动词名称也是可以接受的,其含义通过上下文和数量关系来体现。
聚合关系描述的是一个较大的事物由较小的事物组成,用一个空心的菱形来表示,菱形要画在较大事物的那一侧。
不是什么类之间都存在聚合关系。聚合关系表达的是大事物和小事物之间整体和部分的关系,符合这个条件的类并不算多,常见的就是组织和订单。
组成关系是聚合关系的一种形式,表达了整体对部分有很强的所有权和生存控制。组成关系一旦创建,部分就和整体共存亡。所以,组成关系强调组合而成,只有组在一起才成为某种事物。
组成关系通常用一个实心的菱形来表示,菱形要画在较大事物的那一侧。组成关系的判定标准有两个:
-
部分对象在生命周期内必须完全隶属于一个整体对象,不存在任何形式的共享或多重从属;部分对象不能独立于其所属的整体对象而存在。
-
部分对象与整体对象具有完全一致的生命周期。整体对象的创建必然导致其他各部分对象的创建,反之亦然;整体对象的销毁也必然导致其所有部分对象同步销毁。
综上所述,聚合关系包含组成关系。聚合关系是比组成关系更大的概念,组成关系是比聚合关系更准确的描述。当然,在现实工作中,都用聚合关系也可以。
在梳理了关联关系之后,还需要确定关键属性。关键属性是实体中的关键字段。如果有需要,可以在梳理实体的过程中,提前把关键字段进行标记。
最后,要综合上述所有分析,考虑效率和灵活性。
在进行领域建模和业务数据建模之后,还需要进行业务数据分析。除非要开发的系统不涉及业务数据,否则这个环节不能跳过。
首先要进行数据应用分析,即理清哪些流程场景在使用这些数据,使用这些数据的哪些部分,甚至理清 CRUD 的关系。
分析哪些流程会使用这些数据,可以简单列出哪些子系统的哪些流程会使用。如果有需要,还可以使用更加复杂的 CRUD 矩阵来优化。但通常只对核心、重要的业务数据执行这一步。
在分析数据应用之后,还需要分析数据构成,也就是理清这个业务数据包含哪些字段。然后针对各个字段,理清以下几方面的内容:
-
数据类型:比如字符串型、整型、布尔型等。
-
数据规格:主要包括长度、精度信息,也可以直接使用数据表设计中的规格描述方式。
-
约束/取值范围:这个字段可以接受的值。对于复杂的取值范围,还可以考虑使用传统的数据字典法来描述。
-
其他细节:还可以再添加一些内容,比如是否为空、是否为键值、是否自动编号等。如果这个字段的值是计算出来的,那么还应该提供计算公式和计算方法。
对于核心的重要数据,还可以考虑对其进行数据特点分析。
-
从结构特点出发:分析主要字段与次要字段,也就是用户主要会看哪些字段;还可以分析稳定字段与不稳定字段。针对新业务带来的数据通常是不稳定字段这一情况,在进行表结构设计时,需要考虑未来拓展。
-
从使用特点出发:比如把数据划分成即时数据与历史数据,但需要确定多久才算历史数据。这个尺度会影响历史数据的迁移,以提高实时查询速度。还可以分成关键字段和辅助字段,也就是谁会被用来作为关键字,可以使用索引等手段来加快速度。
业务数据分析最后要输出业务数据描述文档。文档的主要内容就是上述三部分的分析:构成分析、应用特点、使用特点。