簡單地說,就是要把復(fù)雜的問題簡單化,把一個(gè)從0到N的問題轉(zhuǎn)化為N個(gè)0到1的問題。另一個(gè)相近的說法就是“解耦”。
舉個(gè)例子,我們接到一個(gè)客戶需求,要求寫一個(gè)應(yīng)用,這個(gè)應(yīng)用中有頁面的切換,有對(duì)應(yīng)頁面的數(shù)據(jù)交互,數(shù)據(jù)的獲取,數(shù)據(jù)的計(jì)算,如果把這些功能放在一個(gè)單一的應(yīng)用中的話,從大局觀的角度來看,這個(gè)單一的應(yīng)用是比較復(fù)雜的。
為了降低這個(gè)復(fù)雜度,我們首先要做的就是前后端分開,關(guān)于前后端的定義,大體來說是這樣的:前端負(fù)責(zé)的內(nèi)容主要有頁面路徑管理,頁面對(duì)應(yīng)數(shù)據(jù)的顯示與管理等等;后端負(fù)責(zé)的內(nèi)容主要有數(shù)據(jù)的提供,數(shù)據(jù)的計(jì)算,安全性管理等等;前后端的通信一般通過HTTP請求來實(shí)現(xiàn);當(dāng)然這里也有個(gè)例外情況,比如有一部分功能可能要求實(shí)時(shí)性,像類似聊天類的功能,共享文檔的功能,畫板分享的功能,多人協(xié)同操作的功能等等,需要通過socketio這樣的通信機(jī)制進(jìn)行。
再細(xì)分一下講,單一的程序框架模型會(huì)是MVC(Model-View-Controller)結(jié)構(gòu)的。前后端分離以后,后端會(huì)有Model/Entity-Repository/Service-Controller,前端會(huì)有View-Model-API調(diào)用。
看一下前端部分,View主要是指網(wǎng)頁的頁面,手機(jī)端的頁面(Android就是Activity,Layout和View等, iOS就是View Controller和UIView等),如果使用跨平臺(tái)技術(shù)(如React Native, Flutter,Xamarin等)也離不開上述的概念,大同小異。這部分的處理當(dāng)然離不開數(shù)據(jù)Model和API調(diào)用。處理好這些以后前端的任務(wù)也就做好了。
再看一下后端部分,界面相關(guān)的處理已經(jīng)不再是后端的任務(wù)了,后端只需要通過API提供前端需要的數(shù)據(jù)就可以了。Controller就是用來定義這些API的,這一部分會(huì)分析或者計(jì)算出前端的輸入和輸出模型,具體處理方式有以下幾個(gè)因素考慮:請求的類型如GET,POST, PUT, DELTE,PATCH等;數(shù)據(jù)From Body,數(shù)據(jù)From Route,數(shù)據(jù)From Form等等;數(shù)據(jù)處理完成以后,一個(gè)是通過API返回,一個(gè)是更新數(shù)據(jù)源,這里的數(shù)據(jù)源可以是數(shù)據(jù)庫如SQL和NoSQL,可以是消息中間件如Kafka,也可以是數(shù)據(jù)緩沖服務(wù)器如Redis等等。通過上述的描述,我們可以看到后端的任務(wù)變得更加輕量級(jí)了,邏輯上也更加簡單了。
所以,通過前后端的分離,我們把前端和后端的復(fù)雜度始終維持在可控的范圍內(nèi)。如果在軟件開發(fā)中始終使用這種理念的話,我們會(huì)大大擴(kuò)展我們的軟件開發(fā)效率和程序質(zhì)量。因?yàn)榻鉀Q一個(gè)N難度的問題顯然要比解決N個(gè)1難度問題要困難得多。對(duì)于一個(gè)N難度的問題,我們將其分解為N個(gè)1難度的問題之后,我們可以各個(gè)擊破,步步為營,一步一個(gè)腳印,在工作中從容而且自信,因?yàn)槲覀兪冀K用最簡單的方法去解決問題。如果碰上復(fù)雜的問題,就再將其分化為多個(gè)難度為1的問題,以此類推。簡單一些講,就是要保證我們在解決問題的時(shí)候,不打無準(zhǔn)備之仗,始終腳踏實(shí)地,分而治之,避免把我們自己架到火爐上烤。
復(fù)雜度降低以后,整個(gè)項(xiàng)目的維護(hù)成本和擴(kuò)展成本都會(huì)非常的低。我們對(duì)項(xiàng)目開發(fā)的駕馭能力也會(huì)提高很多。
再說一個(gè)數(shù)據(jù)流向的問題,這個(gè)主要發(fā)生在前端。 這部分的處理會(huì)直接關(guān)聯(lián)到前端程序設(shè)計(jì)的復(fù)雜度。在三大前端框架中有雙向數(shù)據(jù)流向和單向數(shù)據(jù)流向,其中React只支持單向數(shù)據(jù)流向。但是目前有了Hooks機(jī)制以后,你可以通過傳Setter和Getter兩個(gè)Reference來達(dá)到修改數(shù)據(jù)的目的。這種通過傳遞參數(shù)到其他Component的模式實(shí)際上增加了程序的復(fù)雜度,因?yàn)橐粚訉拥膫鬟f使得組件之間的耦合性增強(qiáng)了。
那么如何解決這個(gè)問題呢
在Angular中可以通過Service中定義Getter和Setter來解決這個(gè)問題,每個(gè)需要操作這個(gè)數(shù)據(jù)的組件都可以依賴注入這個(gè)Service,有了這個(gè)Service,就可以很輕松的讀取和更新其中的數(shù)據(jù)了,對(duì)于數(shù)據(jù)的監(jiān)聽,可以通過在Service定義一個(gè)Subject,監(jiān)聽到數(shù)據(jù)變化以后,你可以更新界面,向服務(wù)器發(fā)送請求等等,這樣做,組件之間的耦合性就大大降低了。
再說一下單向數(shù)據(jù)流向機(jī)制如Ngrx, VueX, Mux等等。單向數(shù)據(jù)流向機(jī)制在目前的前端開發(fā)中使用很普遍,然而,實(shí)際上這種機(jī)制會(huì)增加程序的復(fù)雜度。這個(gè)主要是因?yàn)檫@種機(jī)制會(huì)在前端開發(fā)層級(jí)中引入另外一套體系來維護(hù)數(shù)據(jù)的流向,假如我們對(duì)已有的業(yè)務(wù)定義為從0到1的實(shí)現(xiàn),加上這個(gè)機(jī)制以后,就變成了0到1再加上另外一個(gè)0到1.變成了0到2的問題。這就變復(fù)雜了。
前端只要做好如下的任務(wù)如頁面的切換,數(shù)據(jù)與后端的交互,數(shù)據(jù)模型與API的對(duì)應(yīng), 組件盡量的寫成Self-Contained就可以了。
所以我不建議在前端中再額外的添加類似的數(shù)據(jù)流向機(jī)制了。
再談一下后端的分析。我們在談后端的時(shí)候,我們不太關(guān)心使用什么技術(shù)(Node JS,.net Core,SpringBoot,PHP, Python, Ruby On Rails等等),這是因?yàn)楹蠖说倪壿嬍乔逦?,不管你用那種技術(shù),程序的設(shè)計(jì)的層級(jí)是大同小異的。
后端的主要任務(wù)是API數(shù)據(jù)的提供。比如用戶相關(guān)的API,創(chuàng)建一個(gè)用戶,更新一個(gè)用戶,刪除一個(gè)用戶等等的操作都是在一個(gè)用戶Controller定義相關(guān)的API。對(duì)于Controller的添加,我建議要根據(jù)業(yè)務(wù)層來添加,不要在一個(gè)Controller中做太多的事情。比如我們可以添加Book Controller來處理Book相關(guān)的操作,訂單Controller來處理訂單相關(guān)的操作。
這樣做是為了把API設(shè)計(jì)變成線性的,平行的,各自Controller之間的耦合性降到最低,從而也就降低了復(fù)雜度。
進(jìn)一步說,在實(shí)現(xiàn)的層級(jí)上,我們可以有Data Set對(duì)應(yīng)數(shù)據(jù)庫表格,Entity對(duì)應(yīng)數(shù)據(jù)表格記錄,Model對(duì)應(yīng)API數(shù)據(jù)模型,Service/Repository負(fù)責(zé)邏輯實(shí)現(xiàn)等等。
在后端技術(shù)選取中,數(shù)據(jù)庫相關(guān)的操作是一個(gè)不可逾越的門檻,有的框架使用類似EntityFramework的機(jī)制如.NetCore和PHP Laravel, 有的使用類似JPA Hibernate,Mybatis如Spring Boot,有的則直接使用JDBC SQL語句執(zhí)行的方式,有的結(jié)合Stored Procedure。在這個(gè)地方,按照程序復(fù)雜度排序的話,由低到高分別是EntityFrameWork
當(dāng)然,數(shù)據(jù)庫的設(shè)計(jì),數(shù)據(jù)庫的升級(jí)Migration也都是關(guān)系到程序項(xiàng)目復(fù)雜度的因素。這個(gè)要結(jié)合具體的后端技術(shù)來談。在本文中我們就不展開了。
前后端分離的作用給用戶帶來了許多的便利。互聯(lián)網(wǎng)與科技時(shí)代并存的年代,會(huì)有怎樣的浪潮出現(xiàn)?想要了解更多信息,請繼續(xù)關(guān)注中培偉業(yè)。