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