低代碼平臺發展漫談
當前位置:點晴教程→知識管理交流
→『 技術文檔交流 』
接受過初中政治課教育的我們都知道,目前軟件行業的主要矛盾是「人民群眾日益增長的軟件產品的需求同落后的軟件生產力之間的矛盾」。來自 mongodb 的一篇博客指出: According to the International Data Corporation, there will be 750 million new applications built by 2025. That means there will be more applications built over the next few years than were built in the software industry’s first 40 years. 來源:https://www.mongodb.com/blog/post/three-factors-limiting-developers-innovation 可見,以目前兩千多萬正經程序員的體量,和目前落后的生產力的現狀,要開發和維護七億多新的應用程序,無異于天方夜譚。 來源:https://www.inapps.net/how-many-software-developers-are-in-the-world/ 那么,有沒有可能極快地增加開發人員的供給呢?很遺憾,盡管一到三個月的速成班層出不窮,可以大批量制造 CRUD 工程師,但這個增量在巨大的空缺面前依舊是杯水車薪,而且,速成班提供的工程師依舊需要 1-3 年的養成期才能配得上「正經」二字。究其原因,還是軟件開發的門檻太高,開發者花在學習技術,理解代碼,維護現有系統上的時間太多,導致真正用于開發新系統的精力不夠,而不成熟的開發者構建的低質量系統進一步加劇了理解代碼和維護代碼的難度,于是再次拉低了生產力。 鑒于這種現狀,2014 年 Forrester 創造性地提出低代碼/無代碼(LCNC)愿景,旨在能大幅降低軟件開發的學習曲線,讓非技術用戶能夠在短時間以低成本的方式構建應用。這是一種降維打擊的思路:一方面,它可以大大拓寬應用程序開發者的群體,另一方面它希望能大大提升構建應用的效率。換句話說,LCNC 試圖解決我們開篇拋出的矛盾:有沒有可能讓構建和維護應用程序的生產力激增 10-100 倍,從而讓軟件行業的生產力趕得上人民群眾日益增長的需求? 在經歷了虛無縹緲虛頭巴腦的數年探索后,近兩年,LCNC 開始扎實落地,在商業智能,CRM,企業內部系統,工業自動化,機器學習,電子商務,設計工具,Web/移動應用開發,以及工作流自動化等領域四處開花,很多公司實現了付費客戶和收入的大幅上揚,并引起了 FAANG 等大公司的警覺。下圖是 unigram_labs 對 LCNC 生態的一個總結: 你也可以到這個 google sheet:https://docs.google.com/spreadsheets/d/160sFMEpNqjJkPCr4pxRLK_yZVT7mJJRSlRG9HZNdxBQ/edit#gid=0 查閱 LCNC 公司的融資情況和最新消息。 那么,這些低代碼平臺是如何降低軟件開發的學習曲線呢?我個人的感受是以下幾個方面。 可視化工具首先,降低開發門檻的一大利器是提供動動手拖拖拽拽就可以完成主要 UI 界面的可視化工具。對于絕大多數非程序員而言,圖形化編輯界面要比 IDE 或者 CLI 友善得多。 目前 LCNC 陣營提供的可視化工具大多分為兩類:以 webflow 為首的主攻設計師和無軟件開發經驗的產品主要通過提供 website builder 允許開發者精細化控制其頁面展示: 雖然 webflow 復雜的界面編輯工具不是我的菜,但它顯然抓住了包括設計師在內的很多用戶的胃。這家誕生于 2013 年,沒怎么融資,純靠自力更生賺小錢錢養活自己的初代 LCNC 平臺,于2019 年迎來大爆發,收入井噴式增長,并在近三年融了 300M,一騎絕塵。 可視化工具另外一個大方向是以 retool 為首的,為開發公司內部系統的程序員量身定制的極簡 UI builder。它包括常用的控件,允許開發者通過簡單拖拽構建展示上過得去,但可以有豐富邏輯(比如通過 SQL 從數據庫中獲取數據)的頁面: 預置功能,第三方集成和模板可視化工具的背后,是一系列預置的功能和模板。它們大大降低了開發者開發的門檻,使得開發者可以聚焦于實現業務邏輯,而非重新造輪子。以目前風頭正勁的 airtable 為例,它提供大量預置的模板和組件,以及多達上百個與第三方 SAAS 服務的集成: 除了將功能打包成預置的模塊外,還有一個很有意思的方向是將預置功能打包成庫,供開發者通過極其簡單的方式調用,比如 autocode 就在其 stdlib 中集成了很多第三方 SAAS 服務的 API,通過簡單的 javascript 調用暴露給用戶。下圖展示了如何使用它來構建一個 webhook,向 slack 發送消息: autocode 的這一思想我也實踐過。今年年中的時候,我對 deno 比較著迷,試圖通過 Rust 構建一系列 javascript API 提供給 deno,讓用戶的 javascript 代碼可以通過簡單的 API 訪問 KV / document DB(基于 DynamoDB),文件系統(基于 s3),以及一系列 cloud API(比如 github API)。通過這種方式,用戶代碼基本上就是簡單的膠水代碼,而復雜的邏輯都被預置的庫封裝好了。 預置的規則和行為在預置的功能之上,可以進一步為用戶抽象出預置的功能和行為。以 clickUp 為例,當數據發生變化時,你可以從一系列預置的觸發器(trigger)選擇想要的觸發條件,然后再選擇相應的行為(action)。這種預置的規則和行為對工作流處理尤為方便,讓原本需要代碼處理的邏輯轉化成簡單的配置: 在這一點上,retool 提供了極其精細的控制 —— 比如你可以對一個表格的 row selection 事件提供相應的行為: 以上三種主要的手段幫助應用程序開發者減輕了從界面到功能,再到可復用的工作流和事件處理的工作。對于簡單的應用來說,開發效率的確可以得到大幅的提升。更重要的是,開發者要閱讀和維護的代碼量大大減少,從而進一步降低了引用的 TCO。 AI 輔助開發除了上述三種降低門檻的手段外,目前大熱的 AI 輔助開發也許會是 LCNC 的終極解決方案。我自身是 github copilot 的深度用戶 —— 近半年來我個人項目中 70% 以上的單元測試代碼都是 Copilot 幫我完成的, 它大大提高了我開發的效率,使得我在不必花費太多額外時間的前提下,可以為自己開源的諸多項目提供不錯的測試覆蓋率。雖然 Copilot 幫我完成的代碼有時還是有荒謬絕倫的錯誤,但大部分時候,它能夠很好地領會了我的意圖。而最近一個月爆紅的 ChatGPT 更是把 AI 輔助開發的潛力提升到了一個新的高度。所以我覺得,從提升生產率的角度,AI 輔助開發未來在 LCNC 領域會扮演終結者的角色。雖然現在還沒有 LCNC 廠商發布 AI 輔助開發的版本(可能我比較孤陋寡聞),但我相信,前面那張 LCNC 生態圖中的大小公司們,都已經在它們內部迭代的產品中試圖增加 AI 輔助開發:用戶只需通過文字描述其對要開發的產品的想法,AI 可以生成若干個滿足這一想法的產品供用戶選擇,最終用戶僅僅需要微調就可以得到自己心儀的產品。如果這個愿景可以實現,那么這也許就是軟件開發終極的生產力提升的手段!也許,我們有幸在未來的五到十年見證到人人都能開發和維護自己的應用程序的盛況,就像二十年前互聯網走進千家萬戶,讓上網沖浪,獲取信息不再是象牙塔和少部分人的專利那樣。 我對低代碼開發平臺的淺見出于職業習慣,我對不少低代碼平臺都做了一些膚淺的嘗試。它們在各自的細分領域都有不俗的表現,但沒有特別讓我眼前一亮的通用開發平臺。如果我要開發一個 SAAS 服務,一個提供某個特定功能的 Web 應用(比如為開源的 excalidraw 增加 s3 存儲能力),或者一個超出 CRUD 范疇的內部系統,目前的 LCNC 平臺似乎都不能很好地滿足我的需求。 另外,從純程序員用戶的角度,我希望 LCNC 平臺支持其應用可以在生命周期內不斷迭代。畢竟,開發一款軟件產品只是萬里長征走完了第一步,后續的隨需而變,不斷進化才是產品生命力的體現。這就意味著:
遺憾的是,目前還找不到滿足上述需求的 LCNC 平臺。很大程度上,目前的 LCNC 平臺更偏重一些特定場景下的細分市場,而這些細分市場的用戶畫像大多是設計師,產品經理,BI 分析師,或者其它非程序員的角色。autocode 算是面向程序員的,不過它的能力太過有限;而 airplane.dev 是我見過的可能最靠近我需求的產品。它允許你撰寫 yaml 和 SQL 處理大多后端需求,撰寫少量 JSX 和 react 代碼處理前端展示,這一切既可以在可視化工具中拖拽完成,也可以直接撰寫代碼,存入 git repo 中,享受其版本控制,git 工作流,github action 等一系列開發者常用的流程。 如果我來開發一款 LCNC 產品,會是什么樣子的? 首先,我的用戶定位會放在程序員群體。程序員一般需要開發兩類應用:公司的內部系統,以及業務系統。我覺得一開始面向內部系統,解決大部分公司沒有太多資源向內部系統傾斜的難題會是一個不錯的切入點。這里有很好的商業機會和付費模型。事實上,retool,airplane 都是在切這塊蛋糕。 而一家公司的業務系統往往是其收入核心,除非初創公司要快速驗證 product/market fit,否則很難下決心使用目前還不夠成熟的 LCNC 產品。當然,如果某個 LCNC 產品可以切下中小型公司的業務系統的一部分蛋糕,讓中小型公司的業務 GTM 的速度大大提升,那將是一個非常了不起的里程碑。 從產品的形態來看,LCNC 產品自身是 SaaS 服務,因而需要具備 SAAS 服務的一切要素:定價模型,功能或者容量限制,用戶權限,租戶數據的隔離(物理或者邏輯),特定的部署需求,以及向下伸縮的能力。普通應用只需要處理自身的部署問題,而 SAAS 服務往往需要在租戶切換其付費模式時進行特定的部署 —— 比如免費用戶大家共享一個 DynamoDB table,切換到 pro 版本也許就要考慮為其單獨提供 table。而當用戶停止付費或者退出服務時,還需要將相關資源完全回收避免不必要的云服務賬單。這些,都是 SaaS 產品普遍的需求。 除此之外,LCNC 產品還要具備其業務自身所需的基礎功能:可視化工具,預置功能和模板,第三方集成,預置的規則和行為等等。 在這些基礎功能之外,就真正考驗 LCNC 產品自身的能力了。以一個通用的 LCNC 產品為例,我們可以把完整的產品邏輯都裝載 lambda 函數 + DynamoDB 之內,這樣可以充分利用 serverless 的可伸縮性和按需付費的計費模型,最大程度降低產品自身在 infra 上花費的時間。 也許有同學會問,為何不用 kubernetes?它也可以有足夠好的伸縮性。Kubernetes 雖然很好很強大,但其背后需要一支成熟的運維團隊支撐。對于初創的 LCNC 公司來說,使用 Kubernetes 可能還等不到產品找到 product/market fit,開發團隊的開銷就把自己整嗝屁了。 在我看來,按需使用,按需付費,幾乎無限 scale up,且可以隨時 scale to 0 的serverless 是應用程序的未來。除非有特殊原因或者就是做 devOps 方面的創業,否則任何初創技術團隊都應將產品架構在 serverless 之上。 回到 LCNC 產品的討論。在 lambda runtime 之前,可以考慮按需放 LB 或 API gateway,LB/API gateway 之前掛 CloudFront。目前 lambda function 支持 cloud URL,也許 CloudFront 直接訪問 lambda 的 cloud URL 也是一個不錯的選擇。在 lambda runtime 后方,可以把 S3 封裝成 FS,DynamoDB 封裝成 KV store,再使用 Neon(serverless postgres)這樣的解決方案,或者干脆讓用戶自行提供 RDBMS server(retool 就這么干),就可以為用戶提供豐富的,滿足絕大多數需要的 OLTP 數據訪問方案: 再往后,就是常用的前后端功能的組件化。比如,每個應用可能都會使用的 oauth 登錄,可以封裝好,以簡單的 yaml + jinja2 模板提供給用戶使用: --- name: oauth_login args: provider: {{ params.provider }} csrf_token: {{ params.csrf_token | default('') }} 如果要支持 email / password 登錄呢?用戶可以撰寫下面的代碼來完成整個后端的邏輯:
乍一看,這樣的代碼雖然比自己實現要簡單許多,但還是有一定的學習成本。不過這個學習成本可以通過上文所述的可視化編輯工具來消弭。 后端組件化可做的事情很多,比如各種基礎的構建 app 的常見功能,大到data pipeline,implicit / explicit signals,權限管理,數據查詢,數據搜索等,小到 base64 編解碼,數據加解密,生成和校驗 JWT 這樣的單一函數。我們可以構建出一系列基礎組件作為 stdlib,然后在此之上為各種各樣的功能開發如上的流程模板,最大程度減輕用戶開發的難度。 說完了后端,我們再來看前端的組件化。在 LCNC 生態中,絕大多數公司都花費了很多精力構建其前端組件的組合能力。畢竟,前端是門面,再優秀的后端組件,如果沒有與之匹配的前端展示,也會被用戶棄之如敝履。目前大家青睞的前端組件化的方案主要是 react / vue,還有少量的 svelte。這些方案用在自己的應用中問題不大,但它們是否適合 LCNC 項目呢?以 airplane.dev 為例,它采用了 react。這就勢必要求 airplane 的用戶群體會使用 react,或者至少愿意在 react 上投入精力。要知道,盡管 react 在工程上已經非常穩定,但它的新功能還是層出不窮,兩年前的代碼和現在的代碼寫法有很大的不同(尤其在狀態處理方面)。如果未來 react 跟風要引入 signal 呢?那 airplane 跟還是不跟?用戶跟還是不跟? 此外,使用 react / vue 這樣的前端方案,還意味著后端需要 API 化,而前端需要維護復雜的狀態。對于 LCNC 方案來說,如果最終的代碼用戶毫無感知還好,否則,只會增加用戶維護的心智負擔。 所以我個人覺得 react / vue / svelte / solidjs 等一切前端 JS 庫,也許不是最適合 LCNC 的選擇,對于 LCNC 項目,我們要盡量減少用戶前端代碼的維護成本。那么,什么樣的代碼維護成本比較小呢?在我看來,如果后端組件(如上所示)已經使用了模板來進行復用,前端沒道理拋開模板另開一套方案。所以,也許我們可以讓前端倒退 10 年,走回模板的老路? <tr id="item-{{ data.item.id }}"> {%- for col in data.names -%} {%- if loop.first -%} <td class="py-4 pl-4 pr-3 text-sm font-medium text-gray-900 whitespace-nowrap sm:pl-6"> {{- data.item[col] | humanize(type=data.types[loop.index0]) -}}</td> {%- else -%} <td class="px-3 py-4 text-sm text-gray-500 whitespace-nowrap">{{- data.item[col] | humanize(type=data.types[loop.index0]) -}}</td> {%- endif -%} {%- endfor -%} <td class="relative py-4 pl-3 pr-4 text-sm font-medium text-right whitespace-nowrap sm:pr-6"> <a hx-get="/todos/{{ data.item.id }}?view=edit" class="text-indigo-600 hover:text-indigo-900">{{ config.edit_title }}</a> </td> </tr>如果小伙伴們使用過 Django 或者類似的框架,對這樣的類 jinja2 的 HTML 模板代碼一定不會陌生。它的可讀性和可維護性不錯,基本就是在 HTML 之上添加少量邏輯,由后端渲染出完整的 HTML 在前端展示。 那位問了:這么做,過去 10 年前端無刷新訪問的努力難道白費了么?用戶體驗一下回到解放前? 非也。我們可以使用類似 HTMX 的庫來達到頁面局部更新的目的,就像 phoenix framework 提供的 LiveView 那樣。 使用 HTML + 模板的另一個考量是即便組件化做得很好,react 工程師的門檻還是不低的,而 HTML + jinjia2 模版(其語法自 2008年以來就幾乎沒有變化)的門檻就要低得多。這樣,無論是構建組件本身,還是使用組件,我們都可以使用更為便宜的人才達到更高的生產力,從而降低在研發方面的支出。 最后,我們來簡單聊聊開發 LCNC 系統的語言選擇。 我個人的首選開發語言是 Rust。這里很大一個原因是:只要你選擇 serverless 方案,那么 Rust 就應該是重點考慮的語言(見這個性能測試:https://github.com/Aleksandr-Filichkin/aws-lambda-runtimes-performance)。我自己在 AWS lambda function 中嘗試過 nodejs 和 Rust 做類似的 web 服務,包括冷啟動,Rust(axum)可以輕松在 300-400ms 內完成一個請求,占用內存穩定在 ~30M 左右;而 nodejs(express)大概需要 600-800ms 完成請求,占用內存 > 100M,偶爾會超過 200M。而熱啟動時,Rust 可以達到 40ms 的低延遲: 冷啟動:REPORT RequestId: d070a653-7f10-48b8-a9d1-26e48bf53013 Duration: 219.52 ms Billed Duration: 307 ms Memory Size: 256 MB Max Memory Used: 31 MB Init Duration: 87.08 ms 熱啟動:REPORT RequestId: 4d834f9a-f139-4ef6-829c-09bce5039655 Duration: 40.85 ms Billed Duration: 41 ms Memory Size: 256 MB Max Memory Used: 32 MB (以上請求均訪問 S3 獲取文件,解壓,抽取數據,渲染模板,返回渲染后的 HTML。熱啟動時感覺 lambda 到 S3 的路徑上 AWS 似乎做了文件的緩存,所以速度很快) 在 serverless 的世界里,內存占用和處理速度直接決定了賬單的大小。所以,Java/DotNet 這樣狂吃內存,冷啟動巨慢的語言直接出局,而 Rust 這樣高效低內存占用的語言頓時成了香餑餑。我自己做的簡單的測算,同樣功能的代碼,同樣的預算下,Rust 代碼可以支撐 4-10 倍 nodejs 的請求量。這在未來的 LCNC 產品的白熱化競爭中,可以最大程度地獲取免費用戶且避免導致天量的賬單。 Rust 的另一大好處是可以為用戶代碼提供高效的組件支持。通過 deno 或者 pyo3 這樣的庫,我們可以很方便地把 Rust 構建的組件暴露給 javascript/python 代碼。于是 LCNC 的用戶可以享受到 Rust 的高效,同時又可以使用簡單直觀的代碼來構建自己的應用。 該文章在 2023/11/18 12:01:47 編輯過 |
關鍵字查詢
相關文章
正在查詢... |