目标
在线的低代码开发平台,用户在平台界面通过托拉拽就能完成开发完,线上直接就能使用,不需要学习任何计算机知识,无需关心后端前端数据库等,只需考虑页面托拉拽设计,表单设计,流程设计,数据建模等,就能完成一个应用
核心领域划分
领域:是指根据一定的规则将业务问题限定在特定的边界内,从而划分为一个个范围
根据云枢、氚云等平台使用文档中可以理解到,LowCode平台的使用流程抽象出来即如下所示
表单设计——>数据建模——>流程设计——>视图设计
提取出四个对象
- 表单
- 数据模型
- 工作流
- 视图
按照业务规则可以划分为多个领域。
每个对象都为一个域,表单域,数据模型域,工作流域,视图域
分为3个域,工作流域,表单+视图域,数据模型域
分为2个域,表单+数据模型+视图域,工作流域
分为1个域。
为了方便分析,我这里为每个对象都划分为一个域。
除了工作流域相对独立,剩下三个域有一些联系
表单和视图需要使用数据模型,数据模型是由表单创建,视图和表单是列表和详情的关系
各个域的作用和分析
表单域
用户在客户端界面通过托拉拽页面的组件自定义布局来设计自己的表单,此表单就是指一个html的提交表单
表单由组件构成,1对N的关系,表单实体有表单属性和配置,每个组件有自己的属性和配置。
后端不应该关心表单和组件,只负责考虑用合适的设计去存储表单和组件的属性、配置,为前端提供支持,前端需要考虑如何去运用这些数据。
这么设计的好处在于,前后基本完全分离,后端只负责存,前端怎么用怎么改由前端自己做主,符合单一职责和开闭原则
表单的构建同时也是初始化数据模型,数据模型是由组件的字段构成的一个数据结构,这部分后端要完成三个目标,
- 数据模型的初始化
- 配置的自动装配
- 配置的生效使用
这是LowCode的核心基础之一,决定了LowCode平台的能用与否,关于数据模型在下文详细分析。
综上所述,表单域的需求:
- 前端和后端需要共同定义一种"通用格式",它的作用有两个,前端如何能根据这个"通用格式"能方便快速的渲染页面包括布局和组件,后端如何根据这个"通用格式"获取数据模型的字段,举个例子,最省事的做法就是将整个页面的HTML代码保存,前端请求获取HTML,并渲染,再比如,前端组件的样式,可以抽出来作为单个组件的属性,并在页面设置
- 数据模型
- 表单可随意定制,随意更改,保存,发布
数据模型域
表单在完成的时候就会同时初始化完成数据模型,数据模型的字段是来自表单的组件,数据类型就是表单的组件属性。
数据模型是贯穿整个LowCode平台使用的对象,所有的操作和配置包括但不限于CURD都是作用于数据模型,由于表单可以任意更改组件,所以导致数据模型的成员也是会任意变动。
初始化完成的数据模型,应该内置五种方法:新增,更新,删除,查询,列表查询,也可绑定自定义方法集成服务。
数据模型还允许绑定规则,即触发事件。例如当对数据模型进行新增的时候,满足A条件的情况下,触发A+事件。(参考云枢和氚云后,氚云是不暴露数据模型也就没有这一个域,而云枢暴露,关于这一点个人认为优先级不高,不属于核心,而属于迭代功能)
数据模型可以内置权限,指定角色可以查看哪些数据,同上理由,这也不属于核心,优先级不高。
数据模型真正的核心点是就是有一套"框架"能高度抽象化模型从而能屏蔽模型差异做到高层次调用,目的只有一个:
内部形成一种机制,以零代码的方式配置,让 Web 请求能处理 Action
举个例子,假设有这种"框架",无论我的数据模型结构如何,一旦创建,就能自动生成对应的curd方法并可以直接使用,最普通的案例就是代码生成器。然而这只是最基本的,如果再加上上述的规则,权限,配置等,就将是很复杂的实现。
综上所述,数据模型的需求:
搞个框架?- 数据模型的初始化
- 内置五种基本方法,并能对数据模型进行操作
- 规则,权限,配置的自动装配生效使用
视图域
视图其实就是一个后台管理列表页面。可以理解为表单是一个client,视图是一个后台系统,提交的表单数据都能在视图上看到
视图跟表单不一样,视图的限制比较大,视图仅仅就是个列表页,在给定的页面结构和配置,让用户抉择使用
用户可以在视图页,指定展示哪些字段,字段是数据模型的子集。数据模型内置的五种方法在视图的提现就是五个按钮,查询按钮可以用户配置查询条件,可随时更改。
总结下来,视图的主要属性是配置,这一块的重点跟表单一样,主要是前端如何将视图的布局配置传给后端,传一大段html代码。后端只要数据模型那一块"框架"搭建的好,这里就可以做到以零代码的方式配置,让 Web 请求能处理 Action,点击相应的按钮就能自动处理。
综上所述,视图模型的需求
- 前端和后端视图页面的数据流转
- 内置方法的装配使用
工作流域
工作流域相比其他域,是独立存在的,它所在层级应该是最外层覆盖的范围也是四个域里最大,用户执行的操作都是在工作流里的流程。
工作流指“业务过程的部分或整体在计算机应用环境下的自动化”。是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。
举个例子,最常见的请假流程,员工A发起请假———>主管B审查通过——>老板C同意。这就是一条既定的工作流,是一个既定的"规则"
综上所述,工作流域的需求
- 后端调研选型一个合适的工作流引擎,投入使用
- 前端将工作流引擎提供的web UI 设计器进行二次开发,符合需求的样式(工作流的web组件UI太丑
领域模型分析
先介绍一些概念。
实体一般对应业务对象,它具有业务属性和业务行为;而值对象主要是属性集合,对实体的状态和特征进行描述。但实体和值对象都只是个体化的对象,它们的行为表现出来的是个体的能力。领域模型内的实体和值对象就好比个体,而能让实体和值对象协同工作的组织就是聚合,它用来确保这些领域对象在实现共同的业务逻辑时,能保证数据的一致性。
如果把聚合比作组织,那聚合根就是这个组织的负责人。聚合根也称为根实体,它不仅是实体,还是聚合的管理者。
聚合=实体+值对象,聚合根也是一个实体,值对象只是一种属性集合
接下来通过事件风暴等方式分析找出聚合和聚合根。
聚合
红色标识表示聚合根,白色表示实体
- 数据模型聚合(核心): 聚合根是数据项(模型字段)。
- 表单聚合:聚合根是表单。
- 视图聚合:聚合根是配置。
接着对每个聚合进行详细分析
模型聚合
无论怎么划分域,数据模型都属于核心的那一部分
领域模型 | 领域对象 | 字段 | 功能 | 类型 |
---|---|---|---|---|
数据模型 | ||||
数据模型 | 唯一ID,名称 | 编码,字段名 | 聚合根 | |
数据类型 | 字段的类型 | |||
索引 | 是否索引 | |||
默认值 | 字段的默认值 | |||
为空 | 是否为空 | |||
内置方法 | 唯一ID,名称 | 编码,字段名 | 实体 | |
类型 | 系统内置或用户自定义 | |||
绑定服务 | 绑定的外部服务 |
如上面对域的分析所知,低代码平台的核心就是构建一套机制(框架)以实现自动化配置自动化运行的目的。单就从模型来说并不涉及到多复杂的业务。
领域对象 | 命令 |
---|---|
数据模型 | 初始化模型 |
初始化配置 | |
发布 |
表单聚合
关于表单的实现简单的可以很简单,比如直接保存HTML代码,每次修改页面布局的时候,只需要替换整体的HTML代码就行。如此一来,这个聚合也就没什么意义,本质上就是一个字段所存的一个数据。
如果稍微让它变得有可配置的话,那么该聚合拥有表单,控件等实体,表单是个聚合根。
关于布局,云枢只支持上下和左右两种布局,氚云有一个布局控件,根据各自的业务这里的布局可以是个实体可以是个值对象或是一个字段属性
领域模型 | 领域对象 | 字段 | 功能 | 类型 |
---|---|---|---|---|
表单 | ||||
表单 | 基本属性 | 标题,编码,表单的布局 | 实体 | |
控件集合 | 表单所拥有的控件 | |||
控件 | 基本属性 | 例如控件名 | 实体 | |
类型 | 控件类型 | |||
样式 | 组件的style | |||
数据 | 绑定的数据和数据格式 |
表单这块的业务对于后端来说比较简单,命令只有基本的增删改查。
领域对象 | 命令 |
---|---|
表单 | 保存表单 |
修改表单 | |
发布 | |
控件 | 设置控件 |
视图聚合
视图这块主要就是一个视图的配置,表单的数据主要是前端需要服务端只需要保存就行,视图的话涉及到一些数据业务。
领域模型 | 领域对象 | 字段 | 功能 | 类型 |
---|---|---|---|---|
视图 | ||||
视图 | 基本属性 | 名称、编码 | 聚合根 | |
配置 | 视图的主要配置 | |||
配置 | 展示字段 | 视图列表展示的字段 | 实体 | |
查询条件 | 视图的条件查询按钮 | |||
排序规则 | 视图的排序 | |||
操作绑定 | 视图上的按钮操作,如新增,修改 |
视图对象的一些命令
领域对象 | 命令 |
---|---|
视图 | 保存配置 |
修改配置 | |
发布 |
该领域模型的命令是很简单的,但是落地到实际业务上的流程却不这样,视图的配置和数据模型是息息相关的。
- 当用户在视图的时候,要先查看这个视图下有没有配置"展示字段",根据配置展示页面
- 当用户筛选查询的时候,要根据配置的"查询条件"过滤,根据这些条件进行查询
- 视图页面上的默认按钮是由数据模型的内置方法配置的,云枢这里可以通过html页面自己编写代码,添加自定义按钮,氚云则没有按钮的配置
总结
通过对领域对象的分析得知,只要你能明确每个领域的边界,领域模型划分的合理,那么每个领域对象是互不干扰的,从整理得知领域对象本身的命令并不复杂也只是常规的curd,业务难点还是落在代码流程自动化上。
实现思路
开头先说答案:
以mongoDB为主用来操作数据的CURD,mysql为辅支持组件配置,仿SpringMVC,servlet实现完成LowCode流程的初始化,配合工作流完成程序的运行
分析提到,表单是可随意更改组件布局,这就导致了数据模型里的字段也是会随意变动,而数据模型又是整个程序流程中最重要的一环,那无论是出于实现难度、可拓展性、方便性考虑,关系型数据库如mysql都显的太重。
普遍方案都是采用一个表单一个表,存放数据字段,这里就是涉及到选择哪种数据库,不妨简单思考一下代码逻辑实现,
- 当用户完成表设计以后,代码需要根据这个表单,创建一个表,用户更改表单如添加、删除组件,代码需要操作数据库对表添加、删除字段;
-
数据模型是要使用的,由于表单的不确定性,导致表结构的不确定性,要求保证能正确的对每个不同的表单完成curd,从这又延申出2种解决方法:
- 每次更新表单时,根据表结构动态生成class类从而实例化依赖orm对该类进行curd操作。
- 不依赖orm,字段匹配去进行curd操作
- 数据模型的字段还跟其他配置如规则,权限等捆绑,如果随意更改,那这些也要想办法相应的更改
不解决上述3点,LowCode就迈不出第一步,更不用谈"框架"。
问题就是如何方便的、拓展性高的、逻辑清晰的解决上述问题
利弊分析
针对上述问题,关系型数据库和非关系数据库的优劣分析
- 为不同的表单创建不同的表,每个表有不同的字段并且还会随时更改,针对这一点,很明显的关系型数据库弊大于利,如果有N个表单就有N个表,如果这时多表修改表结构会拖垮数据库。
- 数据模型的curd,由于模型的多变性就需要考虑不同的结构的抽象性,关系型的数据库有两种方式:1.动态生成class类 2.依赖SQL用字段匹配。非关系型数据库:字段匹配直接进行curd就行。
- 与模型相关的配置,这部分变动不频繁相对有固定的结构,从实现来说关系型的数据库会更合适。
使用MongoDB来操作数据
关于mongo的介绍这里不赘述
通过下图可以快速了解mongo的一些概念
MongoDB 有一个非常突出的特点,即文档的概念,文档是一个键值(key-value)对(即BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别
一个简单的文档例子如下:
{"site":"www.baidu.com", "name":"百度"}
集合就是 MongoDB 文档组,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,比如,我们可以将以下不同数据结构的文档插入到集合中:
{"site":"www.baidu.com"} {"site":"www.google.com","name":"Google"} {"site":"www.zhihu.com","name":"知乎","num":5}
这个特性就非常的符合上述表单更改组件导致数据模型结构变更,能很好的包容表单多变的特性,能很好解决表单变动频繁,
不妨假设一下,如果我们有请假表单、审批表单等结构不同的表单,对应的数据模型也不一样,但是mongodb很好的包容了这分差异,这是mongo查询的用法
db.drivers.find({name: "Xiaose"}) #查找 name 为 Xiaose 的文档
db.drivers.find({age:{$gt:20}}) #查找 age 大于 20 的文档
得益于mongodb结构,我们不需要关心具体的字段是什么就能做到将curd抽象,只需要符合做好字符匹配,实现难度低,扩展度高。
同理,对于表单本身这种变动频繁的,也可也
低代码框架时序图
经过上面分析,数据模型的curd已经没什么大问题了,剩下的就是在代码设计层面,如何像spring或者springmvc那样的框架,做到配置自动装配,配置自动生效,诸如事件机制,触发器,监听器等,如何组合并运用这些经过合理设计做到自动化,达到低代码或零代码的目的。
水平不够,日后待定
代码设计
根据领域和聚合的分析,按照DDD设计,代码结构如图,关于DDD分层概念这里不赘述。
- application : 应用层,负责编排领域服务
- domain:领域层,领域对象,仓储,领域服务
- infrastructure:基础层,提供项目的基础工具、组件使用
- interfaces:用户接口层,面向前端的一层
各层流程图
总结
低代码平台是一个大型的工程,不是一蹴而就,其最核心的地方还是后端如何处理一系列配置从而实现低代码的目的
核心业务如下:
- 后端如何做到低代码开发配置(自动解析数据模型,自动装配CURD方法,使用规则等),这是低代码平台的基础
- 前端和后端的数据交互格式,后端如何告诉前端 界面的设计,前端能展现出来,这是低代码的门户
- 数据如何落地