軟件架構(gòu)分層,你的項(xiàng)目處于什么階段?
前言
只要從事軟件開發(fā)的工作,系統(tǒng)架構(gòu)是必備知識(shí)。有朋友說可能會(huì)說,我只是一個(gè)搬磚的,怎么會(huì)接觸到架構(gòu)知識(shí)呢?其實(shí),除了架構(gòu)的設(shè)計(jì)者(也就是架構(gòu)師),作為普通的開發(fā)者也是在時(shí)刻踐行著系統(tǒng)架構(gòu)的理論。畢竟,再好的架構(gòu),都需要碼農(nóng)去實(shí)施。只不過當(dāng)你沒有系統(tǒng)了解軟件架構(gòu)時(shí),可能感知不到而已。
本篇文章就帶大家系統(tǒng)的了解一下軟件架構(gòu)的分層,學(xué)習(xí)完畢,你就會(huì)明白,為什么系統(tǒng)要分層。同時(shí),也能準(zhǔn)確的看清楚目前自己系統(tǒng)中采用的是什么樣的分層架構(gòu)。
不采用架構(gòu)分層,行不行?
首先我們來思考一個(gè)問題,如果一個(gè)系統(tǒng)不采用分層架構(gòu)可不可以?這個(gè)問題就好像在問,代碼中不使用設(shè)計(jì)模式行不行?答案當(dāng)然是可以的。但不采用架構(gòu)分層,會(huì)帶來極大的未知風(fēng)險(xiǎn),或者說代碼極具熵增的特性。
作為一個(gè)初創(chuàng)軟件,可能沒有什么業(yè)務(wù)邏輯,沒有什么用戶量,而軟件最主要的目標(biāo)就是快速上線,實(shí)踐商業(yè)模式。此時(shí),可以不考慮分層。但隨著業(yè)務(wù)邏輯的復(fù)雜,業(yè)務(wù)板塊的增多,彼此之間就會(huì)出現(xiàn)錯(cuò)綜復(fù)雜的依賴關(guān)系,隨之就會(huì)產(chǎn)生的邏輯不清晰、可讀性差,維護(hù)困難,改動(dòng)一處動(dòng)全身等問題。
什么是架構(gòu)分層?
分層架構(gòu)是將軟件模塊按照水平切分的方式分成多個(gè)層,一個(gè)系統(tǒng)由多層組成,每層由多個(gè)模塊組成。同時(shí),每層有自己獨(dú)立的職責(zé),多個(gè)層次協(xié)同提供完整的功能。比如,我們經(jīng)常提到的MVC架構(gòu),就是一種非常典型非?;A(chǔ)的分層方式。
分層設(shè)計(jì)的本質(zhì)其實(shí)就是將復(fù)雜問題簡單化,基于單一職責(zé)原則讓每層代碼各司其職,基于“高內(nèi)聚,低耦合”的設(shè)計(jì)思想實(shí)現(xiàn)相關(guān)層對(duì)象之間的交互。從而,提升代碼的可維護(hù)性和可擴(kuò)展性。
系統(tǒng)架構(gòu)分層之后,往往需要達(dá)到以下目標(biāo):
- 高內(nèi)聚:分層設(shè)計(jì)可以簡化系統(tǒng)設(shè)計(jì),讓不同層專注做某一模塊的事;
- 低耦合:層與層之間通過接口或API來交互,依賴方不用知道被依賴方的細(xì)節(jié);
- 復(fù)用:分層之后可以做到代碼或功能的復(fù)用;
- 擴(kuò)展性:分層架構(gòu)可以讓代碼更容易橫向擴(kuò)展
通訊領(lǐng)域的OSI參考模型
在計(jì)算機(jī)領(lǐng)域現(xiàn)有最典型的分層架構(gòu)設(shè)計(jì)就是OSI參考模型和TCP/IP參考模型了。關(guān)于這個(gè)模型,我們?cè)凇兑黄恼?,只用看三遍,終生不忘網(wǎng)絡(luò)分層! 》一文中已經(jīng)詳細(xì)介紹了。下面直接看一下相關(guān)的模型圖:
對(duì)于上述的三種分層模式,試想一下,如果沒有分層,當(dāng)一個(gè)業(yè)務(wù)或協(xié)議需要改變時(shí),我們只能針對(duì)整個(gè)系統(tǒng)做修改或擴(kuò)展。而分層之后,便可以很方便的把不同功能的模塊抽離出來,修改對(duì)應(yīng)的模塊即可。而且不同層還可以被復(fù)用,只要確保按照這個(gè)層的協(xié)議來處理就可以了。
軟件系統(tǒng)整體分層
以Java軟件應(yīng)用為例,整個(gè)軟件系統(tǒng)也可進(jìn)行分層,比如分為部署的硬件環(huán)境、操作系統(tǒng)、所需的中間件、承載業(yè)務(wù)的應(yīng)用程序以及軟件接入層??赏ㄟ^下圖進(jìn)行整體了解:
對(duì)于上述分層也產(chǎn)生了對(duì)應(yīng)在職位,比如運(yùn)維工程師、中間件工程師、產(chǎn)品經(jīng)理、開發(fā)工程師、測(cè)試工程師等工種。而我們?cè)趯?shí)踐過程中,接觸最多,使用最多的分層要屬應(yīng)用軟件層了,其次是中間件層。
下面我們就來看看針對(duì)應(yīng)用軟件層通常有哪些分層方式。
經(jīng)典三層架構(gòu)
三層架構(gòu)(3-tier application) ,通常就是將整個(gè)業(yè)務(wù)應(yīng)用劃分為:表現(xiàn)層(UI)、業(yè)務(wù)邏輯層(BLL)、數(shù)據(jù)訪問層(DAL)。
表現(xiàn)層(UI),通俗講就是展現(xiàn)給用戶的界面,對(duì)應(yīng)項(xiàng)目中的Web層包含Servlet和Controller等。
業(yè)務(wù)邏輯層(BLL):也稱作領(lǐng)域?qū)樱?fù)責(zé)系統(tǒng)業(yè)務(wù)邏輯的處理,對(duì)應(yīng)項(xiàng)目中Service和ServiceImpl等。
數(shù)據(jù)訪問層(DAL):該層所做事務(wù)直接操作數(shù)據(jù)庫,針對(duì)數(shù)據(jù)的增添、刪除、修改、更新、查找等,對(duì)應(yīng)項(xiàng)目中的Dao。
在提出該分層架構(gòu)的時(shí)代,多數(shù)系統(tǒng)往往較為簡單,本質(zhì)上都是一個(gè)單體架構(gòu)(Monolithic Architecture)的數(shù)據(jù)庫管理系統(tǒng)。這種分層架構(gòu)已經(jīng)是Client-Server架構(gòu)的進(jìn)化了,它有效地隔離了業(yè)務(wù)邏輯與數(shù)據(jù)訪問邏輯,使得這兩個(gè)不同關(guān)注點(diǎn)能夠相對(duì)自由和獨(dú)立地演化。
在開源技術(shù)框架中,表現(xiàn)層實(shí)現(xiàn)的代表作品是Struts1/2、Spring MVC,業(yè)務(wù)層實(shí)現(xiàn)的代表作品是Spring,持久層實(shí)現(xiàn)的代表作品是Hibernate和Mybatis。
MVC
MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設(shè)計(jì)典范,用一種業(yè)務(wù)邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,將業(yè)務(wù)邏輯聚集到一個(gè)部件里面,在改進(jìn)和個(gè)性化定制界面及用戶交互的同時(shí),不需要重新編寫業(yè)務(wù)邏輯。MVC被獨(dú)特的發(fā)展起來用于映射傳統(tǒng)的輸入、處理和輸出功能在一個(gè)邏輯的圖形化用戶界面的結(jié)構(gòu)中。
標(biāo)準(zhǔn)的MVC交互模型如下圖:
View:視圖,為用戶提供使用界面,與用戶直接進(jìn)行交互。
Model:模型,承載數(shù)據(jù),對(duì)用戶提交請(qǐng)求進(jìn)行計(jì)算的模塊。分為兩類,一類稱為數(shù)據(jù)承載Bean,一類稱為業(yè)務(wù)處理Bean。數(shù)據(jù)承載Bean是指實(shí)體類,專門承載業(yè)務(wù)數(shù)據(jù)的,如Student、User等。而業(yè)務(wù)處理Bean則是指Service或Dao對(duì)象,專門用于處理用戶提交請(qǐng)求的。
Controller:控制器,用于將用戶請(qǐng)求轉(zhuǎn)發(fā)給相應(yīng)的Model進(jìn)行處理,并處理Model的計(jì)算結(jié)果向用戶提供響應(yīng)。
從圖中可以看到,標(biāo)準(zhǔn)的MVC中模型能主動(dòng)推數(shù)據(jù)給視圖進(jìn)行更新(觀察者設(shè)計(jì)模式,在模型上注冊(cè)視圖,當(dāng)模型更新時(shí)自動(dòng)更新視圖),但在Web開發(fā)中模型是無法主動(dòng)推給視圖(無法主動(dòng)更新用戶界面),因?yàn)樵赪eb開發(fā)是請(qǐng)求-響應(yīng)模型。
Web MVC標(biāo)準(zhǔn)架構(gòu),如下圖所示:
在Web MVC模式下,模型無法主動(dòng)推數(shù)據(jù)給視圖,如果用戶想要視圖更新,需要再發(fā)送一次請(qǐng)求(即請(qǐng)求-響應(yīng)模型)。MVC用于將web(UI)層進(jìn)行職責(zé)解耦。
三層架構(gòu)和MVC的區(qū)別與聯(lián)系
MVC嚴(yán)格說是三層架構(gòu)中的UI層,也就是說,MVC把三層架構(gòu)中的UI層再度進(jìn)行了分化,分成了控制器、視圖、實(shí)體三個(gè)部分,控制器完成頁面邏輯,通過實(shí)體來與界面層完成通話,而C層直接與三層中的BLL進(jìn)行對(duì)話。
三層架構(gòu)和MVC可以共存。三層架構(gòu)是基于業(yè)務(wù)邏輯來分的,而MVC是基于頁面來分的。MVC是表現(xiàn)模式(Presentation Pattern),三層架構(gòu)是典型的架構(gòu)模式(Architecture Pattern)。
三層架構(gòu)的分層模式是典型的上下關(guān)系,上層依賴于下層。但MVC作為表現(xiàn)模式是不存在上下關(guān)系的,而是相互協(xié)作關(guān)系。即使將MVC當(dāng)作架構(gòu)模式,也不是分層模式。MVC和三層架構(gòu)基本沒有可比性,是應(yīng)用于不同領(lǐng)域的技術(shù)。
阿里四層架構(gòu)
三層架構(gòu)實(shí)現(xiàn)比較簡單,很多朋友可能覺得項(xiàng)目分層就應(yīng)該如此,結(jié)果就是往往會(huì)出現(xiàn)一大堆的業(yè)務(wù)邏輯都堆砌在Service層中。而在《阿里巴巴 Java 開發(fā)手冊(cè) 》中將原來的三層架構(gòu)進(jìn)一步細(xì)化,添加了Manager通用業(yè)務(wù)處理層。
Manager層可以將原Service層的一些通用能力進(jìn)行下沉,比如與緩存和存儲(chǔ)交互策略,中間件的接入;還可以封裝對(duì)第三方接口的調(diào)用,比如調(diào)用支付服務(wù),調(diào)用審核服務(wù)等RPC接口。
通用業(yè)務(wù)處理層,它有如下特征:
- 對(duì)第三方平臺(tái)封裝的層,預(yù)處理返回結(jié)果及轉(zhuǎn)化異常信息。
- 對(duì)Service層通用能力的下沉,如緩存方案、中間件通用處理。
- 與DAO層交互,對(duì)多個(gè)DAO的組合復(fù)用。
其各層的作用如下:
- 終端顯示層:各端模板渲染并執(zhí)行顯示的層。當(dāng)前主要是Velocity渲染,JS渲染, JSP渲染,移動(dòng)端展示等。
- 開放接口層:將Service層方法封裝成開放接口,同時(shí)進(jìn)行網(wǎng)關(guān)安全控制和流量控制等。
- Web層:主要是對(duì)訪問控制進(jìn)行轉(zhuǎn)發(fā),各類基本參數(shù)校驗(yàn),或者不復(fù)用的業(yè)務(wù)簡單處理等。
- Service層:業(yè)務(wù)邏輯層。
- Manager層:通用業(yè)務(wù)處理層。
- DAO層:數(shù)據(jù)訪問層,與底層 MySQL、Oracle、HBase 等進(jìn)行數(shù)據(jù)交互。
- 外部接口或第三方平臺(tái):包括其它部門RPC開放接口,基礎(chǔ)平臺(tái),其它公司的HTTP接口。
系統(tǒng)工程結(jié)構(gòu)
在學(xué)習(xí)了以上分層架構(gòu)之后,下面來看一下針對(duì)分層在軟件系統(tǒng)中的對(duì)照關(guān)系表:
以上分層定義僅供參考。在上表中還多出了對(duì)外接口層和接入層。
對(duì)外接口層:所有對(duì)外的接口放在這層,不能包含任何業(yè)務(wù)邏輯,只數(shù)據(jù)對(duì)象的轉(zhuǎn)換和異常的封裝。
接入層:所有外部系統(tǒng)的依賴放在這層,好處是一旦外部系統(tǒng)接口修改,只需要在一處修改即可。
DDD分層架構(gòu)
DDD是一種處理高度復(fù)雜領(lǐng)域的設(shè)計(jì)思想,試圖分離技術(shù)實(shí)現(xiàn)的復(fù)雜性,同時(shí)圍繞業(yè)務(wù)概念構(gòu)建領(lǐng)域模型,提出的一種軟件架構(gòu)設(shè)計(jì)的方法論。
DDD分層架構(gòu)將數(shù)據(jù)、緩存等都視為基礎(chǔ)層, 可以被所有層調(diào)用;抽離了領(lǐng)域?qū)?,?fù)責(zé)核心業(yè)務(wù)邏輯處理,領(lǐng)域?qū)诱{(diào)用外部依賴全部通過接口,以保證領(lǐng)域?qū)拥?00%單測(cè)覆蓋率;應(yīng)用層聚合多個(gè)領(lǐng)域?qū)拥哪芰?,只做功能的組合、轉(zhuǎn)發(fā),不負(fù)責(zé)具體業(yè)務(wù)邏輯。
我們這里只做DDD分層架構(gòu)的簡單介紹,關(guān)于DDD概念不做過多拓展,相關(guān)架構(gòu)模式可專門進(jìn)行學(xué)習(xí)一下??匆幌翫DD分層的架構(gòu)圖:
其中對(duì)應(yīng)層的功能介紹如下:
接口層(Interfaces):該層包含與其他系統(tǒng)交互的所有內(nèi)容,如Web服務(wù)器、RESTful接口。接口層處理傳入數(shù)據(jù)的解釋、校驗(yàn)、編解碼、序列化操作,同時(shí)可以考慮引入專門的DTO(數(shù)據(jù)轉(zhuǎn)換對(duì)象)來協(xié)助數(shù)據(jù)轉(zhuǎn)換;
應(yīng)用層(Application):該層負(fù)責(zé)驅(qū)動(dòng)應(yīng)用程序完成工作流程。很薄一層,協(xié)調(diào)多個(gè)領(lǐng)域?qū)ο?實(shí)體、聚合根、領(lǐng)域服務(wù))實(shí)現(xiàn)服務(wù)編排和組合完成工作流,該層通常不應(yīng)該包含具體業(yè)務(wù)邏輯。該層涉及:其他微服務(wù)RPC調(diào)用、微服務(wù)編排和組合、分布式事務(wù)實(shí)現(xiàn)、消息驅(qū)動(dòng)事件的驅(qū)動(dòng)、日志記錄等。
領(lǐng)域?qū)?Domain):該層是軟件的核心,包含業(yè)務(wù)邏輯具體實(shí)現(xiàn),包含實(shí)體、值對(duì)象、聚合、領(lǐng)域服務(wù)、倉儲(chǔ)接口等領(lǐng)域?qū)ο髢?nèi)容,通常該層應(yīng)該配備圖示告知軟件是如何工作的;
基礎(chǔ)層(Infrastructure):包含網(wǎng)關(guān)、緩存、數(shù)據(jù)庫存儲(chǔ)、消息中間件、監(jiān)控、應(yīng)用程序服務(wù)等通用的技術(shù)和基礎(chǔ)服務(wù)。基礎(chǔ)層以不同方式支持到其他三層,促進(jìn)各層間通信。配置文件、數(shù)據(jù)庫Schema模式定義以及倉儲(chǔ)接口實(shí)現(xiàn)都是基礎(chǔ)結(jié)構(gòu)的一部分;
DDD分層架構(gòu)傳統(tǒng)三層架構(gòu)的比較
DDD四層架構(gòu)也基于傳統(tǒng)三層架構(gòu)的,看一下它們之間的對(duì)照關(guān)系:
DDD四層架構(gòu)和傳統(tǒng)三層架構(gòu)有以下區(qū)別:
- 關(guān)注點(diǎn)不一樣:三層架構(gòu)關(guān)注請(qǐng)求調(diào)用順序;DDD架構(gòu)關(guān)注領(lǐng)域服務(wù)。
- 橫向劃分方式不一樣:三層架構(gòu)主要關(guān)注縱向劃分,對(duì)橫向劃分沒有約定;DDD架構(gòu)更關(guān)注縱向,即:多個(gè)領(lǐng)域?qū)又g劃分及交互方式。
- 對(duì)資源的定位不一樣:三層架構(gòu)把所有依賴的數(shù)據(jù)都放到數(shù)據(jù)訪問層;DDD架構(gòu)只將領(lǐng)域強(qiáng)關(guān)聯(lián)的數(shù)據(jù)放到Repository中,其他比如API層緩存、文件等都當(dāng)成基礎(chǔ)服務(wù)來處理。
關(guān)于DDD架構(gòu)分層還有整潔架構(gòu)和六邊形架構(gòu)兩種形式,這里就不再拓展,感興趣的朋友可自行查找相關(guān)資料進(jìn)行學(xué)習(xí)。
小結(jié)
本篇文章為大家講解了市面上常見的架構(gòu)分層。分層架構(gòu)的目的是通過關(guān)注點(diǎn)分離來降低系統(tǒng)的復(fù)雜度,同時(shí)滿足單一職責(zé)、高內(nèi)聚、低耦合、提高可復(fù)用性和降低維護(hù)成本。但分層架構(gòu)同樣也有一定的缺點(diǎn),比如開發(fā)成本高、性能略低、可擴(kuò)展性低等問題。實(shí)踐中,可根據(jù)需要選擇合適的分層架構(gòu)。