低代码调研与思考

2022-12-05 10:29:29 浏览数 (1)

简介

低代码平台:是通过少量代码或无需编码就可以快速生成应用程序的开发平台。通过可视化进行应用程序开发的方法,使开发人员可以通过图形化的用户界面,使用拖拽组件和模型驱动的逻辑来创建网页和移动应用程序。

  • 1980年后:快速应用开发工具
  • 2000年后:可视化编程语言
  • 2014年后:Forrester低码概念的引入
  • 2021年后:数字化建设&疫情大环境的推动

竞品分析

开源平台:

  • 腾讯开源:tmagic-editor(star 2.9K) 编辑器:https://tencent.github.io/tmagic-editor/playground/index.html#/ 文档:https://tencent.github.io/tmagic-editor/docs
  • 阿里开源(宜搭):lowcode-engine(star 8K) 编辑器:https://lowcode-engine.cn/demo/index.html 文档:https://lowcode-engine.cn/
  • 百度开源(爱速搭):amis(star 12.1K) 前端编辑器:https://aisuda.github.io/amis-editor-demo/#/edit/0 文档:https://baidu.gitee.io/aisuda-docs 前端文档:https://aisuda.bce.baidu.com/amis/zh-CN/docs/index

设计思想

低代码开发平台在设计思想上主要可以分为表单驱动模型驱动两种。

  • 表单驱动将页面的表单和数据的存储结构合二为一,而模型驱动则与纯代码开发思想接近,实现了数据与表现的完全分离。
  • 表单驱动的典型代表:Airtable、阿里宜搭、字节飞书多维表格、轻流、明道云等。
  • 模型驱动的典型代表:Mendix、OutSystems、腾讯微搭、阿里Mobi、百度爱速搭、华为AppCube、网易轻舟、金蝶苍穹云、蓝卓SupOS、数睿数据等。

思考:基于元数据驱动的低代码方案?(数据驱动与模型驱动结合下的数模驱动方案?)

模块构成

我理解的低码平台构成模块分为:

低码平台可以简单分为:超管、管理端、用户端(小程序、H5、PC Web 、iOS、Android应用)

  • 数据建模 元数据、字段级、对象级
  • 业务建模 前端组件,拖拽,基于元数据模型驱动开发的思想,提供灵活、稳定的元数据模型建模与管理,通过数据实体、属性、关系等元数据配置响应业务需求变化,提供了在线的数据库实体建模和E-R建模功能,支持单表、一对一、一对多关系。
  • 规则引擎 交互行为、事件规则、公式
  • 流程引擎 工作流、审批流,数据触发、流程编排 审批流:可视化拖拉拽流程设计;会签、加签、跳转、退回、撤销等多种流程操作,配置即用;用户、部门、角色、岗位、 关系等多种选人方式,符合中国特色组织选人需求。
  • 报表建模 数据工厂,BI报表、固定报表、自定义报表 报表设计器是一款在线可视化报表建模工具,提供了汇总表、明细表、柱形图、条形图、饼图、折线图、面积图、雷达图、指标图等多种种常用图表,可以组合及联动使用。设计器采用拖拽操作的风格,简单易用,能够实时展示配置效果,一目了然。
  • 权限管理 数据权限、页面权限、业务权限、人员权限、管理权限
  • 页面管理 模版、页面路由
  • 代码管理 JavaScript、代码生成、代码调试
  • 应用管理 小程序管理部署发布、版本管理
  • 平台管理 API集成、云开发、微服务、容器化、私有化、公有化

实现方案

前端方案

声明式编程 vs 命令式编程

如果想绘制一个红色区块,用「声明式」来实现,可以使用 HTML CSS,类似下面的方法:

  • 声明式编程 声明式UI:AndroidJetpack ComposeIOSSwiftUi、跨端的Flutter、Web的Vue/React、Web图表类的Echart、嵌入式的Qt QML
代码语言:javascript复制
<div style="background:red; height:50px">div>
代码语言:javascript复制
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
const rectangle = new Path2D();
rectangle.rect(0, 0, 100, 100);
ctx.fill(rectangle);

虽然最终展现效果是一样的,但这两种代码在实现思路上有本质区别:

  • 「声明式」直接描述最终效果,不关心如何实现。
  • 「命令式」关注如何实现,明确怎么一步步达到这个效果。

从可视化编辑器的角度看,它们的最大区别是:

  • 「声明式」可以直接从展现结果反向推导回源码
  • 「命令式」无法做到反向推导

反向推导是编辑器必备功能,比如编辑器里的常见操作是点选这个红色区块,然后修改它的颜色,在这两种代码中如何实现?

如果是「声明式」的 HTML CSS,可以直接改 stylebackground 值,而基于 Canvas 的命令式代码则无法实现这个功能,因为无法从展现找到实现它的代码,命令式代码实现同样效果的可能路径是无数的,除了前面的示例,下面这段代码也可以实现一样的效果:

代码语言:javascript复制
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(50, 0);
ctx.strokeStyle = '#ff0000';
ctx.lineWidth = 100;
ctx.stroke(); 

甚至有可能这个颜色是多个字符串加随机数拼接而成,即便通过静态分析也找不到来源,从而无法实现可视化修改。

「命令式」代码无法实现可视化编辑,而可视化编辑是低代码唯一不可少的功能,所以我们可以得到结论:所有低代码平台必然只能采用「声明式」代码,这也是为什么所有低代码平台都会有内置的「DSL」

DSL 即「Domain Specific Language」,中文一般译为「领域特定语言」,在《领域特定语言》这本书中它有了一个定义:

一种为特定领域设计的,具有受限表达性编程语言

界面渲染

核心原理是将 JSON 转成自研的 React/Vue 组件库,然后使用 React/Vue 进行渲染。

比如下面的JSON

代码语言:javascript复制
{
  "type": "page",
  "title": "页面标题",
  "subTitle": "副标题",
  "body": {
    "type": "form",
    "title": "用户登录",
    "body": [
      {
        "type": "input-text",
        "name": "username",
        "label": "用户名"
      }
    ]
  }
}

低代码原理就是转成了下面这样的 React/Vue 组件树,最终由各个 React/Vue 组件库渲染 HTML:

代码语言:javascript复制
<Page title="页面标题" subTitle="副标题">
  <Form title="用户登录">
    <InputText name="username" label="用户名" />
  Form>
Page>
交互逻辑的实现

交互及逻辑处理很难,目前常见有三种方案

  1. 图形化编程
  2. 固化交互行为
  3. 使用 JavaScript
  • 图形化编程 图形化编程局限性很大,本质的原因是「代码无法可视化」。代码的抽象思维难以像积木一样进行拼接,积木拼接这种方式只适合用来实现简单的逻辑,比如 scratch。
  • 固化交互行为 常用的交互行为固化并做成了配置,比如弹框的配置:
代码语言:javascript复制
{
  "label": "弹框",
  "type": "button",
  "actionType": "dialog",
  "dialog": {
    "title": "弹框",
    "body": "这是个简单的弹框。"
  }
}

请求成功后,显示反馈弹框

代码语言:javascript复制
{
  "type": "page",
  "body": {
    "type": "button",
    "label": "ajax 反馈弹框",
    "actionType": "ajax",
    "api": "/api/mock2/form/saveForm",
    "feedback": {
      "title": "操作成功",
      "body": "${id} 已操作成功"
    }
  }
  • 但这个方案最大的缺点是灵活性受限,只能使用 自身开发的低码平台 内置的行为。
  • 使用 JavaScript
  • 要实现更灵活的控制,还是得支持JavaScript 其他语言工具中,比较常见的代表C Builder / Xcode,本质其实是一样的
代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19162" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
    <dependencies>
        <deployment identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19162"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner"/>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
        <customView id="c22-O7-iKe">
            <rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
            <subviews>
                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="EWk-sd-qTp">
                    <rect key="frame" x="156" y="177" width="75" height="32"/>
                    <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
                    <buttonCell key="cell" type="push" title="Button" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="QXz-cE-Nde">
                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
                        <font key="font" metaFont="system"/>
                    buttonCell>
                button>
            subviews>
            <point key="canvasLocation" x="139" y="154"/>
        customView>
    objects>
document>

后端方案

如何实现自定义数据存储? 如何实现业务逻辑? 如何实现流程流转?

0 人点赞