對象結構,自動化metadata掃描后众,自動化api和界面生成胀糜,一起都很美好颅拦。經過一番研究后個人覺得不適合企業(yè)應用開發(fā)。
簡化前端開發(fā)流程教藻,同時控制開發(fā)成本距帅,提高靈活性,連接多種客戶端怖竭,對接第三方系統(tǒng)锥债。反反復復琢磨了快15年了吧陡蝇,這是一點也不夸張痊臭。傳輸格式從xml,到xaml, 到json, 到二進制的壓縮格式登夫。自己定義的rpc, 到jsonrpc, grpc, rest广匙。自描述的樹型類型系統(tǒng),自描述的rpc簽名恼策,類似swagger的交互式文檔系統(tǒng)鸦致。但現(xiàn)在openapi, json-ld,graphQL涣楷》滞伲客戶端生態(tài),closure-tools, GWT, pajamas, reactjs, vue, angular狮斗,都折磨了很久绽乔。是的,我沒有學過DCOM, WebService碳褒,EJB, 我覺得這些方案不實用折砸,個人偏見。
今天我說這樣的結論:這種方式不適合企業(yè)應用開發(fā)沙峻。
對象模型是原罪
這類自動化開發(fā)的基礎是metadata, 而metadata是基于固定結構的對象∧朗冢現(xiàn)實開發(fā)中顯示出的數(shù)據(jù)90%是這種類型的,顯示摔寨,導出去枷,增刪改,過濾條件是复,到可以自動生成 删顶。這是自動開發(fā)最核心的價值。說是在的佑笋,這種思路30年前就有了翼闹,數(shù)據(jù)字典,PB蒋纬,還有一些圍繞dBase, foxBase的工具猎荠。
98%的數(shù)據(jù)坚弱,可以從90%的數(shù)據(jù)中簡單推導而來,比如用表達式領域語言关摇,F(xiàn)P函數(shù)荒叶,從已有的90%的數(shù)據(jù)中,加加減減输虱,或者簡單的查詢得到些楣。有些別扭,但可以接受宪睹。各種框架的支持度上愁茁,和方便程度上有差別。支持度不夠亭病,或者特別麻煩鹅很,會極大的影響開發(fā)。
2%的數(shù)據(jù)罪帖,和對象模型很不契合促煮,是對數(shù)據(jù)的深度加工。這時要套入自動開發(fā)模型就變得非常復雜整袁。為接口實現(xiàn)完整的棧菠齿,從對象結構,到描述坐昙,到削足適履的接口實現(xiàn)绳匀。原先自動的persisit層都要手工完成。
對象reshape民珍,對象鏈接變得復雜
graphq襟士,json-ldl 是解決這類問題的目前最好的答案了。但是復雜和抽象程度嚷量,后臺實現(xiàn)的效率都是難以接受的
龐大的對象結構和不必要的數(shù)據(jù)傳輸
為了開發(fā)方便陋桂,實體對象里堆砌了大量的字段,關聯(lián)的一對一蝶溶,一對多嗜历,多對多的實體,導致了數(shù)據(jù)急劇增長抖所。圖形的對象結構出現(xiàn)都不稀奇梨州,導致獲取完整對象到客戶端在現(xiàn)實中是比可能的。
有四種應對辦法:
- 仔細控制系列化的范圍田轧,用不到的字段不傳輸暴匠,用不到的關聯(lián)實體不傳輸
- 按需加載關聯(lián)的實體對象和數(shù)據(jù)量大的字段(比如圖片和文件)
- 為接口單獨定義類結構,把業(yè)務模型和接口模型斷開
- 用graphql傻粘, 只傳需要的數(shù)據(jù)
第一種方法的問題在于每窖,要仔細平衡方便和性能的關系帮掉。這非常的繁瑣,考慮到不同的接口會用到不同的數(shù)據(jù)窒典,這是不切實際的方案蟆炊。
第二種方案使用透明的代理,在訪問數(shù)據(jù)到需要的數(shù)據(jù)時再加載瀑志,比第一種要好很多涩搓。缺點是有時會觸發(fā)嚴重的性能問題,比如掃描所有屬性的自動化程序劈猪,或者只是檢查一下集合屬性的個數(shù)昧甘;訪問一對多對象里的一對一對象(大量的碎片化請求)。對框架的實現(xiàn)有較高的要求岸霹,比如控制好按需加載的顆粒度疾层,批量化處理碎片化請求(收集碎片化異步請求調用将饺,批量化發(fā)給服務器)贡避,或者使用http2(對服務器配置,反向代理等有一定的要求)
第三種方法予弧,為接口定義類結構刮吧,接口上比較干凈,接口之間比較獨立掖蛤,維護起來比較沒有相互牽扯杀捻,分給多人工作也不相互影響,性能也可以精確控制蚓庭。就有一點:開發(fā)太麻煩了致讥。接口模型和實體模型的映射關系,metadata器赞,都要手寫垢袱,而且很繁瑣。另一方面港柜,相似接口的存在很頭疼请契,復制代碼還是不復制代碼,測試還是不測試都是糾結的問題夏醉。如果語言支持 mixin, 比如golang, 或者各種腳本語言爽锥,可以在mixin層次得到復用,一定程度上解決了這個問題畔柔,但因復用mixin引發(fā)一定的couple問題氯夷。復用mixin需要一定的技巧和心血,其實一般的企業(yè)軟件開發(fā)人員達不到這個水平靶擦。
第四種方法腮考,要求水平太高了擎淤,而且性能問題也不容易解決。另外復雜的數(shù)據(jù)結果秸仙,用graphql也是推導不出來的嘴拢。
對象模型不適應現(xiàn)實需要
OOP是一個迷思,大家認為對象化寂纪,是必須的席吴,有效的方法。其實是不正確的捞蛋。在現(xiàn)實中需要的不是對象模型孝冒,而是視圖模型。
每個人看到的不是椅子拟杉,而是椅子的某個視圖庄涡,不同的投影方法,得到的椅子不同搬设。
產品從廠家到使用者之間穴店,總是要通過不同的渠道。使用者不關心產品的模型和生產過程拿穴,關心的是和他接口的渠道泣洞。
椅子的實體模型固然重要,但更有用的是面向不同場景的不同視圖默色。不分場景一股腦的使用實體模型球凰,必然導致代碼復雜,繁瑣腿宰,效率底下呕诉,用戶使用起來也麻煩。
割裂客戶端和服務器端開發(fā)成本過高
同步開銷
需要同步對象結構吃度,當然我們可以通過工具甩挫,提前或者實時同步。但問題在于同步工具會變成瓶頸规肴,好用的同步工具很少捶闸,開發(fā)環(huán)節(jié)的自動化工具也需要開發(fā)和配置。如果同步工具是現(xiàn)有的拖刃,有可能缺乏需要的功能删壮;如果是自己開發(fā)的,開發(fā)成本很高
另外兑牡,不能不考慮模型的量級央碟,成百上千的實體模型,他們的metadata是很龐大的,都預先同步到客戶端也是很大的開銷亿虽,如果動態(tài)加載菱涤,策略也比較復雜。
前后端割裂開銷
如果不能獨棧開發(fā)洛勉,前后端分兩個人粘秆,前后扯皮會比較嚴重,損失效率
前后端語言不統(tǒng)一
使用nodejs沒有這個問題收毫,但是nodejs相比java,php,csharp,這些生態(tài)不成熟攻走。
使用傳統(tǒng)語言的后端,要么對于開發(fā)人員要求很高此再,要么割裂前后端昔搂。另外前后端可能存在重復的邏輯代碼和對象模型
從技術角度來說,這些都不是問題输拇。但和有著大量用戶的消費軟件不同摘符,企業(yè)用戶量少,訪問頻度低策吠,業(yè)務邏輯復雜逛裤,變動快,實體對象多奴曙,功能多(菜單有上百項再正常不過了)别凹。每個功能上的開發(fā)費用非常有限。使用上些許不便洽糟,卡住半秒一秒,是可以接受的堕战。割裂前端后端造成的成本開銷是沒有必要的坤溃。企業(yè)開發(fā)只能選用成熟的技術框架,至少現(xiàn)在我覺得還不夠成熟嘱丢。
基礎的CRUD薪介,傳統(tǒng)方法(比如MVC)處理起來也很簡單,復雜的依然復雜越驻。完成有價值工作的不是框架汁政,是我們自己。在headless 模型在成本上只有增加缀旁,沒有降低的情況下记劈,沒有使用的必要。
在需要的場景并巍,比如易用性要求高的銷售目木,實時性要求高的工廠,使用新框架是必要的懊渡,必須的刽射。用戶也愿意拿出更多的資金军拟,因為這兩環(huán)節(jié)的優(yōu)化能幫助銷售,提高生產效率誓禁。而企業(yè)內控懈息,關注的是可靠,一個崗位做重復同樣的工作摹恰,方便與否常常不那么重要漓拾,工作時間更多的是做決策,而不是填單子戒祠,卡住半秒骇两,不會影響工作效率。過于仔細的實現(xiàn)功能是沒有必要的姜盈。