UI 设计代码化,即将软件的 UI 设计与 UI 交互转换为特定的领域语言,并使用代码的方式来进行管理。它可以直接将需求转换为 UI 原型,让设计人员基于此进行设计;还负责将其转换对应的 UI 代码,方便开发人员进行编写。
在 Uncode IDE 里,设计代码化是由两部分组成:架构设计(代码设计)代码化与 UI 设计代码化,这是一个相当复杂的领域。作为一个在前端领域的专家,我是在去年完成了 UI 设计代码的第一个版本的设计;作为半个架构专家,我则是在最近完成了部分架构设计代码化的工作。
在最近 ,我刚使用 Rust 将去年设计的 UI DSL 重写,于是重新命名为 Unflow。想不到一个更好的名字,于是将它与 Uncode 进行了一个简单的对应。你可以在 GitHub 上看到 Unflow 当前(早期)版本的设计:https://github.com/inherd/unflow 。
在继续往下阅读之前 ,我要做一个简单的声明:在完成了 Unflow 的设计之后,我一直在等待机会能与一些用户体验设计师合作,以完善整个 DSL。但是呢,一直没有找至一个合适的机会。所以,当前的这个 DSL 并不一定接近真实的设计师体验。
所以呢,如果你对优先这个 DSL 有兴趣,可以一起参与设计。
UI 设计代码化,即将软件的 UI 设计与 UI 交互转换为特定的领域语言,并使用代码的方式来进行管理。它可以直接将需求转换为 UI 原型,让设计人员基于此进行设计;还负责将其转换对应的 UI 代码,方便开发人员进行编写。
在文章开头里,我们定义了一下:UI 设计代码化。但是呢,为什么我们需要一个这样的代码化工具呢?从整个云研发体系来说,将 UI 设计代码化,我们要做的这么几件事:
在云研发体系中,它是非常重要的一环。
在今天来看,将 UI 设计进行代码化已经变得相当的简单。只是呢,还有一些因素,会限制我们的代码化能力:
矢量可编程的 UI 设计。
UI 工具是整体过程中最令人头痛的问题。对于 UI 设计而言,如果它产出的内容不是矢量图形,那么它会限制我们的转换能力 —— 一个二进制文件不适合在代码库中存储。而,如果一个 UI 工具产生的格式是可直接编程操作的,那么就再好不过了,比如 SVG。但是呢,SVG 缺少一些引用等的相关设计。不过呢,Sketch 也是一个非常不错的工具,它的格式是易于进行编程操作的。
UI 元素可编程。
在进行 UI 设计的时候,我们会定义出一套 Design Sytem 或者 UI Guideline,上面充满了丰富的元素,如组件、字体等。对于这些元素来说,它应该是可以由代码生成,或者直接转换为设计 DSL。以用于核验代码中的元素是否真的与设计匹配。
对于交互的抽象。
对于交互的抽象是一个烦人的问题,但是呢,在我深入研究与探索之后,我发现这也不是一个复杂的问题。复杂度并不高,只是呢,我们要考虑如何与我们的设计、代码进行关联,形成统一的关系。
综上所述,我们在对 UI 进行代码化时,要考虑这么一些要素。
在云研发体系里,我们将所有一切代码化有两个原因:
对于 UI 设计代码化这一步来说,我们要:
设计与代码是相似的,在开发过程中,会伴随着需求的变化,影响到 UI 设计上的变化。因此,对于 UI 设计产物来说,它们应该:
在有了这两个条件的情况下,我们可以进行增量变更。
尽管,我在本文中提出了一套交互相关的 DSL,但是它并不是那么完善。除此呢,在不同的公司里,人们也会自己的一些特定的 UI 设计模式等。所以呢,我们还需要设计一种抽象来描述系统对于用户的交互。
对于一个交互 DSL 来说,它需要做两件事:
接下来,让我们看看 Unflow DSL 的设计。
基于此呢,我们设计了 Unflow,它具备了如下的三个模式:
除此呢,还有一个非常重要的部分:反馈式设计,我暂时还没有去验证。
在日常的软件开发活动中,我们经常会看到不同的三段式表达:
对于 UI 设计来说,也存在类似的元素。我尝试着从一堆论文中寻找经验,初始时我尝试以 BDD 的三段式来总结。直到我看到了 Basecamp 的设计师 Ryan 在『A shorthand for designing UI flows』一文中看到几句话:
基于此,添加了一个 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 代码进行对应:
上述代码中的首页,可以对应到 UI 设计的场景、原型上,对应的按钮(Button) 则是组件使用上的声明。与此同时,基于上述的一系列关键描述,如 Login Success、Login Failure 还创建了对应的 UI 设计上的场景。
在设计人员与开发人员协作的过程中,Brad Frost 创建了原子设计的概念:原子设计是一个设计方法论,由五种不同的阶段组合,它们协同工作,以创建一个有层次、计划性的方式来界面系统。
于是,在 Unflow 中,我们依然采用了这个理念,与之对应的设计是:
这里的 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 定义。
这种定义方式,对于 component
、page
也是类似的。
page HomePage {
LayoutGrid: 12x
LayoutId: HomePage
Router: "/home" # 由开发定义
}
稍有不同的是,我们在设计中加入了一个路由的概念,这个后期可以由开发人员来进行补充。
顺带一说,依旧的这只是 Unflow 的第一个版本,所以在设计上会比较粗糙。
起先,如果只是站在早期的布局系统的维度之下,我怕是没有胆量去设计一个 DSL。而随着不同领域对于 Flex 布局的统一化程度:
那么,对于我们的布局系统来说,自然采用的是类似于 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") |
--------------------------------------
}
在设计布局的时候,想的是:
在这种限制的交错之下,就有了现在这种奇怪的设计
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
添加我为好友,拉您入交流群!
请使用微信扫一扫!