UI 設(shè)計代碼化:低代碼式設(shè)計語言——Unflow(ui設(shè)計代碼簡單嗎)
UI 設(shè)計代碼化:低代碼式設(shè)計語言——Unflow(ui設(shè)計代碼簡單嗎)
UI 設(shè)計代碼化,即將軟件的 UI 設(shè)計與 UI 交互轉(zhuǎn)換為特定的領(lǐng)域語言,并使用代碼的方式來進行管理。它可以直接將需求轉(zhuǎn)換為 UI 原型,讓設(shè)計人員基于此進行設(shè)計;還負責將其轉(zhuǎn)換對應(yīng)的 UI 代碼,方便開發(fā)人員進行編寫。
在 Uncode IDE 里,設(shè)計代碼化是由兩部分組成:架構(gòu)設(shè)計(代碼設(shè)計)代碼化與 UI 設(shè)計代碼化,這是一個相當復(fù)雜的領(lǐng)域。作為一個在前端領(lǐng)域的專家,我是在去年完成了 UI 設(shè)計代碼的第一個版本的設(shè)計;作為半個架構(gòu)專家,我則是在最近完成了部分架構(gòu)設(shè)計代碼化的工作。
在最近 ,我剛使用 Rust 將去年設(shè)計的 UI DSL 重寫,于是重新命名為 Unflow。想不到一個更好的名字,于是將它與 Uncode 進行了一個簡單的對應(yīng)。你可以在 GitHub 上看到 Unflow 當前(早期)版本的設(shè)計:https://github.com/inherd/unflow 。
在繼續(xù)往下閱讀之前 ,我要做一個簡單的聲明:在完成了 Unflow 的設(shè)計之后,我一直在等待機會能與一些用戶體驗設(shè)計師合作,以完善整個 DSL。但是呢,一直沒有找至一個合適的機會。所以,當前的這個 DSL 并不一定接近真實的設(shè)計師體驗。
所以呢,如果你對優(yōu)先這個 DSL 有興趣,可以一起參與設(shè)計。
UI 設(shè)計代碼化
UI 設(shè)計代碼化,即將軟件的 UI 設(shè)計與 UI 交互轉(zhuǎn)換為特定的領(lǐng)域語言,并使用代碼的方式來進行管理。它可以直接將需求轉(zhuǎn)換為 UI 原型,讓設(shè)計人員基于此進行設(shè)計;還負責將其轉(zhuǎn)換對應(yīng)的 UI 代碼,方便開發(fā)人員進行編寫。
為什么需要 UI 設(shè)計代碼化?
在文章開頭里,我們定義了一下:UI 設(shè)計代碼化。但是呢,為什么我們需要一個這樣的代碼化工具呢?從整個云研發(fā)體系來說,將 UI 設(shè)計代碼化,我們要做的這么幾件事:
-
用戶交互文檔化。即所有的 UI 交互過程,以明確的格式記錄下來,并與文檔的形式存儲。
UI 工具無關(guān)。采用標準化的方式描述 UI 設(shè)計,讓 UI 設(shè)計與 UI 設(shè)計工具脫離。
雙向反饋。即我們的設(shè)計與 UI 原型、代碼是相綁定的,當代碼與設(shè)計不一致時,我們能即時得到反饋 —— 要么修改設(shè)計,要么修改代碼。
連接需求與代碼的膠水。從某種程度上來說,這個 DSL 還承擔著作為需求與代碼連接的膠水。即將需求轉(zhuǎn)換為設(shè)計的描述,以便于這個描述轉(zhuǎn)換為代碼。
在云研發(fā)體系中,它是非常重要的一環(huán)。
如何進行 UI 設(shè)計代碼化?
在今天來看,將 UI 設(shè)計進行代碼化已經(jīng)變得相當?shù)暮唵?。只是呢,還有一些因素,會限制我們的代碼化能力:
矢量可編程的 UI 設(shè)計。
UI 工具是整體過程中最令人頭痛的問題。對于 UI 設(shè)計而言,如果它產(chǎn)出的內(nèi)容不是矢量圖形,那么它會限制我們的轉(zhuǎn)換能力 —— 一個二進制文件不適合在代碼庫中存儲。而,如果一個 UI 工具產(chǎn)生的格式是可直接編程操作的,那么就再好不過了,比如 SVG。但是呢,SVG 缺少一些引用等的相關(guān)設(shè)計。不過呢,Sketch 也是一個非常不錯的工具,它的格式是易于進行編程操作的。
UI 元素可編程。
在進行 UI 設(shè)計的時候,我們會定義出一套 Design Sytem 或者 UI Guideline,上面充滿了豐富的元素,如組件、字體等。對于這些元素來說,它應(yīng)該是可以由代碼生成,或者直接轉(zhuǎn)換為設(shè)計 DSL。以用于核驗代碼中的元素是否真的與設(shè)計匹配。
對于交互的抽象。
對于交互的抽象是一個煩人的問題,但是呢,在我深入研究與探索之后,我發(fā)現(xiàn)這也不是一個復(fù)雜的問題。復(fù)雜度并不高,只是呢,我們要考慮如何與我們的設(shè)計、代碼進行關(guān)聯(lián),形成統(tǒng)一的關(guān)系。
UI 設(shè)計代碼化要素
綜上所述,我們在對 UI 進行代碼化時,要考慮這么一些要素。
要素 1:代碼反饋設(shè)計
在云研發(fā)體系里,我們將所有一切代碼化有兩個原因:
-
流程代碼化,并實現(xiàn)化轉(zhuǎn)換自動化。
借助反饋進行自動優(yōu)化。
對于 UI 設(shè)計代碼化這一步來說,我們要:
-
尋找合適的 UI 設(shè)計工具及對應(yīng)的解析庫,以將解析 UI 設(shè)計,轉(zhuǎn)換為特定的領(lǐng)域語言。
能解析修改過后的生成代碼,將代碼實現(xiàn)與 UI 設(shè)計進行對比。
自動綁定 UI 設(shè)計與代碼,自動修改、提示不合理的地方。
要素 2:支持增量變更
設(shè)計與代碼是相似的,在開發(fā)過程中,會伴隨著需求的變化,影響到 UI 設(shè)計上的變化。因此,對于 UI 設(shè)計產(chǎn)物來說,它們應(yīng)該:
-
可版本化。與代碼庫同在,能跟蹤到設(shè)計的歷史變化。
可編碼??梢杂尚枨笊稍O(shè)計,由代碼反饋到設(shè)計。
在有了這兩個條件的情況下,我們可以進行增量變更。
要素 3:抽象交互
盡管,我在本文中提出了一套交互相關(guān)的 DSL,但是它并不是那么完善。除此呢,在不同的公司里,人們也會自己的一些特定的 UI 設(shè)計模式等。所以呢,我們還需要設(shè)計一種抽象來描述系統(tǒng)對于用戶的交互。
對于一個交互 DSL 來說,它需要做兩件事:
-
描述用戶交互。
能與需求進行對應(yīng)。
能與代碼進行對應(yīng)。
接下來,讓我們看看 Unflow DSL 的設(shè)計。
Unflow DSL
基于此呢,我們設(shè)計了 Unflow,它具備了如下的三個模式:
-
三段式交互設(shè)計:SEE-DO-React
拆分設(shè)計:原子設(shè)計
布局系統(tǒng):AutoLayout 與 Flex 布局
除此呢,還有一個非常重要的部分:反饋式設(shè)計,我暫時還沒有去驗證。
模式 1 —— 三段式交互設(shè)計:SEE-DO-REACT
在日常的軟件開發(fā)活動中,我們經(jīng)常會看到不同的三段式表達:
-
BDD 里的:Given – When – Then
UI 設(shè)計的:顯示 – 行動 – 響應(yīng)
HTTP 請求的:request – handle – response
代碼的:輸入?yún)?shù) – 處理 – 輸出結(jié)果
測試的:Arrange-Act-Assert
前端開發(fā)的:展示 – 事件 – 響應(yīng)
對于 UI 設(shè)計來說,也存在類似的元素。我嘗試著從一堆論文中尋找經(jīng)驗,初始時我嘗試以 BDD 的三段式來總結(jié)。直到我看到了 Basecamp 的設(shè)計師 Ryan 在『A shorthand for designing UI flows』一文中看到幾句話:
-
What the user sees
What them do
What them see next / what them do next
基于此,添加了一個 REACT 的選項,即系統(tǒng)要對他們做出什么響應(yīng)。于是,有了一個簡單的 DSL 原型:
-
flow 登錄 {
SEE 首頁
DO 輸入密碼
DO [點擊] \"登錄\".Button
REACT 成功: 展示 \"Login Success\".ToastwithANIMATE(bounce)
REACT 失敗: 展示 \"Login Failure\".Dialog
}
這里的 SEE 對應(yīng)了用戶的所見,DO 則是對應(yīng)于用戶所做,而 REACT 則是相應(yīng)的可能結(jié)果。我們可以將它與需求代碼化里的 Given-When-Then 進行一一應(yīng)對。稍有區(qū)別的是,這里在 REACT 里進行了合并,方便后續(xù)與 UI 代碼進行對應(yīng):
-
調(diào)用接口成功的場景下,則顯示 Login Success,然后再往下進行操作。
調(diào)用接口失敗的場景下,則顯示 Login Failure 彈窗(Dialog),然后可以添加其它行為。
上述代碼中的首頁,可以對應(yīng)到 UI 設(shè)計的場景、原型上,對應(yīng)的按鈕(Button) 則是組件使用上的聲明。與此同時,基于上述的一系列關(guān)鍵描述,如 Login Success、Login Failure 還創(chuàng)建了對應(yīng)的 UI 設(shè)計上的場景。
模式 2 —— 元素拆分:原子設(shè)計與元素定義
在設(shè)計人員與開發(fā)人員協(xié)作的過程中,Brad Frost 創(chuàng)建了原子設(shè)計的概念:原子設(shè)計是一個設(shè)計方法論,由五種不同的階段組合,它們協(xié)同工作,以創(chuàng)建一個有層次、計劃性的方式來界面系統(tǒng)。
于是,在 Unflow 中,我們依然采用了這個理念,與之對應(yīng)的設(shè)計是:
-
原子 – library。描述基礎(chǔ)、庫組件的一些要素。
分子級 – component。描述組件
有機體 – component。描述組件
模板 – template。
頁面 – page
這里的 library、component、template、page 都是 Unflow 中的定義。Unflow 的 DSL 只是提供定義,如下是一個對于顏色規(guī)范的定義:
-
library Color{
Primary{
label = \"Primary\"
value = \"#E53935\"
}
Secondary{
label = \"Blue\"
value = \"#1E88E5\"
}
Third{
label = \"Third\"
value = \"#000000\"
}
}
Unflow 定義的是這些要素,隨后結(jié)合其它工具進行轉(zhuǎn)換。在早期 ,我們結(jié)合 Node.js 里的 Sketch Constructor 進行了轉(zhuǎn)換,它將轉(zhuǎn)變?yōu)閮刹糠郑篠ketch 里的顏色規(guī)范定義,以及前端代碼庫里的 SCSS 定義。
這種定義方式,對于 component
、page
也是類似的。
-
page HomePage{
LayoutGrid:12x
LayoutId:HomePage
Router:\"/home\"# 由開發(fā)定義
}
稍有不同的是,我們在設(shè)計中加入了一個路由的概念,這個后期可以由開發(fā)人員來進行補充。
順帶一說,依舊的這只是 Unflow 的第一個版本,所以在設(shè)計上會比較粗糙。
模式 3 —— 布局系統(tǒng):Flex
起先,如果只是站在早期的布局系統(tǒng)的維度之下,我怕是沒有膽量去設(shè)計一個 DSL。而隨著不同領(lǐng)域?qū)τ?Flex 布局的統(tǒng)一化程度:
-
移動端框架 Flutter 中的線性布局(Row、Column)
原生 UI 框架 Druid 采用的 Flex 布局
前端領(lǐng)域采用的 Flex 布局
Android 端的 FlexboxLayout
……
那么,對于我們的布局系統(tǒng)來說,自然采用的是類似于 Flex 布局。如此一來,我們只需要考慮一下結(jié)合 Apple 的 Auto Layout,就能得到一個勉強可以用的 UI 系統(tǒng)。
而,我最早對于 Layout 體系的想法,語法來源是 autolayout.js。一個在前端實現(xiàn)了 AutoLayout 和 Visual Format Language 的布局系統(tǒng),它的語法如下:
-
H:|[view1(==view2)]-10-[view2]|
V:|[view1,view2]|
雖是如此,我設(shè)計的第一個版本的布局系統(tǒng)有點不那么實用。關(guān)于這一點,我還在自我反思 ,為什么會設(shè)計出這么難寫的語法:
-
LayoutNavigation{
--------------------------------------
| \"home\"|\"detail\"|Button(\"Login\") |
--------------------------------------
}
在設(shè)計布局的時候,想的是:
-
以 Flex 作為實現(xiàn)方式
以 Table 作為展示形式,方便開發(fā)人員維護
支持組件上的參數(shù)傳遞
在這種限制的交錯之下,就有了現(xiàn)在這種奇怪的設(shè)計。
其它
Unflow 正在設(shè)計中,歡迎為 Unflow 提出您的意見:https://github.com/inherd/unflow
參考資料:
-
A shorthand for designing UI flows
https://github.com/inherd/unflow
https://github.com/IjzerenHein/autolayout.js
https://github.com/dorostanian/sushi
Understanding Auto Layout