建模语言之业务组件

业务组件定义应用的业务模型,业务模型是包含了UML类图以及一些其他的扩展元数据构成的,所有的业务逻辑都通过此模型承载,涉及到比较多的模型元素如下:

一. 公共特性

1.1 统一设置

业务模型设置中,有许多属性设置项的含义和规则是一致的,在这里列举出来,后续文档中将不在逐条说明,除非有特殊要求:

  • 基本设置
    • 名称:类型一般使用大写字母开头,属性、参数等非类型元素一般使用小写字母开头,后面皆遵循驼峰命名规范;
    • 显示名称:元素对用户显示的友好名称,使用适当长度、有意义的中文
    • 描述:元素的描述信息,一般在前端为用户提供提示或帮助信息
  • 简单属性:属性、参数、返回值等
    • 数据类型和引用类型:当引用的类型为其他的实体、枚举、值对象等非简单类型时,需要设置,此时,数据类型需要设置为:Reference(引用类型);如果数据类型选择简单类型,则引用类型要保持为空
    • 是否集合:true代表属性为一个集合数据,真实数据类型由属性“数据类型、引用类型”来定义
    • 是否只读:true代表为只读,在生成的实体代码中,不会提供setter的设置器
    • 分组名称:属性的逻辑分组名称,在实体的编辑、详情等页面,用于将实体归类显示,建议使用简短有意义的中文;
  • 完整属性:包括实体、DTO、值对象、分布式事务等类型的属性
    • 是否标题:定义实体在前端页面列表呈现时,此属性是否是标题,通过点击标题可以查看详情,每个类型最多只有一个标题属性,对于实体而言,标题属性是必须的;
    • 长度:定义属性的长度,对于数值型、布尔型、日期时间型、GUID等不能设置;
    • 精度、小数位:只有当数据类型为数值型时有效;
    • 是否可空:是否允许属性为空值,如果是false,当属性值为空时会抛出异常
    • 缺省值:创建空类型实例时,将属性赋值为缺省值
    • 是否包含中文:true代表包含Unicode字符,一般在创建数据库的时候使用;
    • 是否固定长度:属性值的长度是否是固定值,一般在创建数据库的时候使用;
    • 真/假:显示名称:当数据类型是布尔值型,true/false对应的前端显示名称,如果可以设置为“开启/关闭”
  • 校验属性
    • 是否校验:是否开启参数合法性校验,开启以后的校验设置才生效
    • 校验正则表达式:参数需要满足的正则表达式
    • 验证失败提示消息:当开启校验,并且设置了校验正则表达式的时候,参数输入值不符合则抛出异常,内容即为此提示消息
    • 最大值:参数允许的最大值(包含本身),仅对数值型、日期型参数有效
    • 最小值:参数允许的最小值(包含本身),仅对数值型、日期型参数有效
  • 参数设置
    • 缺省值:当不传入参数的时候将使用缺省值,但是取决于语言,如果语言不支持缺省参数,此设置将无效;

1.2 重要枚举定义

【访问修饰符】

包括Public、Protected、Private、Internal、ProtectedInternal,不同语言会根据其语言特性进行相关的转义,在不适用的场所不可选择,比如不能将类设置为Private;

  • Public:公开的,代表类型是公开类型,任何地方都可以访问
  • Private:私有的,代表私有类型,修饰成员,只有在相同类型中可以访问
  • Protected:受保护的,代表只有继承树中的类型可以相互访问,可以跨包
  • Internal:内部的,代表是内部元素,只能在包内可以访问
  • ProtectedInternal:内部受保护的,只能在相同包的继承树中的类型可以相互访问

【HTTP谓词】

  • GET:GET请求
  • POST:POST请求,不幂等
  • PUT:PUT请求,幂等
  • DELETE:删除请求
  • HEAD:HEAD请求

【网络协议】

  • HTTP:
  • HTTPS:

二. 类型定义

2.1 接口(Interface)

【定义】

与UML1.1定义一致,定义业务实体接口,可以包含属性和方法定义。

【规则】

  • 接口规则
    • 名称:以大写字母“I”开头
    • 必须至少包含一个属性或方法定义,不包含方法实现
  • 属性规则
    • 名称:以大写字母开头
  • 方法规则:
    • 名称:以大写字母开头
    • 方法参数规则
      • 名称:以小写字母开头

【最佳实践】

  • 接口名称以大写字母“I”开头
  • 不需要为每个业务实体都定义接口,模型在转化和生成代码的时候,会为实体生成对应的接口

2.2 实体(Entity)

【定义】

与UML1.1定义一致,定义业务实体,代表一个业务对象抽象,可以包含属性及方法,与DDD的实体有类似之处,在生成的实体代码中,实体是业务的核心入口;

【规则】

  • 实体规则
    • 继承修饰符:包括None、Abstract、Sealed,定义一个类型是否是抽象或最终类型
      • None:无,不做继承修饰符的定义
      • Abstract:抽象类,定义一个实体类为抽象类
      • Sealed:最终类,定义一个实体类为最终类
    • 是否前端可见:false代表实体不会对前端暴露,也不会生成对应的前端实体或通用API;
    • 需要审核:true代表是需要审核的实体,关于审核的详情参加后文
    • 持久化类型:
      • None:不持久化
      • RMDB:持久化到关系型数据库,是默认类型
      • XML:持久化到XML文件,目前平台还未支持,是预留类型
    • 实体事件:对于插入、更新、逻辑删除、恢复、物理删除这几种情况,都提供了前后事件,可以用过打开具体的事件,需要在相应的扩展文件中编写具体实现;
  • 实体属性规则:
    • 是否是计算属性:计算属性不持久化,不能设置值,需要设置对应的计算表达式
    • 计算表达式:属性的计算表达式,此处需要根据不同的语言来设置不同的表达式,为了提高兼容性,建议采用方法调用的方式来设置计算表达式;
    • 是否是静态:标记是否是静态属性,静态属性会添加static关键字
    • 业务主键:业务主键,多个属性同时为true则会设置为联合业务主键,业务主键满足全局唯一的要求;
    • 是否唯一:属性值是否唯一,唯一的属性在实体发生变更保存的时候会做唯一性校验;
    • 是否前端可见:属性在前端是否可见,不可见的属性前端页面即实体生成的DTO都将忽略;
    • 是否是系统属性:true代表系统属性,此属性不能修改;
    • 是否上传图片:true代表上传图片,则生成的代码会提供图片上传控件及功能,此时数据类型必须为string;
    • 是否上传文件:true代表上传文件,则生成的代码会提供文件上传控件及功能,此时数据类型必须为string;
    • 关联类型:关联类型,只针对关联属性有效;
    • 是否持久化:不持久化的属性不会进行持久化操作,仅作为内存属性使用
  • 实体方法规则
    • 名称:以大写字母开头
    • 方法参数规则
      • 名称:以小写字母开头

【最佳实践】

  • 继承树中的父实体,一定设置为抽象实体,否则可能是继承树的抽象逻辑有问题;
  • 继承树的设计,在模型转换及数据库创建的过程中,默认使用具体表映射的方式:即具体类对应一张数据库表,而抽象类不对应数据库表;
  • 与UML类图设计思想基本一致,遵循高类聚、松耦合的规则,尽量合理的利用继承、关联、接口等类型
  • 与常规的数据库设计不一样,实体并不一定与数据库表一一对应,很多时候都不是一一对应的;
  • 合理使用值对象,可以有效的减少属性数量并做好统一控制;
  • 所有抽象类上不要创建实体间关系(原因是一条关系线无法定义清楚继承树上实体在线中的两端属性),只在具体类之间创建关系
  • 审核实体的内容,请参见平台特性中数据状态说明的内容

2.3 枚举

【定义】

定义一个枚举类型,包含多个枚举值,一般当一组有限可枚举的值需要定义时,可以使用枚举类型,枚举值在运行期不可修改。

【规则】

  • 枚举规则
    • 名称:必须以单词“Enum”开头
    • 一个枚举类型必须至少包含一个枚举值
  • 枚举值规则
    • 名称:以大写字母开头
    • 枚举值:为了兼容二进制方式操作,一般采用2的指数形式

【最佳实践】

  • 枚举值尽量采用2的指数值,可以高效的操作数据,同时可使用一个字段来存储多个枚举值,具体二进制的用途,可参见平台最佳实践的相关文章。

2.4 商业逻辑

【定义】

商业逻辑是一段代码集合,此处仅定义其框架,具体的商业逻辑实现由用户通过扩展代码提供

【规则】

  • 商业逻辑规则
    • 名称:以大写字母“BL”开头
    • 返回值是否分页:定义返回值是否是返回分页数据
    • 支持分布式事务:true代表支持,此时商业逻辑需要扩展实现分布式事务的逻辑代码
    • 分布式事务协议:指定分布式事务的协议,目前平台仅支持TCC,TCC是两阶段编程模型,实现方法Try, Commit, Cancel
  • 参数规则
    • 名称:以小写字母开头
    • 参数服务来源:当商业逻辑暴露为服务时,参数获取的来源,包括:Query、Body、Form、、Header、Route、Services。

【最佳实践】

  • 将一段经常被复用的代码,封装成一个商业逻辑是个不错的选择
  • 由于服务本身不具备业务逻辑代码扩展的能力,需要通过商业逻辑来提供,所有的业务逻辑实现都应该使用商业逻辑实现;
  • 商业逻辑除了可以暴露成服务,也可以供内部调用

2.5 DTO

【定义】

数据传输对象,用于前后端分离情况下的数据传输,不持久化,不要当作实体来使用。

【规则】

  • DTO规则
    • 名称:以大写“DTO”结尾,注意不要与实体名称重复,因为实体会自动生成对应的DTO
  • 属性规则
    • 是否在构造器中:在生成的代码中,false代表构造器的参数不含此属性,需要通过属性访问器自行设置

【最佳实践】

  • DTO仅作为前后端数据传输使用,不具备业务含义
  • DTO的名称与实体名称不能重复,比如:有实体Customer,那定义的DTO名称不能叫CustomerDTO
  • 定义商业逻辑的返回值,可以采用定义的DTO作为数据类型
  • DTO的属性可以指定数据类型为其他DTO,以便于封装结构化的数据

2.6 服务

【定义】

服务是对外提供的API集合,包含了一套按业务归类的API接口,服务本身只是负责调度对应的商业逻辑或外部服务,自身本身并不具备逻辑。同时,服务还将生成前端的代理类,用于前端直接调用服务。

【规则】

  • 服务操作规则
    • 引用:指定服务操作引用的元素,可以是商业逻辑或外部服务,要引用请先创建对应的商业逻辑或外部服务

【最佳实践】

  • 服务名称:建议以单词“Service”结尾
  • 请遵循HTTP谓词的共识来设置,比如:删除使用DELETE,提交使用POST,可重复的提交使用PUT等;
  • 将一组业务相关性比较大的操作聚合到一个服务中是个好的选择

2.7 常量

【定义】

定义对应固定值的常量集合,常量在运行期的值不可修改。

【最佳实践】

  • 运行期不变的值,可以使用常量来定义,但是值如果要修改,则需要通过修改模型重新发布才能生效
  • 可以建立多个常量,这样有利于按照业务进行划分

2.8 值对象

【定义】

定义多个属性集合,不持久化,用于定义实体属性的时候,将拆分值对象的具体属性为对应的数据库表中的列。此处值对象的含义与DDD中有所差异

【最佳实践】

  • 一个属性常常需要分解成多个字段来存储的时候,建议使用值对象,比如:地址可以设计为值对象,其下的属性包括地址、电话、联系人等;坐标可作为值对象,属性包括横坐标、纵坐标等;
  • 值对象不具备ID和数据状态,也不能持久化
  • 实体转化为DB模型的时候,实体属性对应的列名规则:属性名称_值对象属性名称,比如:属性为UserAddress,数据类型为值对象Address(City, Phone),则对应的数据库列名分别为:UserAddress_City, UserAddress_Phone

2.9 引用实体

【定义】

定义一个已经存在的实体的引用,引用实体只能是引用当前应用下、不同组件内的实体,主要用于定义跨组件实体间的多对多关系

【规则】

  • 引用实体:只能选择系统预置类型或相同工作空间下的其他组件实体

【最佳实践】

  • 需要跨组件建立多对多关系,不适合于建议关联实体的情况下,可以通过引用实体来建立单向的多对多关系

2.10 分布式事务

【定义】

定义分布式事务,需要用户扩展提供具体的分布式事务的逻辑实现

【规则】

  • 协议类型:指定分布式事务的协议,目前平台仅支持TCC,TCC是两阶段编程模型,实现方法Try, Commit, Cancel
  • 是否幂等:true代表幂等,即服务可以重复调用而不影响结果
  • 超时时间:分布式事务的超时时间,单位秒,0代表不超时,否则达到超时时间以后系统将抛出超时异常

【最佳实践】

  • 跨服务(跨应用)的商业逻辑,需要使用分布式事务来保证数据的最终一致性
  • 分布式事务在使用上,也业务逻辑类似,建议通过业务逻辑来调用分布式事务

2.11 外部服务

【定义】

定义相同工作空间下其他应用的服务引用,在逻辑上与商业逻辑是同等类型,但是并不需要提供具体的逻辑实现,使用上与商业逻辑一致

【规则】

  • 服务地址:外部服务的服务地址,不含协议名,域名以及微服务名称,也不含操作名称
  • 服务名称:微服务注册的服务名称,模型使用应用名
  • 方法:服务的方法

以上三项构成了外部服务的完整服务地址

【最佳实践】

  • 通过IDE右侧的元数据浏览器或服务浏览器,将要引用的服务操作用鼠标拖拽到工作区,即可自动创建外部服务并正确设置相关的值,这样做可以避免手工录入发生错误
  • 使用上,其与商业逻辑一致,即可以由其他商业逻辑调用,也可以由服务封装后向外提供API

2.12 继承

分为实体继承和接口继承,与UML1.1的定义一致。

【最佳实践】

  • 不能支持多重继承
  • 基实体(基类)一定是抽象类

三. 实体间关系

实体间支持多种关系,每个关系都有特定的业务含义,与数据库中的外键关系完全不一样,基本遵循了UML1.1的规范。

3.1 组合 Composition

A(源) - B(目标):A包含B(或A由B组合),A中会有B集合的引用,B中有对A的引用 

【特点】

  • 一种包含关系,B不能独立存在(独立存在没有业务含义),必须具有A
  • 删除A,需要级联删除B
  • 数据库:B表具有对A的外键,不可空

【举例】

  • 订单头包含订单体

3.2 聚合 Aggregation

A(源) - B(目标):A包含B(或A由B聚合),A中会有B集合的引用,B中有对A的引用 

【特点】

  • 一种包含关系,B可以独立存在,A可以为空
  • 删除A,级联删除B的几种选择:删除、更新为另一个源、更新为NULL
  • 数据库:B表具有对A的外键,可空

【举例】

  • 教室包含桌子
  • 多级类型(比如:文章类型的父子关系)

3.3 关联 Association

A(源) - B(目标):A关联B(或A引用B),A中会有B的引用,B中有对A集合的引用 

【特点】

  • 一种双向引用关系,A可以独立存在,B可以为空
  • 删除B,级联删除A的几种选择:删除、更新为另一个源、更新为NULL
  • 数据库:A表具有对B的外键,可空

【举例】

  • 图片引用文章

3.4 依赖 Dependency

A(源) - B(目标):A依赖B,A中会有B的引用,B不知道A的存在 

【特点】

  • 一种单向引用关系,A可以独立存在
  • 不能级联删除,删除B可能导致A的数据异常
  • 数据库:A表具有对B的外键,可空

【举例】

  • 图片引用文章

3.5 弱引用依赖

A(源) - B(目标):A依赖B,A中会有B的引用,B不知道A的存在 

【特点】

  • 一种单向引用关系,A可以独立存在,一般用于跨组件引用
  • 不能级联删除,删除B可能导致A的数据异常
  • 数据库:不生成外键

【举例】

  • 用户依赖微信用户

3.6 交叉关联 Cross

A(源) - B(目标):A与B交叉关联(多对多),A中会有B集合的引用,B中会有A集合的引用 

【特点】

  • 一种双向引用关系,一般用于多对多关联
  • 级联删除,删除A或B,同时删除两者的关系
  • 数据库:生成交叉表AB(AID, BID)

【举例】

  • 用户交叉关联角色

3.7 引用交叉关联 ReferCross

A(源) - B(目标):A与B交叉关联(多对多),A中会有B集合的引用,B中会有A集合的引用。与交叉关联类似,一般用于跨主键的多对多关系。 

【特点】

  • 一种双向引用关系,用于多对多关联。
  • 级联删除,删除A或B,同时删除两者的关系
  • 数据库:生成交叉表AB(AID, BID)

【举例】

用户 交叉关联 角色

免费下载PDF文件

您的公司
您的姓名
您的电话
您的邮箱
预约体验