構(gòu)建之路—談?wù)劷M件化后端構(gòu)建和實(shí)現(xiàn)

前言

這一篇文章,準(zhǔn)備了很久,構(gòu)思了很久,草稿了很久。從個(gè)人編程至今,歷經(jīng)了C,C++,Java,到現(xiàn)如今的NodeJS。也后端到前端,再回到后端。更從學(xué)校里的學(xué)生信息管理系統(tǒng)到大型商業(yè)系統(tǒng)構(gòu)建,是的,我曾一直以為編程也就是如此了,由瀑布模型,敏捷開發(fā),設(shè)計(jì)模式等等組成的軟件工程大致就是如此了。相信可能很多人也會有和我類似的想法,是否也都曾迷茫過?

幸運(yùn)的是,伴隨著對前端的接觸和深入,云霧散開。前端組件化的蓬勃發(fā)展,讓我思考了很多,仿佛是一夜之間,整個(gè)前端翻天覆地,為什么在軟件工程已經(jīng)逐漸成熟的這么多年后,竟然還會有如此之大的編程風(fēng)格轉(zhuǎn)換呢?

我的答案是,因?yàn)檫€沒有到極限,還沒有到最好,還沒有到最簡單


前端的變革

前端原本并不復(fù)雜,由HTML,CSS,JS三劍客組成的用戶交互,很長時(shí)間占據(jù)統(tǒng)治地位的JQuery,解放同步請求,無阻塞的AJAX,仿佛就是前端的一切。HTML為骨架,CSS為外觀,JS為交互。分工明確,邏輯合理,可為什么現(xiàn)實(shí)項(xiàng)目中代碼還是亂的一塌糊涂呢?為什么還是會有重復(fù)冗余的頁面,為什么還是有重復(fù)冗余的JS方法,為什么每個(gè)頁面都還是會一遍遍地設(shè)置字體大小,顏色樣式,而不是像書本中所崇尚的,只要寫一遍CSS樣式,然后全站應(yīng)用呢?

大概是因?yàn)樽霾坏桨?。對于一個(gè)人,或者兩個(gè)人的項(xiàng)目也許真的可以按照書本中說的實(shí)現(xiàn),但是超過三個(gè)人之后,項(xiàng)目的人力溝通協(xié)作成本會呈現(xiàn)指數(shù)形式的上升,無論多么精良的項(xiàng)目協(xié)作管理,都難免會出現(xiàn)遺漏。


設(shè)計(jì)架構(gòu)的問題,靠人力是無法解決的。

所以,前端變革了,針對軟件工程高內(nèi)聚,低耦合的思想,組件化大潮應(yīng)運(yùn)而生。一夜間,大批的MVVM框架如同雨后春筍,我們興奮且欣喜地看到前端新世界在一點(diǎn)點(diǎn)地重新搭建,原本的大廈被推倒重來。所有嗅覺敏銳的前端精英們,都日夜苦修地貢獻(xiàn)著代碼,成為這個(gè)時(shí)代的構(gòu)建者之一。同樣,國內(nèi)的頂尖開發(fā)者也抓住了這個(gè)機(jī)會,開始在架構(gòu)框架上嶄露頭角,甚至一舉超越了一直在此領(lǐng)域領(lǐng)先的歐美。


這其中最典型的就是Vue,無論是對比Angular還是ReactJS,Vue都毫不遜色。這是我個(gè)人最喜歡的MVVM框架,其優(yōu)美滿足了我?guī)缀跛械幕孟搿>腿缤琕ue風(fēng)格對無分號的堅(jiān)持,長久以來,我也一直很不喜歡重復(fù),冗余,沒有意義的東西。為什么我需要寫一模一樣的代碼,為什么我需要復(fù)制粘貼,為什么業(yè)務(wù)的拓展就一定要犧牲代碼的優(yōu)美?多些了幾層調(diào)用就是靈活?一大堆的配置就是靈活?一堆的if...else...一堆的try...catch...就是嚴(yán)謹(jǐn)?



沒有BUG的程序

世界上唯一沒有BUG的程序是什么?

是HelloWord


任何語言的HelloWorld,都幾乎只有一句話,或者兩三句。那么程序沒有BUG的秘密相信很多人都能看出來了,很簡單,越少代碼就越少BUG,沒有代碼就沒有BUG。

人終究是人,不是AlphaGo,沒有無限的記憶力,無法記憶所有的細(xì)節(jié),當(dāng)細(xì)節(jié)越多,犯錯(cuò)的概率就會越大。

但人有靈性,人有重構(gòu)優(yōu)化的思維。任何事物發(fā)展到了瓶頸,那么就意味只有重構(gòu)才能得到嶄新的道路。


后端的進(jìn)步

于是,帶著這樣的思考,我開始審視我自己這么些年寫的后端,總結(jié)一下:

C語言時(shí)代——文件引入,二進(jìn)制lib庫引入,純手寫的功能函數(shù),小心翼翼地檢查指針,檢查內(nèi)存分配,檢查每一個(gè)循環(huán)中的i變化,檢查每個(gè)數(shù)組的下標(biāo),檢查每一句代碼的每一個(gè)字母

C++時(shí)代——大量的庫出現(xiàn),仍然是以二進(jìn)制居多,不知道是如何實(shí)現(xiàn)的,但是心里面默默感覺,都是專家寫的,肯定沒錯(cuò),用就是了?;旌现鳦和Java,不純粹的面向?qū)ο?,雖然別扭,但是好像沒有C寫起來那么累了,嗯,從原來的每天寫一百行代碼提升到幾百行了!

Java與PHP時(shí)代——哇哦,好像寫代碼更簡單了,不僅僅不用關(guān)心內(nèi)存分配,也沒有指針了,最棒的是語言自身都集成了好多數(shù)據(jù)結(jié)構(gòu),再也不用手寫數(shù)據(jù)結(jié)構(gòu)工具類了,嗯只需要點(diǎn)點(diǎn)點(diǎn)或者箭頭箭頭箭頭就能出來我想要的功能了,這不正是我們一直想要的嗎?嗯,從原來的每天寫幾百行提升到每天可以寫兩千行代碼了!

庫時(shí)代——最典型的是Maven,Grable,等等,終于不用上網(wǎng)一個(gè)個(gè)Jar包下載,然后放到指定文件夾了,把配置文件寫好,一個(gè)命令,全自動下載,依賴全自動解決,好像很酷很快呀。Java這么成熟,什么庫都有,這豈不是可以快速開發(fā)一切了?這個(gè)時(shí)候,不需要每天寫兩千行代碼了,寫兩百行配置,然后寫兩百行代碼就好了,嗯,雖然配置多了點(diǎn),但是相比代碼的減少,值得的!

微服務(wù)時(shí)代——突然發(fā)現(xiàn),即便是有Maven,可以通過配置自動構(gòu)建了,但是大型系統(tǒng)里面,日志,SpringMVC,數(shù)據(jù)庫,分布式,緩存等等東西的存在,哇,好幾十個(gè)配置文件,每個(gè)文件好幾十行,甚至上百行奇怪的配置,太恐怖了,根本看不懂在寫什么,為什么要配置這么多東西,為什么啟動一個(gè)應(yīng)用要這么累,為什么每次發(fā)生產(chǎn)都要等到凌晨兩點(diǎn)?于是,復(fù)雜的SpringMVC謝幕了,SpringBoot登場了!什么,一個(gè)pom.xml配置文件就搞定了所有事情!我們終于可以專心寫Action,Server,Dao,SqlMap了,好不爽快。而且生產(chǎn)發(fā)布好像也變得簡單了一些。

至此,我們已經(jīng)到達(dá)了目前主流且趨勢的后端開發(fā)模式了,然而,到這里就要停止了嗎?似乎,一切都還沒不是那么完美?Java就是最后統(tǒng)治一切的主宰了么?

SpringBoot不是終點(diǎn)

我個(gè)人認(rèn)為不是的,SpringBoot雖然已經(jīng)輕量化很多了,但其本質(zhì)沒有變化,只不過用了更極限的封裝隱藏了更多的細(xì)節(jié),使得其呈現(xiàn)出來的效果驚人。但是這樣極限的封裝會帶來一個(gè)問題,那就是大量的設(shè)計(jì)模式使用和多層隱蔽的封裝使得其原理越來越模糊。如果是直接使用SpringBoot作為初學(xué)的開發(fā)者,還有多少人會去了解其底層的Servlet,還有多少人會明白SpringBoot究竟是怎么實(shí)現(xiàn)這些很靈活很方便的功能,SpringBoot究竟是如何攔截,SpringBoot那些強(qiáng)大的插件和模塊究竟是如何工作的?當(dāng)然,一般這些問題去百度或者去社區(qū)提問,大部分繁忙的大神們會丟下一句話——“自己看源碼去,多看看就懂了”。

個(gè)人認(rèn)為這樣的一句話是很不負(fù)責(zé)任的,如果你愿意教導(dǎo)別人,那就好好回答,如果不愿意教導(dǎo)別人,那就節(jié)省自己的時(shí)間不要回復(fù),為什么要這般回答別人的提問呢,似乎國內(nèi)這個(gè)風(fēng)氣比較嚴(yán)重,在國外的很多社區(qū)問答上幾乎很難看到有這樣的問答,哪怕是再愚蠢的問題,都會有人耐心講解,甚至我還遇到過有人專門錄制了視頻為提問者解答。當(dāng)然,發(fā)達(dá)國家們的worker畢竟都收支理想,空閑時(shí)間多,但是不管怎么樣,我還是覺得動不動讓別人去看源碼學(xué)習(xí)的人,真的還不如不說。

話說遠(yuǎn)了,繼續(xù)說回SpringBoot,正是因?yàn)镾pringBoot的簡易性是以犧牲原理性為代價(jià)的,所以我覺得它還不是最好的解決方案。


世界上最好的語言

這個(gè)時(shí)候,終于要說出一句引戰(zhàn)的話了,就如同當(dāng)年P(guān)HP的梗——

JavaScript是世界上最好的語言!

好吧,我承認(rèn),JavaScript還不是世界上最好的語言,但是我要說的是,JavaScript正在成為世界上最好的語言。從ES5到ES6的巨大轉(zhuǎn)變,再到ES6到ES7的巨大進(jìn)步,我們能看到,ECMAScript標(biāo)準(zhǔn)的制定者們,已經(jīng)是默認(rèn)并且下定決心將其打造成為未來Web構(gòu)建世界的基石的決心。而且從ES7開始,ES不再以數(shù)字分代,而是以年份命名,也就說,ES將會一年一代!這是什么概念,除了Java,還有什么語言是有這樣的更新迭代速度?

可以說,JS正在朝著取代Java的道路上前進(jìn)著。而這一切是因?yàn)槭裁??僅僅是因?yàn)榍岸私M件化的構(gòu)建引發(fā)的嗎?

不,比起前端的組件化,有一個(gè)更值得引人注目的產(chǎn)物,那就是NodeJS。


這已經(jīng)不是我第一次在文章中推崇NodeJS。當(dāng)然,NodeJS早期剛推出的時(shí)候爭議很大,甚至有很多人,甚至是很多大神都發(fā)文表態(tài)“為什么我不用NodeJS”之類。

我不否認(rèn),甚至我自己在文章中也寫過,NodeJS的純異步風(fēng)格和金字塔無限回調(diào)成為了其發(fā)展的瓶頸和阻礙。但是,伴隨著新版7.7的Node支持ES7中的async...await開始,這個(gè)問題似乎開始逐漸被解決了,同步和異步似乎已經(jīng)開始趨向平衡。而且在更未來的ES版本中,可以預(yù)覽到Node似乎更適合面向?qū)ο?,甚至是更簡單,更?qiáng)大了。

好,接著我們說說為什么NodeJS是未來Web后端構(gòu)建的基石

1,NodeJS有著無與倫比部署簡易性,腳本,哪怕SpringBoot再簡單,都絕不如NodeJS部署快和方便。

2,NodeJS大量的異步思維,性能絕佳,未來實(shí)現(xiàn)多線程后,就再也沒有短板。

3,NodeJS與前端JS語言同步,真正意義上的one language,run everywhere


次世代

其次,本文的核心重點(diǎn),后端組件化構(gòu)建,我認(rèn)為是下一個(gè)時(shí)代的趨勢

同前端組件化一樣,后端也可以組件化。不是模塊化,模塊化只是簡單的業(yè)務(wù)分離,也不是層次化,Java將層次化發(fā)展到極致,但是大量的層次會使得系統(tǒng)縱深過大,代碼冗余復(fù)雜,維護(hù)性反而降低。

后端的組件化概念,應(yīng)該是組件聚合了真正完整的業(yè)務(wù)實(shí)現(xiàn)功能,以軟件包的形式分發(fā),然后通過極其簡單的引用,將組件零侵入,零耦合地嵌入原生系統(tǒng)之中。

看到這里,有些朋友們已經(jīng)能感覺到了,這有點(diǎn)像npm的概念,那現(xiàn)在的npm就是組件化嗎?每個(gè)npm的node包就是組件了嗎?

不全是,npm只是包管理工具,這是實(shí)現(xiàn)組件化的很重要的基礎(chǔ),我目前看到的最合適實(shí)現(xiàn)后端組件化構(gòu)建的框架,就是Express和Koa。這兩個(gè)框架的中間件的概念和設(shè)計(jì),讓我嘆為觀止,這是一種全新的后端開發(fā)概念。當(dāng)然,其實(shí)很多人并沒有理解到中間件的應(yīng)用,所以我見過很多把Express和Koa當(dāng)做是SpringMVC和SpringBoot來用的框架。

如果依然是重復(fù)著控制器,業(yè)務(wù)層,持久層,一層層的處理,然后Express僅僅只是做一個(gè)路由,負(fù)責(zé)網(wǎng)絡(luò)請求處理,那中間件的意義又何在?

所以,我對中間件的理解是,中間件是被路由的內(nèi)聚業(yè)務(wù)


好的,解釋一下,就是說是對于Express和Koa,我們的注意力不應(yīng)該還是放在MVC上,也不是放在業(yè)務(wù)層的if...else的邏輯表達(dá)上,也是著眼全局,放在業(yè)務(wù)路由處理上,具體如何理解,看下面的例子:

我們都知道,對于express來說,app.use(path,fn) 就能將指定路徑訪問請求轉(zhuǎn)到指定方法。那么其實(shí)對于應(yīng)用app來說,我們關(guān)心的其實(shí)只有兩個(gè)點(diǎn),第一,業(yè)務(wù)請求,也就是路由;第二,就是業(yè)務(wù)。

到這里,相信很多人都能理解了,沒錯(cuò),就是通過業(yè)務(wù)路由和內(nèi)聚業(yè)務(wù),就可以完成我們的業(yè)務(wù)需求。在這里業(yè)務(wù)路由就是標(biāo)準(zhǔn)的RESTful請求,而內(nèi)聚業(yè)務(wù)就是我一直在說的后端組件。

再舉更加簡單的例子,相信一看就能徹底明白我說的:

app.use('/register’,用戶注冊組件)

app.use('/shoppingcart',購物車組件)

app.use('/product',產(chǎn)品管理組件)

...

到這里,已經(jīng)接近尾聲,因?yàn)橐呀?jīng)很明了了,每個(gè)業(yè)務(wù)組件僅僅通過一句話,就能無縫嵌入到原生系統(tǒng)中,架構(gòu)師所需要做的,就是規(guī)劃路由,開發(fā)者們需要做的,就是實(shí)現(xiàn)每一個(gè)內(nèi)聚業(yè)務(wù)體,也就是業(yè)務(wù)組件。在這里,每個(gè)業(yè)務(wù)組件內(nèi)部都獨(dú)立實(shí)現(xiàn)MVC三層,類似與Vue組件中的HTML,JS,CSS三者,高度內(nèi)聚其中。

這樣,每個(gè)業(yè)務(wù)組件就真的能夠通過包的方式分發(fā),真正實(shí)現(xiàn)代碼的可復(fù)用,避免重復(fù)造輪子。

這段時(shí)間以來,我個(gè)人一直在做這方面的工作,寫下這篇文章之時(shí),我初步完成了一個(gè)組件框架的實(shí)現(xiàn),下面是我制作的一個(gè)教學(xué)入口:

XServer——全新組件化后端構(gòu)建


在這個(gè)教學(xué)示例入口里,包含了我個(gè)人開發(fā)的很多Node中間件,當(dāng)然,因?yàn)槠綍r(shí)工作的關(guān)系,和這個(gè)工作量很大,文檔方面還不是很完善,github上工程的使用和教學(xué)都還有點(diǎn)粗糙,這些都還需要一段時(shí)間慢慢完善,希望大家能多多包涵。


結(jié)語

終于寫下了這篇文章,這篇文章,是個(gè)人在這一階段的思考和總結(jié),也是希望XServer能夠得到更多人的支持和意見,時(shí)代總在不停的進(jìn)步,作為對技術(shù)無比熱愛和追求的我,永遠(yuǎn)不會停息,也許明天還有比NodeJS更好的存在出現(xiàn),我期待著...

謝謝閱讀:)

關(guān)于:XServer官網(wǎng)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,229評論 25 708
  • 本書和作者 本書是著名的全球暢銷書,超過30種語言出版,被評為《金融時(shí)報(bào)》、《商業(yè)周刊》年度商業(yè)暢銷書之一,《經(jīng)濟(jì)...
    一只狼閱讀 602評論 0 3
  • 暗戀是每個(gè)女孩心里的一朵花,有的花開了,有的花凋謝??墒且膊粫⒆钃踝非髳鄣穆贰?第一次暗戀 也許我比較早熟,第...
    BIBI大爺閱讀 1,872評論 0 1
  • 每一種食物都可以代表一種個(gè)性的人。 火辣熱情的像辣椒,在一盤子菜里你很難忽視它的存在,就像在人群里你總是第一個(gè)發(fā)現(xiàn)...
    飛行家MK閱讀 485評論 0 0

友情鏈接更多精彩內(nèi)容