前言
前一篇文章里讲解了逻辑与Runtime&DSL,也提到了逻辑编排三板斧:元件 + 编排器 + Runtime,我在本篇将主要聊一聊元件设计以及YOHO的平台化。
元件
元件在我们的设计中,分为基础元件和业务元件,业务元件就是我们需要创建仓库、编写源码、提交发布的的元件,它是逻辑片段的实体;除它以外的都是基础元件,我们在设计给好莱坞使用的编排方案中。基础元件只有开始元件和结束元件,只是为了降低非研发人员的使用成本,元件越少越好。
虽然分成了基础元件和业务元件,但业务元件实质上是一种特殊类型的基础元件,它们的关系类似于树和图,树也是图的一种,但书里常常会把书拆成单独的一个章节,因为树的体系足够大。业务元件也是,它就是基础元件中的 Custom 元件,但在元件体系中它的比重足够大,所以我们也将它抽出来作为一个大类来讲。
元件语言
业务元件的几个重要属性如下:
初始化业务元件后,我们定义的文件结构:
.
|-- schema
| |-- input.json
| |-- output.json
| `-- branch.json
|-- index.js
|-- package.json
- index.js: 元件的入口文件,源码就写在里面,发布时文件中的源码会被作为 code 字段进行存储
- package.json: 元件的 dependency 就是从里面读取,作为元件的依赖项进行存储,和 code 字段配合使用
- input.json: 配置元件编排时渲染属性表单的JSON Schema,作为元件的 input 字段进行存储
- output.json: 用于描述元件的返回值,同样为JSON Schema,作为元件的 output 字段进行存储
- branch.json: 描述元件有几个分支,以及每种值的中文定义是什么
我们对元件中分支判断的代码制定了规范,配合 branch.json ,将这种分支型业务元件的使用成本降到了最低,使用的复杂度转嫁为开发的约束性。拿《判断是否登录》元件举例,它有两个分支,已登录 与 未登录,代码进行分支判断是必须按照如下的格式书写:
function foo() {
if (isLogined) {
return { branch: 0, data: { key: value } }
} else {
return { branch: 1, data: { key: value } }
}
}
如果已登录,返回 branch 值为 0 ,如果未登录,返回 branch 值为 1。那么对应的 branch.json 必须如此定义:
['已登录', '未登录']
元件中返回的 branch 的值,会作为 branch.json 中的索引,元件中分支实际判断标准要和 branch.json 中的数组一一对应上,这样 runtime 才会按照正确的走向执行逻辑。
元件整体设计
基础工具侧,我们提供了模板初始化的能力、提供对应的元件开发脚手架,保障元件的基础开发能力,正在建设的 VSCode 插件用于提升研发体验,基于元件 OpenApi 提供的 元件 SDK 能够帮助元件录入元件市场,目前还只是服务本地研发,4月会进行线上元件开发的能力补齐。元件的表单配置项借助 form-render 实现了可视化的表单搭建,很好用,点赞。
基于底层设施,上层实现了统一的元件市场,会按照应用、标签等进行隔离,所有业务的元件在元件市场中收敛,方便以后统一落入优酷物料中心。
元件的一生
一个元件从被生产到被编排,最后在页面被运行,贯穿了逻辑编排的始末,也是“逻辑是核心”的论证,下面我们就以元件的视角来看看整个逻辑编排过程中它都经历了啥。
元件被发布后,进入元件市场,在编排界面,被拖拽生成元件实例,构建完整的业务逻辑。画布中,branch.json 被用于阐述各个分支,input.json 中的 json schema 通过 form-render 渲染为可配置的表单。编排实例创建完后,与UI编排进行关联,在UI搭建平台中创建的坑位,会需要元件执行后的返回值渲染UI,UI搭建平台会解析元件的 output.json ,将所有数据平铺展示。业务模块搭建完成后,跟随页面发布上线,runtime经过 启动 --> DSL 解析 --> 元件加载&注册 --> 元件检查 --> 元件执行 链路执行业务相关动作,在 元件执行 这一步,runtime 会进行 helper 和 payload 注入,提供帮助函数以及配置数据。
两个问题
这里有两个问题是我们落地过程中争论过的点,也希望各位看官提出自己的见解。
- 先是业务元件 还是 结束元件?
- 元件的 JSON Schema可以被修改吗?
前端特色的逻辑编排
集团内目前还是服务编排和业务编排比较多一点,也有服务端的逻辑编排,前端侧的逻辑编排却不多见。如果你对逻辑编排、业务编排、服务编排不是很清楚,推荐这篇文章 —— 《业务编排、服务编排、逻辑编排的区别》。在落地可视化搭建系统的过程中,结合搭建技术我们做了一点比较前端质的实现。
我们的模块搭建系统,每个模块都会生成对应的 CDN 资源,页面组装的时候,会将页面用到的模块资源在服务端进行拼接 —— JS Combo。在逻辑编排落地的过程中,我们一不希望入侵现有构建服务,增加开发适配工作,第二也不希望逻辑编排增大页面 JS Bundle。所以在 runtime 的 dslWillInterpret 生命周期里,我们进行逻辑元件的资源按需动态加载。元件都很小,一个完整的流程对应的 JS 资源只有几 KB,这一点加载时间暂可忽略。配合上对已加载元件 JS 资源进行缓存重复利用,需要加载的资源体积会进一步减少。
这个方案帮助我们解决了另一个问题,就是同一个业务模块中,我会创建多个编排实例,两个编排实例可能会在维护过程中出现使用同一个元件的不同版本,这种场景下,如果我们不进行按需动态加载,页面的 JS Bundle 可能会不可控地急速扩大。此时回头看,按需动态加载逻辑元件,帮助我们将页面的逻辑从 JS Bundle 中抽离了出去,替换成了简洁的 DSL,页面的 JS Bundle 也变小了,对于性能还有提升。
YOHO平台
YOHO平台的结构如下。
在图的最右侧,有我们对 YOHO 的定位,它是一个平台。我们不希望做完全中心化的平台,我们只想约束协议、规范,基于这套编排协议做统一的 node 服务,对外提供 OpenApi;在前端交互侧,不奢求一套交互可以满足所有业务,编排器的外框架只会基于编排协议实现各个板块的适配器,你可以选择用或者不用我们提供的面板或者画布,或者选择性的用,编排器同样会基于这套协议去实现自动检查、编排快照等能力。
未来规划
FBP,业务逻辑编排最后一公里
这就需要提到我们当初做YOHO平台,要服务营销搭建平台的愿景了。将业务模块从易到难进行排列,前面75%的模块将由逻辑编排来覆盖。剩下的25%包含了我们的玩法类的或者定制性极强的模块,它们共同特点的逻辑要求高,内部状态多,想支持,也能支持,但元件调试发布、编排调试发布显得极为麻烦,在我们的预期中,这部分复杂模块是由研发来承接的。
可视化搭建中逻辑编排的最后一公里还有解法吗?是可解的,基于现有能力去扩展 FBP 能力,让研发能够基于流来编程,在线编写 --> 在线测试 --> 流程纠错,你不仅可以更快的开发,而且你的代码会更加安全。
总结
逻辑编排的价值:
可视化:简化了业务逻辑的生产
UI与逻辑解耦:提高业务模块的可维护性
逻辑复用:逻辑可以通过连接为多种不同的方式来产生不同的行为,会更好的代码复用能力
天然跨端、跨容器:因为是纯 JS 执行,天然适配各端、各容器内。它的更深远意义是,如果UI + 逻辑能够覆盖所有模块开发,对于rax0.6 升 1.0、Weex 切 Kraken这种场景,迁移成本可以降低 90+%
在线测试、自动纠错:让你的代码更安全
YOHO的价值:
统一大团队内的逻辑编排规范约束
便捷的工具/库便于逻辑编排在业务中落地