之前在《2021 前端会有什么新的变化?》一篇 10W+ 的回答中有提到 imove,大家对这个开源项目颇为感兴趣,这里将它背后的设计思路和背景做一下介绍,从概念到实践,各种曲折也是颇有思考的。
F2C 即 Flow 2 Code,即通过流程可视化编排来产生代码。这不是一个新的概念,但确确实实是跨界整合的一个经典案例。在做前端智能化的过程中,我们发现,在 UI 侧有 imgcook 这样的设计稿转代码的工具,应对变化是足够的。但在逻辑领域,真正能解决问题的又面向开发者的少之又少,imove 算这个方向的一个探索。下面,我们一起来看一下吧。
从 FBP 到 BPM
为了能够让大家更好的理解 F2C 这个概念,我们需要先交代一下背景,当前业界的做法和研究。
可视化编程工具
大多数流行的可视化编程工具都只是基于文本代码之上的抽象,在实时图像渲染,数据处理,程序架构等方面应用是非常多的,像 UML、ER 图也都属于可视化编程工具范畴的。参考 https://nodes.io/story/ 里的文章,我们可以看一下可视化编程工具有哪些。
Scratch 是一款由麻省理工学院(MIT) 设计开发的少儿编程工具,支持多国语言,可以在 Windows 系统、Mac 系统和 Linux 系统环境下完美运行,软件分为网页版和单机版,网页版需要电脑上网才可以运行,单机版不需要上网即可独立运行。其特点是:使用者可以不认识英文单词,可以不会写代码,就能制作出自己的编程作品。因为 Scratch 构成程序的命令和参数都是通过积木形状的模块来实现的,小朋友用鼠标拖动模块到程序编辑栏就可以进行编程了。
https://scratch.mit.edu/projects/411101291/editor/
像下面这种图像纹理处理,就做的非常直观。
人工智能化是另一个计算机图形学领域,比如神经网络,就非常喜欢使用节点和线框来做可视化。
Nodes 是一个创意工具.
无疑,可视化工具是非常好的方式。这其实也是非常吸引开发者的,开发者习惯性编写代码,但代码如何做可视化呢?一种实现就是 FBP。虽然没有火起来,但确实是很有价值的实践,在某些领域,比如 iot,是非常具有参考意义的。
FBP
Flow Based Programing 是由 J. Paul Rodker Morrison 在很早以前提出的一种编程范式。
概念
维基百科对 FBP 的定义如下:
In computer programming, flow-based programming (FBP) is a programming paradigm that defines applications as networks of "black box" processes, which exchange data across predefined connections by message passing, where the connections are specified externally to the processes. These black box processes can be reconnected endlessly to form different applications without having to be changed internally. FBP is thus naturally component-oriented.
Flow-Based Programming,简称 FBP,是一种数据流编程范式,有着一组独特的特性,同时是基于组件的软件工程方法的一种。FBP 把一个应用看作一组进程(process),进程间通过连接(connection)进行通信,进程通过端口(port)来访问连接(这种抽象类似网络编程)。
在 github 的这个 https://github.com/samuell/awesome-fbp 项目内列举了很多不同语言对该范式的实现以及一些资料,大家可以参考。
很可惜,FBP并没有普及,感谢炽宇老师知道,让我理解了这些概念。但这不影响我们能看到一些类似的案例。
社区研究
前端社区知名大 V,TJ Holowaychuk 曾在一篇《You might not need if statements: a better approach to branching logic》较有争议性的技术文章中评论到:
“I thought about doing similar, I think flow-based programming is really cool, and we’re pretty much the only industry to not adopt it. That said functional languages like Elm pretty much fill this niche just fine, it’s JavaScript that is the problem in general.”
《What the hell is Flow-based-programming?》https://medium.com/bitspark/what-the-hell-is-flow-based-programming-d9e88a6a7265
Flow-Based Programming 是一种很好的组件编程方式,基本概念就是
把可复用的代码抽象成组件,组件有 输入、控制、输出端口。
用 DSL(领域专用语言)把不同组件的输入、输出端口连起来,组合出复杂的功能。控制端口用于初始设置组件的功能。
最后由 Flow - Based runtime (引擎)解析 DSL ,让所有组件一起运行完成你所需的功能。
Iot 场景
FBP 还可以应用在嵌入式设备上,尤其是适用于智能家居行业这种需求复杂多变的场景里。如下是控制 AR.Drone 起飞,降落的例子
// Start by connecting to drone. We could provide IP here
'' -> IP Connect(ardrone/Connect)
// Tell drone to take off
Connect() CLIENT -> CLIENT Takeoff(ardrone/Takeoff)
// Tell drone to land
Takeoff() CLIENT -> CLIENT Land(ardrone/Land)
// And that is all, folks!
Land() CLIENT -> IN End(core/Drop)
这些传感器只有输入和输出,尤其适合的 FBP。
相关介绍网址:
http://noflojs.org/example/
http://www.jpaulmorrison.com/fbp/index.shtml
BPM
BPM的意思是:即业务流程管理,是一套达成企业各种业务环节整合的全面管理模式。BPM不但内涵盖了传统“工作流”的流程传递、流程监控的范畴,而且突破了传统“工作流”技术的瓶颈。
工作流最早起源于生产组织和办公自动化领域,它是针对平时工作中的业务流程活动而提出的一个概念,目的是根据将工作分解成定义良好的任务或角色,根据一定的原则和过程来实施这些任务并加以监控,从而达到提高效率、控制过程、提升客户服务、增强有效管理业务流程等目的。
工作流管理联盟(WFMC)把工作流定义为:全部或部分由计算机支持或自动处理的业务过程。
工作流管理系统(Workflow Management System,WFMS)用来支持流程定义、管理和执行一批设定好的工作流程。这套系统的目标是:管理工作流程以确保工作能够在正确的时间内被所期望的人执行。在自动化进行的业务过程中“插入”人工的干预,是工作流系统开发者的主要工作内容。
做Java的同学大致都熟悉 activiti 和 jbpm 这里成熟的 bpm 引擎。
对于经常变更,有明确流程的功能都可以使用 bpm 引擎来实现的,这里就不再赘述。
什么是 F2C?
F2C,全称 Flow 2 Code。即通过流程可视化编排来产生代码。
对于逻辑代码可视化编排,我是非常认可的,对于开发领域,确实是可以提高研发效率的。在做前端智能化的过程中,我们发现,在 UI 侧有 imgcook 这样的设计稿转代码的工具,应对变化是足够的。但在逻辑领域,真正能解决问题的又面向开发者的少之又少。站在前端领域视角,这可能是一个极好的探索。
前端痛点
我认为前端,尤其是前端开发中问题很多,尤其是以下3点
UI 老变,导致开发必须跟紧
逻辑挑战,开发也必须改代码,很多后端处理逻辑都在里面
组合接口,这是历史原因,主要是和后端配合导致的。其实没有 node 层,都由组件来做,会问题非常多。
好在前端发版本比较容易,但这也加剧了组件的开发难度。
为什么所有的修改都要前端的改呢?这个逻辑不对。最近几年年,一直都是活动中前端最累,做各种重复工作,以致于大家的感觉是前端是瓶颈。对此我是非常不认可的。其实我们可以让运营不找前端开发就能完成这些事儿的。这才是提效要做的事儿。未来前端可以做以下4点。
逻辑可组装:其实是接口和 UI 在最小粒度上的复用。
流程可视化:这些可复用的最小单元,可以通过流程来进行编排,继而达到让运营简化的目的。
运营配置收敛:这是因为多套系统导致运营成本很高导致的,统一放到一起最好。
玩法能力沉淀:促使产品将玩法进行沉淀,变成可复用的能力。并在一年中反复使用,以提升业务数据为目标,这样才能做出产品化的好东西。
组件抽象
对于 Web 前端而言,核心是以组件开发为中心的,组件中能够改变 ui 的只有 2 个动作:分别是组件生命周期和事件处理。这个是根据各种活动的交互实现推断出来。
一般在 ComponentDidMount
里发起请求,根据请求成功的数据完成渲染或其他业务逻辑,这种是完全无 UI 的 Ajax 请求处理。
除了,组件声明周期,就只有各种交互事件里,这里面一般是 UI 和 Ajax 混用的场景。具体看一下应用场景。
举几个例子
比如点击事件,比如图中的用户领券流程,发送 Ajax 请求之后,通过 toast 弹出领取结果。
领券流程,首先需要对用户进行鉴权,确保用户是已经登录的。这个在 App 里需要使用 JS Bridge 来做,这个也是 JavaScript 编写的,所以也能够以 JavaScript 函数来调用。但用户鉴权和领券是 2 个行为,它们之间需要通过参数传递来连接起来。
UI+API 混用:比如前端点击事件,Ajax 请求和后端 API 是可以编排出来的。依然以领券逻辑为例,先做用户鉴权,如果用户已登录,进行发券,如果用户未登录,跳转到登录页面。这里需要说明的是发券分 2 个步骤,1 个是 Ajax 调用,1 个是具体服务端 API 实现,如果服务端 API 使用 Node.js 或 Node FaaS 进行透传,是可以建立 2 个流程,分别部署的。
对于服务,其实有很多思考,比如分类为端渲染和业务服务。这样就服务进行广义化,无论前端,后端,API 代理都是服务,只要涉及了 Server 端提供的服务都算的。
从前端视角看,服务可以做的事情更多,CDN 是 Server 端的,Node FaaS 也是 Server 端的,这才是围绕 JavaScript 可以做的广阔空间。
其实,这些都是 imove 要能做的事儿,也是 imove 设计之初要实现的应用场景。如果通过结构化业务逻辑编排,同时生成放到 CDN 上的代码和 FaaS 上的代码,是不是一举两得,可以将前端的复杂度降低,甚至说在 Lowcode 领域,再夺一城。
能否像运营配置一样开发?
我的好基友侯策曾在知乎上发表一篇文章 《「可视化搭建系统」——从设计到架构,探索前端领域技术和业务价值》https://zhuanlan.zhihu.com/p/164558106
侯策说“几乎每一个前端团队,都会有一个页面搭建系统”。页面搭建技术是一个老生常谈的话题,可这个话题伴随着前端技术的发展,历久弥新。究其原因,包括但不限于:
运营活动页面对于产品业务至关重要,是吸引流量、提高留存的关键手段
高频且重复度较高的活动页面开发,对于前端意味着大量的时间和人力成本消耗
在此背景下,快速页面搭建技术就显得尤为重要。其特点和技术方向可以各有特点,但技术原理总体可以归纳为以下图示:
简单讲,搭建就是在强运营体系下的必然产物:开发模块,便于运营配置使用。
这种搭建是对运营极其友好的,从运营同学作为搭建主要用户的角度来思考,以及无线化场景下,手机屏幕的特征,一维存储的模块列表是比较友好的。这个设计也对搭建服务本身带来了很大的简化,整个页面结构就是一维数组,每次操作都可以转变成一次简单的数组操作。当然,一维的存储不代表一维的展示,开发者依然可以在展示的时候,通过一些父子关系,来把一维的存储结构转变为树状结构。目前我们是判断把复杂度给开发者,简单的操作给到非技术同学,还是一个比较合适的方式。
再来回想一下我们开篇讲的命题,前端在逻辑处理侧的代码,能否也这样实现呢?
大家的逻辑其实也就是一个流程图。很多人在开发之前是有画流程图,ER图,UML图习惯的,其实就是想梳理清楚,经过设计抽象,做出能应对变化的好软件。
我们不能假定业务一成不变,所以在变化的时候,能够快速应对变化是非常重要的。运营搭建系统的好处是,页面由模块组成,模块是开发提前开发好的,拖进去配置一下就可以发布页面了。我们写的代码其实也是有一样诉求的。
大部分函数里的代码都是面向过程的,组装判断是非常随意的,也未必能做到单一职责。
如果能够可视化编排这些功能,双击节点编写代码,选中节点右边可以配置参数,是不是很有想象力呢?
Flow
可视化编排其实有很多年的时间,以工作流管理 BPM 最为成熟,类似于 xstate 这种先定义状态机,然后再可视化也是一种思路。其实,无论哪种,都是围绕 Flow 来进行的。
Flow 的基本概念很简单,就是一个有向无环图(DAG),数据在节点间流动。
节点 Node
节点是组成流的主要单元,负责对流入节点的数据进行处理,并输出到后续节点进行进一步的处理。
端口 Port
每个节点拥有输入和输出端口,输入端口负责数据流入节点,输出端口负责数据流出节点。每个节点都可能拥有一个或者多个输入和输出端口。
连接 Link
一个节点的输出端口连接到另一个节点的输入端口,节点处理好的数据通过连接流入其后的节点。
Flow 的实现基本思路就是用一个函数 function 实现一个节点,输入端口映射为函数的输入参数。输出端口映射为函数的返回值。
流中有一个节点被设置为终点节点(End Node),通过节点间的连接关系,以终点节点开始通过连接搜索所有的依赖关系(树形查找),得到一个节点运行的栈。例如上图,我们就可以得到一个 [node1,node2, node3] 这样的栈。按顺序出栈的方式执行每一个节点的功能就可以运行整个流。(注意,这是一个简单版本的 Flow 的实现,仍然是一个批处理,不是 streaming)
需要假定每一个节点的功能是无状态的,这样就可以利用输入输出端口对计算结果进行缓存,但输入值是已经运算过的值的时候,不需要运算,直接返回已经计算过的值。
imove
iMove 是基于F2C思想进行设计的开源项目。一天就涨了 280+ star,一举登上了 github
趋势榜第 1 名,取得的成绩还是不错的,说明这个项目定位准确,确确实实解决了开发者问题。
那么,什么是 iMove?
iMove 是一个逻辑可复用的,面向函数的,流程可视化的 JavaScript 工具库。
它是个工具,无侵入性。
双击编写函数,编排后的流程可以导出可执行代码,便于在具体项目里做集成。
测试方便,右键直接执行,此处有创新。
让开发像运营配置一样完成功能开发,做到复用和Lowcode。
界面如下。
简单讲,其实我们理想的前端可以做以下4点。
逻辑可组装:其实是接口和 UI 在最小粒度上的复用。
流程可视化:这些可复用的最小单元,可以通过流程来进行编排,继而达到让运营简化的目的。
运营配置收敛:这是因为多套系统导致运营成本很高导致的,统一放到一起最好。
玩法能力沉淀:促使产品将玩法进行沉淀,变成可复用的能力。
对开发者而言,iMove 恰好是可以完成这些目标的理想工具。动动鼠标,写一下节点函数,代码导出,放到具体工程里就可以直接使用,是不是很方便?
imove 的口号是Move your mouse, generate code from flow chart
,即动动鼠标,写一下节点函数,代码导出,放到具体工程里就可以直接使用。像运营配置一样开发,这已经不是愿望,而是已经实现了的。如果大家对imove感兴趣,也可以一起参与开源项目中。
总结
我相信 imove 只是 f2c 的一个开始,未来应该有更多 f2c 实现。做 imove 的时候我们其实也慎重的考虑 roi 的,事实上,定位对了,站在用户视角解决问题,它就应该是一个好方案。
当然除了这些事项,还有很多思考。
F2C 基于流程图,就意味着节点和边等元数据,可以采用。图将实体表现为节点,实体与其他实体连接的方式表现为联系。我们可以用这个通用的、富有表现力的结构来建模各种场景,从宇宙火箭的建造到道路系统,从食物的供应链及原产地追踪到人们的病历,甚至更多其他的场景。比如从 Apahce TinkerPop 对属性图模型(Property Graph Model)的管理,检索是非常有可能的探索。
F2C 基于流程图,让函数和函数之间进行编排,结构化。这些就为 AI 做好了出码准备。目前 nl2code 的准确率不足,如果有了这些结构化的样本,通过AI组装还会远吗?
产研问题求解,找到 PD 和开发之间的映射关系,其实在出码中也是能够更好的解决的。把视角放大了看,PD 的流程是一个节点,那么开发流程就是这个节点的子流程。
F2C 目前还是一个探索,真的将运营配置的方式引入到前端开发中,让开发流程可视化,可编排,可以探索的方式除了 imove 外还应该有很多。希望有更多同路人,方向对了,路还怕远吗?