浅析完全声明式编程
入职一星期,做了几个项目组的常规需求,顺便过了一下小组项目的整体代码,发现的一个比较明显的问题就是由于项目本身的特点,前端的重复业务逻辑比较多,导致有大量copy&paste出现,应该需要一个减少重复逻辑上投入人力的方案。就是本文想谈到的一个思想了——完全声明式编程。
概念介绍
在谈到完全声明式编程之前,可以先从jQuery的时代开始说起,如果要用JQ实现一个需求,会先用HTML和CSS绘制出页面,再通过一系列JQ方法为DOM绑定相关JS逻辑,基本上就是将需求翻译为业务代码的过程,这种思路被称作命令式或者过程式编程。后来有了三大框架之后,在处理业务逻辑之前,会通过框架做一层data到view的代理,那么将需求翻译为代码时,就可以多考虑一层,将视图的表现转化为数据的变化,开发人员真正需要关注的东西或者说手动实现的部分能够集中到数据的处理上,通过我们声明的响应式数据驱动框架接手DOM的变化,这种思路被称作部分声明式编程,为什么只是部分声明呢?因为被接手的部分只有data到view,但是data随着业务变化的逻辑仍然还是要开发人员手动补充的。大部分情况下这样是没什么问题,毕竟业务的变化多种多样,但有一些特殊项目的data变化是模式相对固定的,那么能不能在部分声明式组件之上再封装一层数据结构和接口去约束这样一种变化模式呢?答案是肯定的,这种手段也就是完全声明式编程的概念了。
思路分析
完全声明式,意味着进一步的约束,约束越多,灵活性也就越低,所以最适合的业务应该是需求模式相对固定,视觉要求低的后台数据管理系统。在已经封装好的部分声明式组件之上,再进一步封装工作流,因为后台管理系统的行为可以固化为如下几步:
- 从特定API获取数据
- 展示数据,并提供交互表单
- 用户完成交互
- 验证新数据提交特定API
- 更新数据重渲染
在这些固化流程的交互上,完全可以通过枚举的形式表达,最频繁的无非以下4种。
- modal操作
- ajax操作
- 路由跳转
- 组件刷新
那么思路就出来了,选定一种约束形式,根据该约束形式的接口声明渲染出工作流组件并描述出工作流组件的交互形式,当然这套工作流组件也就是基于通用组件的封装了。
优势
简单来说,该方案的优势都是精准的强约束带来的。想想之前的开发方式的问题,大量的重复业务逻辑都是初始数据到写好视图到提交数据到刷新,这其中可能还有数据校验,参数重组,请求响应之类的细节问题,本质上都应该是可以用同一种手段解决的问题,但封装只进行到组件这一层,由此带来的问题就是再上层的,本来可以用同一种解决方案的业务丢掉了约束,结果就是由于开发人员风格的不同,写法就产生的各种各样的差异,进一步的降低了可维护性。简单举个例子,一个input字段的最大长度约束,是通过JS验证解决还是通过HTML的maxlength属性解决呢?哪种都可以,但一定要选定一种。
进一步的,既然有了强约束的保证,就降低了开发者的成本和门槛了,过去可能需要用代码去组合组件来表达业务逻辑,现在一个JSON字段就能表达完全,那么可以预见,只要封装能够覆盖到的业务,都可以让不擅长前端开发的人员使用了,如果再搭配上可视化编辑器或者自定义cli,就可以大幅度减少代码工作量。
实现
核心思想其实不难考虑,无非就是JSON入,组件出。每个字段对应着一个工作流组件,通过最关键的type字段从全局组件池中找到相应组件递归解析并渲染即可。其中要注意的关键点大概有这么几个:
- 以何种维度进行状态管理
- 组件间如何实现联动,比如各种表单字段,其实也就是组件通信的实现机制
- 全局组件池的注册和匹配
小结
本文就到此为止,主要谈了些实现思路,下文就结合百度开源的完全声明式工具amis源码具体分析本文提到的一些点。
-- EOF --