概念

  • 领域系统: 一套saas系统,以硬编码的方式存在。从一个单租户模型的小型SaaS系统开始,逐步迭代出来的多租户模型的公有云SaaS系统。在业务上分为ERP和MES两部分。
  • 数据同步: 一种在低代码平台中,对领域系统数据进行CURD的技术方案。方案的原理是通过canal监听, 将领域mysql数据库中的数据通过binlog发掘更新动作, 然后通过领域服务http接口查询最新数据, 再将查询结果通过调用低代码平台的接口保存到低代码平台的数据库里。
  • 数据融合: 一种在低代码平台中,对领域系统数据进行CURD的技术方案,是数据同步的升级版。数据同步是一个设计上有缺陷的方案,在数据的一致性、实时性上都存在严重的稳定性问题,为此付出了昂贵的维护、调试和debug成本,测试和客户会频繁提出问题,最后都归结到数据问题上,因此重新设计了技术方案。新方案需要领域系统按CRUD四个场景提供7个标准接口,低代码平台在ORM层会自动调用领域系统实现的接口,实现上层功能。这个方案并不是优雅的,但目前从实践上看是相对可靠的,虽然一定程度上把工作和复杂度转嫁了。
  • 融合对象: 不管是数据同步还是数据融合,都需要在低代码平台中定义对应的meta对象。融合对象是根据领域融合过来的标准融合表单所创建出来的,融合对象既可以放在逻辑层,也可以表现给用户直接使用,这完全取决于产品经理如何定义业务。
  • 原生对象: 由内部的产品和业务架构师定义的,直接通过低代码平台创建的,非融合的,并提供给租户直接使用的对象。
  • 自定义对象: 某租户下,用户自己创建和定义的对象。
  • 运营平台: 低代码平台的业务后台,一是业务SRE管理,SRE中有“产品线”和“版本”两个顶层概念,产品下通过版本管理一切资源,包括业务域和基础对象,基于版本可以对一个标准产品进行运维操作,比如新建一个版本来进行搭建迭代,发布版本到下一个环境直到生产环境以及相应的回滚,同时继承了测试功能,关于低代码的业务测试,我会再开一篇文章进行讨论。二是租户局部拓展管理。
  • 业务域: 根据领域驱动模型(DDD)业务域指是最顶层的业务划分维度。比如销售是一个业务域,下面可以分订单、预测、发货等子域。这里多插一下,做低代码类的产品,是否以业务为中心是一个很重要的概念,这区分了这个低代码的平台是属于“神仙”还是“特定行业内的明星低代码”,是有行业赛道的还是没行业赛道的,是只做PaaS的还是以SaaS为重心用PaaS为SaaS“赋能”的。关于这个讨论在另一篇文章里,做了更详细的讨论。就业务域本身的重要性来说,如果你是一个卖行业SaaS的公司,客户关心的不是你有多牛逼的低代码平台,而是你提供的SaaS功能和业务能力,是否能解决企业的问题;
  • 子域:在业务域之下的二级业务划分。
  • 租户的局部拓展:
  • NOSP后台: 一个后台管理系统,分为租户管理、商业中心、低代码后台管理三个模块。其中租户管理包括了权限管理、租户运营等功能,商业中心涵盖了商品管理、SaaS应用管理、应用路由管理、订单和应用权限等模块,低代码后台包含部分研发SRE工具,实体与表单管理,数据管理等。
  • 对象分层: 对象分层指的是在一个子域内,业务的架构设计,业务在内部是如何定义、组建并关联起来,它决定了业务内的对象关系。在一个子域内部,对象分别落在表现层、逻辑层和基础数据层,其中融合对象是一个比较独特的概念,它既可以在表现层出现,有可能是逻辑层中的元素,其特殊性更体现在,融合对象是业务域的边界,运营平台在为租户开通权限时(下发),以融合对象作为一个业务域在技术上的判断边界。
    • 表现层:表现层是和终端用户直接打交道的,里面包括了用户在运行时直接进行表单创建、查看详情、管理数据的对象。
    • 逻辑层:逻辑层的内容默认是用户不感知的,这些对象承载了业务的内部逻辑,支撑了表现层对象的运行。比如表单定时器(一种搭建策略)除了表现层一个定时被创建的表单之外,实际上还需要2个辅助表单,这两个辅助表单对用户来说是没有业务意义,只是作为实现业务的一个“util”,那这两个辅助表单属于逻辑层的对象。
    • 融合对象:融合对象是根据领域融合过来的标准融合表单所创建出来的,融合对象既可以放在逻辑层,也可以表现给用户直接使用,这完全取决于产品经理如何定义业务。
    • 基础数据:基础数据有两部分组成,一种是全局的基础数据,为各类业务所共用,比如城市地区、颜色、长度单位、比例单位、性别;另一种是子域基础数据,这种基础数据是某块业务所特有的,比如财务里的“借”与“贷”。
  • APIName: 表单系统中资源的唯一标识符。比如
  • 实体与表单: 在代码和数据库层面,对表单信息的基本存储结构;实体的字段是可拓展的,因此表单字段可拓展;
  • 核心模型唯一性: 在拥有核心业务模型的低代码平台中,对于一个业务概念,比如“订单”,在系统中应该只有唯一的一个业务对象与其对应。低代码平台为搭建者提供了高度自由的业务定义能力,业务搭建者完全可以自己定义一套订单系统。

治理和范围

在过去,基于数据同步、数据融合等技术方案,使得在低代码平台中能获取到领域业务系统的接口数据(我们的融合是基于API级别,或者说是粒度的)

治理的范围,不应该只考融合对象这一种场景。

问题

APIName使用的混乱

领域系统的程序员在使用CPS进行业务搭建时,涉及到融合情景的时候,他们的动作路径如下:

  • 登陆NOSP后台,创建表单,选择表单管理,选择新建表单,命名实体APIName
  • 进入表单进行搭建,并修改表单APIName(这一步很关键,他们会直接用实体的APIName)

根据上面的行动路径,领域的程序员在把那段APIName在代码中hard code时,其实并不清楚他们融合的到底是表单的APIName还是实体的APIName

在CPS之前的版本中,实体这个概念在产品功能和用户交互层面的透出,为用户、开发和功能设计者们造成了极大的理解成本和进一步迭代的难度;后来经过产品方案的修正,实体这种逻辑概念被下沉到用户交互层以下,不再向用户直接透出,如下示意图:

自从上面的实体下沉后,领域进行融合所用的APIName所对应的表单和实体基本就是同一个了。但历史的代码中,仍然有部分APIName对应的是实体而不是表单。

对上面的信息进行以下总结概括:

  • CPS既可以接受表单APIName的融合,又可以接受实体APIName的融合。目前这两个口子都是打开的。
  • 领域中大部分融合用的是表单APIName,少部分历史代码用的是实体APIName。

这部分差别,在数据中被统计出来了:

TODO

融合的目标不统一,实体与表单混杂,这会引发更多的问题。以实体为基础的融合,会导致在低代码平台中无法控制融合表单。我们不能限制用户去基于实体去新建表单,如果某实体是通过数据融合来定义的,那再基于这个实体去新建很多的表单,这些表单的数据就都是融合数据。业务的搭建是基于表单进行而不是实体,那这就产生问题:到底哪个表单才是真的标准呢?后续如果融合对象进行升级迭代,要找到所有的表单进行同步更新。

命名的问题

融合对象在创建时,需要关注三类APIName,实体APIName表单APIName字段APIName和一个表单名称,下图的例子中,以supplier为例,这是一个表单APIName,对应的实体APIName,也是supplier,表单名称为供应商official

在过去,以产品和业务研发为主的业务人员,通过在表单名称后加offical 等字符,来标记一个表单是融合的、重要的。这会引发混乱,混乱的来源有如下几个原因:

  • NOSP后台中,低代码管理部分的功能十分薄弱,只能在表单/实体的粒度进行管理,无法直接的进行业务管理。不能从业务线->产品/功能模块->具体表单的顺序,自上而下的进行管理,只能管理最小粒度的“物料”。原始的低代码后台管理 表单管理

  • 无法进行业务区分和撞名。搭建器中透出的对象,只有表单名称而没有APIName。表单名称(不是APIName)是在用户交互层之上暴露给用户进行操作的,表单的名称表示了对应的业务对象。在下图中我虽然表示了订单(order)订单2(order2)订单offical(order_officail),其中表单名称后的括号内还带了APIName,而实际上在表单搭建器里只体现了表单名称,而表单名称是可重复的,就会出现订单(order)订单(order2)订单(order_officail)的奇葩情况,另搭建的人无所适从。

  • 类型区分问题。类型区分指的是,用户无法知道若干个对象里,哪个对象是融合对象,哪些是原生对象,哪些是自定义对象。这一点在业务搭建里非常有意义,因为这也是混乱的来源之一。举例来说,如果有订单(order)订单(order2)订单(order3),即便我们在对象选择器中标记了APIName,并且order融合对象order2原生对象order3是自定义对象,那只从APIName上,你作为一个搭建者能分辨这三者吗?

  • 对象命名的冲突和混乱,这里不举例子。

  • 从表单层面,对融合的业务对象的定义是不统一、不唯一的,就导致在搭建器中,透出到用户交互层以上的对象的不统一、不唯一,从而造成了搭建者的混乱,这种混乱导致搭建者定义的业务模型是建设在不稳定的对象基础上的。像图中所示的三个业务域,库存依赖的order,财务同时用了order和order2,销售单独依赖order_official,在这种情况下,后续迭代中单独更新任何一个“订单”对象的自定义字段,拓展其功能都无法自动同步到其他有同样业务意义的“订单”对象。对某个“订单”对象的字段删除又极易成功能衰退。而这种问题,随着搭建的业务越来越多,规模越来越大,其产生的破坏力和延后解决的代价是难以估计的。

在上面,我已经大致的枚举了命名的问题,并做了一定程度的归类和抽象。这些问题的成因都不是孤立的,而是有迹可循,有其共性的。结合APIName使用的混乱章节里提到的业务粒度问题,聪明的你一定已经发现了,抛去表面的鸡毛蒜皮功能,这里最核心的错乱都是来自于业务粒度问题。如果领域系统中的APIName对应的是实体,那么在低代码系统这边,从根本上就无法管控对象的创建了。

由此就回到了22年3月关于实体和表单关系的大讨论。当初决定实体与表单进行一对一绑定,并对系统做了修改,但当时并没有把事情做干净,起码在融合对象的问题上没有考虑到。

实体与表单的一对多关系、基于实体的数据融合,是导致上述混乱的根本原因。

架构的问题

设计对象结构

设计对象字段

流程问题

上面讨论了业务混乱的根本原因,但这只是“体”与“器”而非“本”与“道”,换句话说是基础设施不健全导致的。系统想要正确的运行,系统设施本身只能决定手段,更大程度上取决于参与其中的人,从运营的角度上说,流程规范的明确是比设施更重要的。上述的混乱的另一大原因是公司内对于融合没有清晰明确的规则,在这个规则里要声明完成一次业务定义要经历几个核心的流程节点,每个节点参与的人、要素、事情,以及串联这个流程的必要审批。

这个流程又分为如下的几个场景(之所以列的这么细是因为每个流程都不一样,其中涉及了不同的要素):

  • 新增业务域
  • 新增基础数据
  • 新增融合对象
  • 新增原生对象
  • 删除业务域
  • 删除基础数据
  • 删除融合对象
  • 删除原生对象
  • 修改基础数据
  • 修改原生对象
  • 修改融合对象

其中每个操作都必须配备特定的审核流程。对于修改的操作,指的是对象/数据内字段级别的修改,而非对象/数据本身的增删改查。目前在业务域中已经支持了版本,版本的定义是在业务线之下,版本管理一切。当初这么设计的初衷就是为了应对后续的对象迭代与管控的场景时,版本可以作为流程管控的一个基础,在这个基础上再进行进一步的审批拓展,把版本管控来作为一个通用的流程审批来减少重复性的审批劳动。

从版本审批出发,增删业务域、增删原生对象、修改原生对象的操作的大部分审批需求就可以得到满足。基础数据在版本审批中额外加入corepaas产品审批,融合对象在版本审批中额外加入领域产品+corepaas产品审批。

升级迭代的问题

融合对象本身的升级迭代

首先需要明确的是,融合对象的迭代属于高危操作。就像搭积木,搭了100层以后,从最底下的一层抽出来一块,再放回去一块,很难保证上次的业务积木不收到波及,最终导致整个模型的坍塌。

引用融合对象的业务升级迭代

对搭建的影响

对象治理之后,由于和SaaS系统的数据融合被锁定在了表单层面,那基于实体融合来进行的实体表单一对多的搭建方案会无法使用。但这种方案本身也是不稳定的,因为对一个核心业务对象拆分成多个表单,在业务模型上,相当于把一个原子性的业务拆分成了更小粒度,这是不合理的,无法保证事务一致性,进而使业务变得松散和不稳定。

下面我画了一张图来展示实体表单一对多的搭建方案,从左到右分别展示了表单搭建所产生的meta模型和最终运行时数据。

从上图中,600个cell的实体这个是夸张的说法,一般来说低代码平台会对这个数字进行限制,用户创建业务模型时,其字段数量是有上限的,而这个限制其实是对应关系型数据所创建的数据列上限,这个数据列指的是用于存储用户运行时数据的那部分DB。从这里我们就可以感受到一种深水区的感觉,我们从平台层面向下透视到了DB设计的层面,他们之间都是环环相扣的。

同时这个所谓的实体,给人一种“宽表”的感觉,实际上低代码平台用来存储用户运行时数据的数据库里,存储数据的table就是宽表,一张表上定义几百个column,用数字编号,比如COL_1,COL_2...COL_500, 那实体最大就是500。

回归到对象治理的话题上,由于业务融合锁定在表单的定义上,和表单的字段是对齐匹配的,那一个实体对应多个表单的搭建方案自动失效。历史上使用过这种套路的业务,其数据会被订正,若没有及时迁移整改,就会导致业务失败(表现为若干表单拿不到数据,无法CRUD等等)。

问题的影响

问题的表象

问题的本质

方案

前后的变化

变化的本质 -> 设计业务架构

对工作流程的影响

  • 业务产品经理
  • 委员会

拓扑示意图

TODO

架构图

TODO

业务架构

功能设计

解决命名问题

工作内容:

  • 基于业务域,定义对象命名规范,实现对象命名的强限制

    • APIName
      • 不可撞名
      • 标准对象 ${pk}STD${biz_domain_code}_${biz_obj_name}
        • P1_STD_FIN_Bill
        • P1_STD_GMJ_Tools
      • 融合对象 ${pk}SYN${biz_domain_code}_${biz_obj_name}
        • P1_SYN_PRD_productionOrder
        • P1_SYN_ERP_order
      • 自定义对象 保持目前表单命名规则
    • pk
      • 以大写“P”开头,后跟数字
      • PK
        • c2: P1
        • 酷工厂:P2
    • biz_domain_code
      • 生产
      • 售后
      • 财务
      • 异常
      • 库存
    • biz_obj_name
      • 语义化
      • camelcase
      • 禁止特殊字符
    • 表单名称(display name)
      • 不可撞名(后期考虑改成可撞名)
      • 中英文开头
      • 只允许特殊字符dash:-
  • 对所有研发推广这种命名规则,并在上述的命名强限制通过技术实现在运营平台后,推广给其他人如何使用。

  • 在搭建器内暴露。

结果:

  • 彻底解决命名的混乱
  • 若【确定统一的融合对象】部分实现,理论上不会再出现有产品经理为找不到应该关联哪个对象的问题发愁。

管控

工作内容:

基于业务域,收敛表单创建入口,统一在运营平台管理融合对象,原生对象,以及租户的自定义对象

  • 第一步:运营平台内实现基础数据管控
  • 第二步:运营平台内实现业务域内,基于分层(表现层+逻辑层)的对象管控
  • 第三步:对nosp内存量对象进行统计分类,归属到运营平台对应的业务域和分层中。这个实际上是【数据订正】的工作,但作为管控的一环,这里再提一次。
  • 第四步:在本次治理其他工作完成后,关闭NOSP的创建入口,只保留查询功能,作为研发的sre查询工具

结果:

  • 首先这是【一批】对运营平台本身的迭代需求。
  • 这批需求是在为承接nosp内混乱的业务来建设基础设施。
  • 这批需求做完,理论上运营平台就具备了承接业务模型的能力,在业务域内管控业务,定义业务,重建业务。

统计工作

工作内容:

  1. 统计融合表单+融合实体。
  2. 目前任曦已经统计过1次,但数据仍然有不清晰的部分,技术要进行核查
  3. 领域技术对最终结果要二次复核
  4. cps技术对最终结果要二次复核
  • 领域+corepaas的研发分别确认对象统计的结果,并进一步在后台数据进行对比审查

结果:

  • 统计的结果要用来评估影响面,一旦这一步统计数据有问题,影响面评估必定有问题
  • 统计的结果是进行【解决APIName和融合问题】的指导信息

影响面评估

工作内容:

  • 基于统计结果,评估业务影响面(二开+标准功能),需要后台通过DB进行查询评估

    • 影响的租户
    • 影响的业务
    • 租户形如:
      • 业务名 分类 PD 影响租户
      • biz1 二开 章三 租户A/B/C
      • biz1 标准 王五 租户A/B/C
      • biz1 二开 赵六 租户A/B/C
    • 业务形如:
      • 业务名 分类 PD 目标表单 动作 from to
      • biz1 二开 章三 APIname A 修改引用 wrongAPIName targetAPIName
      • ​ APIname B 删除
      • biz1 二开 王五 APIname C 修改引用 wrongAPIName targetAPIName
      • ​ APIname D 修改引用 wrongAPIName targetAPIName
      • ​ APIname E 修改引用 wrongAPIName targetAPIName

结果:

  • 这一步是为了【存量业务整改】而服务。
  • 产品经理按照影响面统计中的数据,各自跟进整改自己所负责的业务,指导整改的迭代和发布。这个信息对测试和安全生产有指导性意义。
  • 当统计的影响面中所涉及的业务全部整改完成,说明所有cps表单所支撑的业务都已运行在统一的融合对象、标准的原生对象,以及共享的基础数据上了。

解决APIName和融合的问题

工作内容:

  • 【技术需求】领域的apiName全部从数据同步切换到数据融合

    • 业务应该是无感的
  • 【技术需求】领域融合的APIName全部切换成表单维度,确保唯一性

    • 业务应该是无感的

结果

  • 这一步是后续的基础性技术工作。
  • 首先数据同步到数据融合本身是一个纯粹技术工作,但要考虑这种切换的价值,有可能切换的对象本身就不再使用或者意义不大,甚至对象本身的定义也是不合理的。
  • APIName从实体到表单的切换,这个操作是具备风险性质的,可能导致在cps搭建的上层业务里,那些基于共有实体创建的表单失效。

关闭实体入口

工作内容

  • 【技术需求】领域切换完成后,corepaas表单系统关闭实体的融合入口,确保目前的融合全部是表单维度
  • 向领域技术说明前后差别,明确概念,统一名词。

结果:

  • 不再支持实体数据融合,这在根本上解决了APIName混乱与表单不可控问题
  • 不再产生实体融合。

数据订正

工作内容:

  • 产品:1. 在任曦给的excel里填写内容,说明要放在业务域内的表单,备注好是原生对象还是融合对象,并分层。2. 在订正完成后确认数据无误,业务可用。
  • cps表单系统研发:根据excel,完成数据订正。

结果:

存量的标准业务,全部迁移至业务域内统一管控

确定统一的融合对象

工作内容:

假设你负责财务类系统,你有100个表单,其中10个是基础数据,50个原生对象,40个融合对象。

  • 你要确定你用到的基础数据,告诉任曦。因为基础数据在一条业务线内是为所有业务公用的,你的修改诉求要回影响全局。我会提供一个excel让你填写,你在里面定义你的基础数据和内部字段以及数据内容。
  • 你要确定你用到的标准对象。理论上如果数据订正完成,你的对象都会被放在你所负责的业务域内。
  • 你要确定并梳理明白,你要用的融合对象,并填写excel。
  • 随着迭代需求,根据excel中对融合对象的定义,领域进行实现和迭代式整改

结果:

  • 融合最终是基于表单的

  • 对于同一个业务意义的对象,在cps的表单系统里只有唯一的标准定义

存量业务的整改

工作内容:

  • 理论上走到这一步,已经差生了统一的融合对象
  • 业务产品经理和实施,根据业务影响面评估的结果,对应组的产品/实施调整搭建方案。
  • 【后置】当大量的业务已经整改完成后,作为后续的收尾工作,要对遗留下来的垃圾融合对象、垃圾原生对象进行一次清理,做逻辑删除。

结果:

  • 业务域内的内容,都是标准化的,之后可以正式的开始依赖业务域展开后续迭代。
  • 标志着本次支持取得阶段性成果。

流程定义与推广

工作内容:

  • 实现审批

  • 定义审批流程和规则,确定核心节点,以及节点内要素。

  • 定义工作流程,撰写运营平台使用的规范和流程。

    • 如何迭代业务域
      • 使用版本
      • SRE
    • 如何处理融合对象
    • 如何处理基础数据
  • 推广流程,使这套规则运行起来。

结果:

  • 这一步的完成,是超越了对象治理本身的既定目标,超额完成。理论上这一套系统的执行,会从根本上改变整个产品团队和产品本身的工作模式。
  • 所有搭建的业务元素,全部纳入管控体系之下,按需可控的进行后续迭代。
  • 这套体系的运行,为后续的建设提供了可能性,后续的团队管理、流程管理、业务管理及运营,迭代的生命周期,产品管理及运营,都可以再这个基础上进行后续的发展。