UI 设计代码化:低代码式设计语言 —— Unflow


prtyaa
prtyaa 2023-12-25 13:27:07 67064
分类专栏: 资讯
UI 设计代码化,即将软件的 UI 设计与 UI 交互转换为特定的领域语言,并使用代码的方式来进行管理。它可以直接将需求转换为 UI 原型,让设计人员基于此进行设计;还负责将其转换对应的 UI 代码,方便开发人员进行编写。

在 Uncode IDE 里,设计代码化是由两部分组成:架构设计(代码设计)代码化与 UI 设计代码化,这是一个相当复杂的领域。作为一个在前端领域的专家,我是在去年完成了 UI 设计代码的第一个版本的设计;作为半个架构专家,我则是在最近完成了部分架构设计代码化的工作。

在最近 ,我刚使用 Rust 将去年设计的 UI DSL 重写,于是重新命名为 Unflow。想不到一个更好的名字,于是将它与 Uncode 进行了一个简单的对应。你可以在 GitHub 上看到 Unflow 当前(早期)版本的设计:github.com/inherd/unflo 。

在继续往下阅读之前 ,我要做一个简单的声明:在完成了 Unflow 的设计之后,我一直在等待机会能与一些用户体验设计师合作,以完善整个 DSL。但是呢,一直没有找至一个合适的机会。所以,当前的这个 DSL 并不一定接近真实的设计师体验。

所以呢,如果你对优先这个 DSL 有兴趣,可以一起参与设计。

UI 设计代码化

UI 设计代码化,即将软件的 UI 设计与 UI 交互转换为特定的领域语言,并使用代码的方式来进行管理。它可以直接将需求转换为 UI 原型,让设计人员基于此进行设计;还负责将其转换对应的 UI 代码,方便开发人员进行编写。

为什么需要 UI 设计代码化?

在文章开头里,我们定义了一下:UI 设计代码化。但是呢,为什么我们需要一个这样的代码化工具呢?从整个云研发体系来说,将 UI 设计代码化,我们要做的这么几件事:

  1. 用户交互文档化。即所有的 UI 交互过程,以明确的格式记录下来,并与文档的形式存储。
  2. UI 工具无关。采用标准化的方式描述 UI 设计,让 UI 设计与 UI 设计工具脱离。
  3. 双向反馈。即我们的设计与 UI 原型、代码是相绑定的,当代码与设计不一致时,我们能即时得到反馈 —— 要么修改设计,要么修改代码。
  4. 连接需求与代码的胶水。从某种程度上来说,这个 DSL 还承担着作为需求与代码连接的胶水。即将需求转换为设计的描述,以便于这个描述转换为代码。

在云研发体系中,它是非常重要的一环。

如何进行 UI 设计代码化?

在今天来看,将 UI 设计进行代码化已经变得相当的简单。只是呢,还有一些因素,会限制我们的代码化能力:

矢量可编程的 UI 设计

UI 工具是整体过程中最令人头痛的问题。对于 UI 设计而言,如果它产出的内容不是矢量图形,那么它会限制我们的转换能力 —— 一个二进制文件不适合在代码库中存储。而,如果一个 UI 工具产生的格式是可直接编程操作的,那么就再好不过了,比如 SVG。但是呢,SVG 缺少一些引用等的相关设计。不过呢,Sketch 也是一个非常不错的工具,它的格式是易于进行编程操作的。

UI 元素可编程

在进行 UI 设计的时候,我们会定义出一套 Design Sytem 或者 UI Guideline,上面充满了丰富的元素,如组件、字体等。对于这些元素来说,它应该是可以由代码生成,或者直接转换为设计 DSL。以用于核验代码中的元素是否真的与设计匹配

对于交互的抽象

对于交互的抽象是一个烦人的问题,但是呢,在我深入研究与探索之后,我发现这也不是一个复杂的问题。复杂度并不高,只是呢,我们要考虑如何与我们的设计、代码进行关联,形成统一的关系。

UI 设计代码化要素

综上所述,我们在对 UI 进行代码化时,要考虑这么一些要素。

要素 1:代码反馈设计

在云研发体系里,我们将所有一切代码化有两个原因:

  1. 流程代码化,并实现化转换自动化。
  2. 借助反馈进行自动优化。

对于 UI 设计代码化这一步来说,我们要:

  1. 寻找合适的 UI 设计工具及对应的解析库,以将解析 UI 设计,转换为特定的领域语言。
  2. 能解析修改过后的生成代码,将代码实现与 UI 设计进行对比。
  3. 自动绑定 UI 设计与代码,自动修改、提示不合理的地方。

要素 2:支持增量变更

设计与代码是相似的,在开发过程中,会伴随着需求的变化,影响到 UI 设计上的变化。因此,对于 UI 设计产物来说,它们应该:

  1. 可版本化。与代码库同在,能跟踪到设计的历史变化。
  2. 可编码。可以由需求生成设计,由代码反馈到设计。

在有了这两个条件的情况下,我们可以进行增量变更。

要素 3:抽象交互

尽管,我在本文中提出了一套交互相关的 DSL,但是它并不是那么完善。除此呢,在不同的公司里,人们也会自己的一些特定的 UI 设计模式等。所以呢,我们还需要设计一种抽象来描述系统对于用户的交互。

对于一个交互 DSL 来说,它需要做两件事:

  1. 描述用户交互。
  2. 能与需求进行对应。
  3. 能与代码进行对应。

接下来,让我们看看 Unflow DSL 的设计。

Unflow DSL

基于此呢,我们设计了 Unflow,它具备了如下的三个模式:

  1. 三段式交互设计:SEE-DO-REACT
  2. 拆分设计:原子设计
  3. 布局系统:AutoLayout 与 Flex 布局

除此呢,还有一个非常重要的部分:反馈式设计,我暂时还没有去验证。

模式 1 —— 三段式交互设计:SEE-DO-REACT

在日常的软件开发活动中,我们经常会看到不同的三段式表达:

  • BDD 里的:Given - When - Then
  • UI 设计的:显示 - 行动 - 响应
  • HTTP 请求的:request - handle - response
  • 代码的:输入参数 - 处理 - 输出结果
  • 测试的:Arrange-Act-Assert
  • 前端开发的:展示 - 事件 - 响应

对于 UI 设计来说,也存在类似的元素。我尝试着从一堆论文中寻找经验,初始时我尝试以 BDD 的三段式来总结。直到我看到了 Basecamp 的设计师 Ryan 在『A shorthand for designing UI flows』一文中看到几句话:

  • What the user sees
  • What them do
  • What them see next / what them do next

基于此,添加了一个 React 的选项,即系统要对他们做出什么响应。于是,有了一个简单的 DSL 原型:

flow 登录 {
  SEE 首页
    DO 输入密码
    DO [点击] "登录".Button
        REACT 成功: 展示 "Login Success".Toast with ANIMATE(bounce)
        REACT 失败: 展示 "Login Failure".Dialog
}

这里的 SEE 对应了用户的所见,DO 则是对应于用户所做,而 REACT 则是相应的可能结果。我们可以将它与需求代码化里的 Given-When-Then 进行一一应对。稍有区别的是,这里在 REACT 里进行了合并,方便后续与 UI 代码进行对应:

  1. 调用接口成功的场景下,则显示 Login Success,然后再往下进行操作。
  2. 调用接口失败的场景下,则显示 Login Failure 弹窗(Dialog),然后可以添加其它行为。

上述代码中的首页,可以对应到 UI 设计的场景、原型上,对应的按钮(Button) 则是组件使用上的声明。与此同时,基于上述的一系列关键描述,如 Login Success、Login Failure 还创建了对应的 UI 设计上的场景。

模式 2 —— 元素拆分:原子设计与元素定义

在设计人员与开发人员协作的过程中,Brad Frost 创建了原子设计的概念:原子设计是一个设计方法论,由五种不同的阶段组合,它们协同工作,以创建一个有层次、计划性的方式来界面系统。

于是,在 Unflow 中,我们依然采用了这个理念,与之对应的设计是:

  • 原子 - library。描述基础、库组件的一些要素。
  • 分子级 - component。描述组件
  • 有机体 - component。描述组件
  • 模板 - template。
  • 页面 - page

这里的 library、component、template、page 都是 Unflow 中的定义。Unflow 的 DSL 只是提供定义,如下是一个对于颜色规范的定义:

library Color {
    Primary {
        label = "Primary"
        value = "#E53935"
    }
    Secondary {
        label = "Blue"
        value = "#1E88E5"
    }
    Third {
        label = "Third"
        value = "#000000"
    }
}

Unflow 定义的是这些要素,随后结合其它工具进行转换。在早期 ,我们结合 Node.js 里的 Sketch Constructor 进行了转换,它将转变为两部分:Sketch 里的颜色规范定义,以及前端代码库里的 SCSS 定义。

这种定义方式,对于 componentpage 也是类似的。

page HomePage {
    LayoutGrid: 12x
    LayoutId: HomePage
    Router: "/home"      # 由开发定义
}

稍有不同的是,我们在设计中加入了一个路由的概念,这个后期可以由开发人员来进行补充。

顺带一说,依旧的这只是 Unflow 的第一个版本,所以在设计上会比较粗糙。

模式 3 —— 布局系统:Flex

起先,如果只是站在早期的布局系统的维度之下,我怕是没有胆量去设计一个 DSL。而随着不同领域对于 Flex 布局的统一化程度:

  • 移动端框架 Flutter 中的线性布局(Row、Column)
  • 原生 UI 框架 Druid 采用的 Flex 布局
  • 前端领域采用的 Flex 布局
  • Android 端的 FlexboxLayout
  • ……

那么,对于我们的布局系统来说,自然采用的是类似于 Flex 布局。如此一来,我们只需要考虑一下结合 Apple 的 Auto Layout,就能得到一个勉强可以用的 UI 系统。

而,我最早对于 Layout 体系的想法,语法来源是 autolayout.js。一个在前端实现了 AutoLayout 和 Visual Format Language 的布局系统,它的语法如下:

H:|[view1(==view2)]-10-[view2]|
V:|[view1,view2]|

虽是如此,我设计的第一个版本的布局系统有点不那么实用。关于这一点,我还在自我反思 ,为什么会设计出这么难写的语法:

Layout Navigation {
--------------------------------------
| "home" |"detail" | Button("Login") |
--------------------------------------
}

在设计布局的时候,想的是:

  1. 以 Flex 作为实现方式
  2. 以 Table 作为展示形式,方便开发人员维护
  3. 支持组件上的参数传递

在这种限制的交错之下,就有了现在这种奇怪的设计

网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。

本文链接:https://www.xckfsq.com/news/show.html?id=30263
赞同 0
评论 0 条
prtyaaL0
粉丝 1 发表 2554 + 关注 私信
上周热门
银河麒麟添加网络打印机时,出现“client-error-not-possible”错误提示  1448
银河麒麟打印带有图像的文档时出错  1365
银河麒麟添加打印机时,出现“server-error-internal-error”  1151
统信桌面专业版【如何查询系统安装时间】  1073
统信操作系统各版本介绍  1070
统信桌面专业版【全盘安装UOS系统】介绍  1028
麒麟系统也能完整体验微信啦!  984
统信【启动盘制作工具】使用介绍  627
统信桌面专业版【一个U盘做多个系统启动盘】的方法  575
信刻全自动档案蓝光光盘检测一体机  484
本周热议
我的信创开放社区兼职赚钱历程 40
今天你签到了吗? 27
信创开放社区邀请他人注册的具体步骤如下 15
如何玩转信创开放社区—从小白进阶到专家 15
方德桌面操作系统 14
我有15积分有什么用? 13
用抖音玩法闯信创开放社区——用平台宣传企业产品服务 13
如何让你先人一步获得悬赏问题信息?(创作者必看) 12
2024中国信创产业发展大会暨中国信息科技创新与应用博览会 9
中央国家机关政府采购中心:应当将CPU、操作系统符合安全可靠测评要求纳入采购需求 8

添加我为好友,拉您入交流群!

请使用微信扫一扫!