小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

回歸架構(gòu)本真:從規(guī)劃、思維到設(shè)計(jì),構(gòu)建堅(jiān)不可摧的架構(gòu)根基

 stwym 2016-06-22

一、什么是架構(gòu)

關(guān)于什么是架構(gòu),業(yè)界從來沒有一個(gè)統(tǒng)一的定義。Martin Fowler在《企業(yè)應(yīng)用架構(gòu)模式》中也沒有對其給出定義,只是提到能夠統(tǒng)一的內(nèi)容有兩點(diǎn):

  1. 最高層次的系統(tǒng)分解;

  2. 系統(tǒng)中不易改變的決定。

《軟件架構(gòu)設(shè)計(jì)》一書則將架構(gòu)定義總結(jié)為組成派和決策派:

  • 組成派:架構(gòu)=組件+交互:軟件系統(tǒng)的架構(gòu)將系統(tǒng)描述為計(jì)算組件及組件之間的交互。

  • 決策派:架構(gòu)=重要決策集:軟件架構(gòu)是在一些重要方面所作出的決策的集合。

而架構(gòu)的概念最初來源于建筑,因此,我想從建筑的角度去思考這個(gè)問題。Wikipedia中,對架構(gòu),即Architecture的定義如下:

Architecture is both the process and the product of planning, designing, and constructing buildings and other physical structures.

簡單翻譯就是:架構(gòu)是規(guī)劃、設(shè)計(jì)和構(gòu)建建筑物或其他物理構(gòu)筑物的過程和結(jié)果。

從上面的定義中可知,首先,架構(gòu)的最終目標(biāo)是為了產(chǎn)出建筑物或其他物理構(gòu)筑物,構(gòu)筑物可以只是一套房子,也可以是一棟樓盤,抑或是一個(gè)小區(qū)、商業(yè)區(qū),甚至是一個(gè)城市。構(gòu)筑物越大,其架構(gòu)必然也越復(fù)雜。

其次,產(chǎn)出建筑物之前需要經(jīng)過三個(gè)階段:規(guī)劃(planning)、設(shè)計(jì)(designing)和構(gòu)建(constructing)。這三個(gè)階段其實(shí)也是架構(gòu)的核心了。比如,開發(fā)商要建一個(gè)住宅小區(qū),首先肯定要對該小區(qū)有一個(gè)整體的規(guī)劃吧:小區(qū)的建設(shè)選址、建設(shè)的規(guī)模、建設(shè)的內(nèi)容、投資估算、建設(shè)周期等等。接著,就要對小區(qū)的各方面進(jìn)行設(shè)計(jì)了,最高層次的應(yīng)該是小區(qū)的總體布局設(shè)計(jì),拆分開的話就是各樓盤的設(shè)計(jì)、綠化的設(shè)計(jì)、各種配套設(shè)施的設(shè)計(jì)等等,再細(xì)化下去就是各種戶型的設(shè)計(jì)、樓盤內(nèi)和小區(qū)內(nèi)各種走道的設(shè)計(jì)等等。最后,構(gòu)建階段也就是施工階段了,是將之前所有的想法轉(zhuǎn)為實(shí)際的建筑物的階段。即架構(gòu)包含了以上的過程和結(jié)果。

那么,如果將建筑物換成了軟件,那就變成對軟件架構(gòu)的定義了:軟件架構(gòu)是規(guī)劃、設(shè)計(jì)和構(gòu)建軟件的過程和結(jié)果。

相應(yīng)地,軟件架構(gòu)的最終目標(biāo)就是為了產(chǎn)出軟件,可以是一個(gè)App,也可以是一個(gè)平臺(tái),如SaaS、PaaS、BaaS等等,甚至還可以是智慧城市這樣龐大的生態(tài)系統(tǒng),地球人都知道,越龐大復(fù)雜的系統(tǒng),架構(gòu)越難。規(guī)劃階段更多考慮的是軟件的需求,包括業(yè)務(wù)上功能性需求和技術(shù)上的非功能性需求,如可靠性、可擴(kuò)展性、可維護(hù)性等;此階段的架構(gòu)一般為系統(tǒng)架構(gòu)。設(shè)計(jì)階段的工作更多的就是拆分細(xì)化,以滿足各種需求;此階段的架構(gòu)一般為邏輯架構(gòu)。構(gòu)建階段主要就是對軟件的實(shí)現(xiàn)和部署了;此階段的架構(gòu)一般為物理架構(gòu)。

二、架構(gòu)規(guī)劃

架構(gòu)規(guī)劃做什么呢?我覺得主要是規(guī)劃好下個(gè)階段架構(gòu)設(shè)計(jì)的邊界。而影響架構(gòu)邊界的,其實(shí)就是需求。需求形成了對架構(gòu)的約束條件,從而也對架構(gòu)設(shè)計(jì)形成了邊界。可以分為三大類:商業(yè)需求、功能需求和質(zhì)量需求。

(一)商業(yè)需求

商業(yè)需求是最高層次的需求,對其含義,我比較贊同溫昱在《軟件架構(gòu)設(shè)計(jì)》中提到的解釋:它關(guān)注從客戶群、企業(yè)現(xiàn)狀、未來發(fā)展、預(yù)算、立項(xiàng)、開發(fā)、運(yùn)營、維護(hù)在內(nèi)的整個(gè)軟件生命周期涉及的商業(yè)因素,包括了商業(yè)層面的目標(biāo)、期望和限制等。商業(yè)需求一般對架構(gòu)的影響比較大,對架構(gòu)產(chǎn)生限制的商業(yè)因素也比較多,在此列舉一些比較常見的:

  1. 上市時(shí)間:上市時(shí)間限定了系統(tǒng)從設(shè)計(jì)、開發(fā)、測試到上市的時(shí)間邊界。之前我跟進(jìn)過一個(gè)垂直于大學(xué)生市場的應(yīng)用,上市時(shí)間就要求在新生入學(xué)前,不然就會(huì)錯(cuò)過推廣的最佳時(shí)期,預(yù)留給開發(fā)的時(shí)間只有兩個(gè)月。因此,我們只好大部分重用前個(gè)項(xiàng)目的元素,包括重用服務(wù)端的一些模塊,還包括客戶端的架構(gòu)和界面。當(dāng)然,一般情況下,預(yù)留給開發(fā)的時(shí)間不會(huì)這么短,但也不會(huì)特別長。架構(gòu)師需要根據(jù)時(shí)間長短,平衡各方面需求,做好架構(gòu)選型。

  2. 成本預(yù)算:成本預(yù)算就限定了能使用的資源邊界。不同架構(gòu)的開發(fā)成本肯定不同,要滿足更多功能需求和更多質(zhì)量需求的架構(gòu)成本也更高,在預(yù)算有限的情況下,只能權(quán)衡各種需求,優(yōu)先滿足重要程度高的需求。

  3. 人力現(xiàn)狀:100人的開發(fā)團(tuán)隊(duì)和10人的開發(fā)團(tuán)隊(duì),軟件的架構(gòu)會(huì)有很大不同。另外,開發(fā)團(tuán)隊(duì)人員所掌握的技術(shù)也會(huì)對架構(gòu)選型有影響。例如,團(tuán)隊(duì)里還沒有人會(huì)用React Native,那現(xiàn)階段就不適合選擇React Native作為App架構(gòu)的技術(shù)基礎(chǔ)。

  4. 與外圍系統(tǒng)的集成:當(dāng)需要與外圍系統(tǒng)集成時(shí),需要認(rèn)真考慮集成方法,尤其是外圍系統(tǒng)比較老的時(shí)候,集成難度可能更高。另外,外圍系統(tǒng)的不可控因素一般也比較多,因此,對架構(gòu)處理這些不可控風(fēng)險(xiǎn)的要求相對也高。

  5. 開放性:封閉的私有系統(tǒng)和開放式系統(tǒng)對架構(gòu)的要求也不同,一個(gè)系統(tǒng)如果選擇了開放,那對架構(gòu)的質(zhì)量要求更高,對安全性、擴(kuò)展性、性能等質(zhì)量屬性都應(yīng)該比封閉時(shí)高。

  6. 目標(biāo)市場:目標(biāo)用戶10萬、100萬、1000萬,不同級(jí)別的目標(biāo)市場,架構(gòu)也是大有不同。另外,大眾市場和垂直的專門市場,架構(gòu)也同樣有區(qū)別,較大的專門市場一般都采用產(chǎn)品線的規(guī)劃方案。

  7. 多端支持:現(xiàn)在移動(dòng)端普遍支持Android、iOS、Wechat,管理端通常則支持PC Web,如果管理端也要支持Android、iOS、Wechat,或者移動(dòng)端和管理端還要再支持WindowsPhone、黑莓,甚至再支持VR,則需要投入更多時(shí)間和人力,架構(gòu)上相應(yīng)也需要做出調(diào)整。

  8. 期望的系統(tǒng)生存期:從主觀上說,誰都希望自己的系統(tǒng)可以生存很久,但生存期越長,意味著系統(tǒng)的可修改性、可擴(kuò)展性、可移植性等需要更高。但是,受上市時(shí)間、成本預(yù)算等因素的制約,再加上軟件本身的變化快,所以,客觀上,一般也不會(huì)期望其生存期太長。當(dāng)系統(tǒng)不能滿足漸增的需求時(shí),基本通過重構(gòu)來解決。

  9. 階段性計(jì)劃:每一個(gè)大平臺(tái)系統(tǒng)普遍都是分階段完成的,因此,前期階段的架構(gòu)設(shè)計(jì)時(shí)就需要考慮好重用性、擴(kuò)展性、伸縮性、移植性等特性。但因?yàn)槊總€(gè)階段經(jīng)過市場驗(yàn)證后,需求有可能會(huì)變化,所以又不能過度設(shè)計(jì),否則就會(huì)造成設(shè)計(jì)浪費(fèi),還可能加大了后續(xù)階段架構(gòu)調(diào)整的難度。

  10. 國際化:如果走國際化路線,那架構(gòu)上就要考慮好對多國語言的支持。

  11. 競爭對手:產(chǎn)品要比競爭對手優(yōu)秀,那就要在一些關(guān)鍵的功能或質(zhì)量上超越對方,也意味著在這些方面的架構(gòu)需要投入更多。

  12. 法律法規(guī):比如,對某些關(guān)鍵字要進(jìn)行過濾屏蔽,這是天朝獨(dú)有的,大家懂的。

商業(yè)需求多種多樣,有些需求還可能會(huì)相互矛盾,比如,上市時(shí)間和成本預(yù)算就會(huì)和期望的系統(tǒng)生存期可能產(chǎn)生矛盾,期望的生存期越長其成本就會(huì)越高,需要投入的時(shí)間就會(huì)越多,那么,就有可能拖延上市時(shí)間。因此,做架構(gòu)規(guī)劃時(shí),必須梳理清楚哪些需求是能夠被滿足的,能被滿足的程度如何,需要在各個(gè)需求間權(quán)衡利弊。另外,商業(yè)需求因?yàn)槭亲罡邔哟蔚男枨?/strong>,因此,相對于功能需求和質(zhì)量需求,其優(yōu)先級(jí)一般也比較高。

(二)功能需求

功能需求描述了系統(tǒng)應(yīng)該提供的服務(wù),包括為用戶提供的服務(wù),也包括為其他系統(tǒng)提供的服務(wù)。而架構(gòu)主要就是為功能服務(wù)的,而功能需求基本與具體的業(yè)務(wù)相關(guān)。因此,要做好功能需求這塊的架構(gòu),就必須對該業(yè)務(wù)領(lǐng)域足夠了解,這樣才能更好地抽象建模。對功能需求的架構(gòu)規(guī)劃,主要就是建立業(yè)務(wù)領(lǐng)域模型。領(lǐng)域模型定下來后,下個(gè)階段的設(shè)計(jì)必須與領(lǐng)域模型保持一致。

而對功能需求進(jìn)行領(lǐng)域建模之前,還需先梳理下需求的優(yōu)先級(jí)。因?yàn)槭苌虡I(yè)需求的影響,功能需求也需要權(quán)衡。比如,上市時(shí)間緊、成本預(yù)算低、人力資源也不是很充足的情況下,功能需求只能少不能多。而需要與外圍系統(tǒng)集成的時(shí)候,也意味著這部分功能不需要自己實(shí)現(xiàn)了;但是,如果外圍系統(tǒng)無法完全滿足需求時(shí),則還需要自己再實(shí)現(xiàn)缺失的需求。因此,現(xiàn)階段需要滿足哪些功能需求?需要滿足到什么程度?這兩個(gè)問題確定了之后才能更有效地進(jìn)行領(lǐng)域建模。

領(lǐng)域建模主要就是要分析清楚每個(gè)領(lǐng)域模型和模型之間的關(guān)系。還是直接用一個(gè)例子來說明吧。假設(shè)現(xiàn)在要做一個(gè)支持O2O(Online To Offline)的電商平臺(tái),以下是經(jīng)過梳理后的幾個(gè)關(guān)鍵的功能需求:

  1. 商家可以在平臺(tái)發(fā)布商品,可以是實(shí)體類商品,也可以是服務(wù)類商品。

  2. 實(shí)體類商品支持快遞,服務(wù)類商品只能到商家門店兌換消費(fèi)。

  3. 用戶購買實(shí)體類商品時(shí)需提供收貨信息。

  4. 用戶購買每個(gè)商品時(shí)對應(yīng)生成一個(gè)訂單。

  5. 用戶購買的是實(shí)體類商品時(shí),可以查看商品的物流信息。

  6. 用戶購買的是服務(wù)類商品時(shí),可以用訂單的兌換碼到商家門店兌換消費(fèi)。

根據(jù)以上需求,可以初步得到相關(guān)的領(lǐng)域概念有:商家、商品、實(shí)體類商品、服務(wù)類商品、物流信息、門店、用戶、收貨信息、訂單、兌換信息。理清這些領(lǐng)域概念之間的關(guān)系之后,可以得到類似于下面的領(lǐng)域模型視圖:

回歸架構(gòu)本真:從規(guī)劃、思維到設(shè)計(jì),構(gòu)建堅(jiān)不可摧的架構(gòu)根基

當(dāng)然,這只是一個(gè)很小的例子,實(shí)際上的領(lǐng)域模型會(huì)比這個(gè)例子復(fù)雜得多。領(lǐng)域模型確定之后,系統(tǒng)中有多少業(yè)務(wù)領(lǐng)域、各領(lǐng)域概念之間的關(guān)系如何就一清二楚了。

(三)質(zhì)量需求

質(zhì)量需求是三類需求中,需求層次最低的,但卻是大部分架構(gòu)師最關(guān)注的??v覽那么多架構(gòu)技術(shù),就會(huì)發(fā)現(xiàn),大部分都是為了解決某個(gè)或某些質(zhì)量屬性優(yōu)化的問題。

質(zhì)量屬性常見的有以下這些:

  • 性能(Performance):性能無疑是一個(gè)非常重要的特性,尤其在計(jì)算資源有限的情況下。但也無需過分追求高性能,從而犧牲其他更重要的特性。

  • 安全性(Security):安全性一般會(huì)和性能相互制約,最明顯的例子就是HTTPS,使用HTTPS提高了安全性,但性能就會(huì)有所犧牲。很難做到既滿足高安全又高性能,因此需要根據(jù)具體需求平衡兩方面的特性。

  • 可用性(Availability):也有人稱為有效性,一般定義為:可用性 = 系統(tǒng)正常工作時(shí)間 / (系統(tǒng)正常工作時(shí)間 + 故障維修時(shí)間)。此定義就說明了可用性與系統(tǒng)故障有關(guān),故障率高,可用性就低,故障率低,可用性才高。另外,高可用性還說明了系統(tǒng)對故障維修的時(shí)間也很短。

  • 易用性(Usability):易用性很容易和可用性混淆,可用性關(guān)注的是系統(tǒng)長時(shí)間無故障運(yùn)行的能力,而易用性關(guān)注的則是系統(tǒng)易于使用的能力。

  • 魯棒性(Robustness):也稱為健壯性、容錯(cuò)性,是指系統(tǒng)在出現(xiàn)了用戶非法操作、或軟硬件的缺陷導(dǎo)致的異常情況下,系統(tǒng)依然能夠正常運(yùn)行的能力。比如說,系統(tǒng)在輸入錯(cuò)誤、磁盤故障、網(wǎng)絡(luò)過載或有意攻擊情況下,能否不死機(jī)、不崩潰,就是該軟件的魯棒性。

  • 可伸縮性(Scalability):可伸縮性是指當(dāng)用戶量和數(shù)據(jù)量增加時(shí),系統(tǒng)維持高服務(wù)質(zhì)量的能力。比如,當(dāng)并發(fā)量為1W時(shí),系統(tǒng)響應(yīng)時(shí)間為1秒,那如果并發(fā)量增加到100W時(shí),只要通過增加服務(wù)器數(shù)量,而無需對代碼進(jìn)行修改即可達(dá)到系統(tǒng)響應(yīng)時(shí)間依然為1秒,就說明該系統(tǒng)的可伸縮性高。

  • 互操作性(Interoperability):互操作性反映了本系統(tǒng)與其他系統(tǒng)交換數(shù)據(jù)和服務(wù)的難易程度。

  • 可擴(kuò)展性(Extensibility):也稱為靈活性,反映了系統(tǒng)應(yīng)對變化的能力。在軟件開發(fā)過程中,需求變更是常有的事,尤其在移動(dòng)互聯(lián)網(wǎng)時(shí)代,變化是非常頻繁的,也因此,可擴(kuò)展性是移動(dòng)互聯(lián)網(wǎng)產(chǎn)品重點(diǎn)考慮的質(zhì)量需求。

  • 可理解性(Understandability):可理解性是指開發(fā)人員通過源代碼和相關(guān)文檔,了解程序功能、結(jié)構(gòu)和運(yùn)行方式的難易程度。遵從好的開發(fā)規(guī)范一般都可以提高可理解性。另外,單一職責(zé)原則運(yùn)用得好,也能大大提高可理解性,所謂“簡單就是美”,簡單才容易理解。

  • 可測試性(Testability):簡單點(diǎn)說,可測試性就是測試和診斷軟件錯(cuò)誤的難易程度。比如進(jìn)行單元測試的難易程度。如果程序包含了復(fù)雜的處理邏輯、數(shù)據(jù)結(jié)構(gòu)、模塊關(guān)系,可測試性的設(shè)計(jì)更顯得尤為重要。

  • 可復(fù)用性(Reusability):可重用性表明了一個(gè)軟件組件可以在其他程序中使用的難易程度。一般需要將一個(gè)組件抽離成通用性的組件時(shí),對可復(fù)用性的要求就會(huì)比較高。

  • 可移植性(Portability):可移植性表明了將軟件系統(tǒng)從一個(gè)運(yùn)行環(huán)境轉(zhuǎn)移到另一個(gè)不同的運(yùn)行環(huán)境的難易程度。

  • 可維護(hù)性(Maintainability):可維護(hù)性是指理解、改正、改動(dòng)、改進(jìn)軟件的難易程度。我覺得,可維護(hù)性是保證一個(gè)軟件系統(tǒng)能夠長期生存的最重要的特性,沒有之一。對一個(gè)可維護(hù)性差的系統(tǒng),久而久之,不斷變得牽一發(fā)而動(dòng)全身,變得不可維護(hù),慢慢只能宣布滅亡。

理想情況下,誰都希望所有屬性都是高質(zhì)量的,但誰都清楚這是不可能的事。要提高更多質(zhì)量屬性,實(shí)現(xiàn)的難度更大,需要付出的成本更高。而且,不同質(zhì)量屬性之間還存在制約關(guān)系,比如,提高安全性,一般就會(huì)減低性能;提高了性能,還可能減低了可維護(hù)性。因此,在實(shí)際做架構(gòu)規(guī)劃時(shí),必須根據(jù)具體需求在各質(zhì)量屬性間權(quán)衡優(yōu)先級(jí)。

三、架構(gòu)思維

這里說的架構(gòu)思維是指進(jìn)行架構(gòu)設(shè)計(jì)時(shí)最高層級(jí)的思考方式,比如:面向過程、面向?qū)ο?、面向切面、面向服?wù)等。

1、面向過程(Procedure Oriented)

面向過程的設(shè)計(jì)思路就是將問題分解成一個(gè)個(gè)步驟,按照步驟一步步執(zhí)行之后,問題就解決了。每一個(gè)步驟就是一個(gè)子過程,也可以稱為一個(gè)模塊,子過程還可以繼續(xù)拆分成更多更細(xì)的子過程。因此,面向過程的設(shè)計(jì)核心就是過程分析、功能分解,一般采用自頂向下、逐步求精的分解方式。一個(gè)大的程序可以分解成多個(gè)子程序,子程序再分解成多個(gè)大模塊,大模塊再分解成多個(gè)小模塊,最終分解成一個(gè)個(gè)函數(shù)。

在此我想借用一個(gè)象棋對戰(zhàn)的例子,例子來源于一篇很老的文章:架構(gòu)師之路(4)---詳解面向?qū)ο?。以下是采用面向過程的設(shè)計(jì)思路分解的對戰(zhàn)流程圖:

回歸架構(gòu)本真:從規(guī)劃、思維到設(shè)計(jì),構(gòu)建堅(jiān)不可摧的架構(gòu)根基

將以上每個(gè)流程分別用函數(shù)實(shí)現(xiàn),問題就解決了。

面向過程的優(yōu)點(diǎn)主要有兩個(gè):一是流程清晰簡單;二是性能比較高。尤其是性能,這也是為什么至今很多單片機(jī)開發(fā)、驅(qū)動(dòng)程序開發(fā)、或其他與硬件相關(guān)的系統(tǒng)開發(fā)等對性能要求很高的軟硬件程序依然在用面向過程的方式進(jìn)行設(shè)計(jì)和開發(fā)。

面向過程的缺點(diǎn)也很明顯:一是主程序太重,主程序與模塊承擔(dān)的任務(wù)不均衡;二是函數(shù)不易擴(kuò)展,導(dǎo)致其可擴(kuò)展性、可復(fù)用性、可維護(hù)性相對都比較差;三是上下層級(jí)模塊之間的聯(lián)系太緊密,耦合高,所以模塊也難以復(fù)用。

2、面向?qū)ο?Object Oriented)

面向過程的思路是“怎么做”,關(guān)注于實(shí)現(xiàn)細(xì)節(jié);而面向?qū)ο蟮乃悸肥恰罢l來做”,關(guān)注于抽象的對象。對象的封裝、繼承和多態(tài)等特性,讓我們以更接近現(xiàn)實(shí)世界的方式來思考程序設(shè)計(jì)。面向?qū)ο笙啾让嫦蜻^程容易實(shí)現(xiàn)更好的分離,相應(yīng)地可擴(kuò)展性、可復(fù)用性、可維護(hù)性也會(huì)比較高,但同時(shí)會(huì)犧牲掉一些性能。不過,也因?yàn)橛布l(fā)展迅猛,所以犧牲的那點(diǎn)性能也不算什么了。

面向?qū)ο笤O(shè)計(jì)的難點(diǎn)在于抽象,從問題域中抽象出一個(gè)個(gè)對象,并找出它們之間的關(guān)系。好在有SOLID原則和一大堆設(shè)計(jì)模式指導(dǎo)我們?nèi)绾胃玫卦O(shè)計(jì)。也有領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的方法論指導(dǎo)我們怎么進(jìn)行領(lǐng)域建模。

還是象棋對戰(zhàn)的例子,用面向?qū)ο蟮脑O(shè)計(jì)思路,可以抽象出以下三種對象:

  • 棋手:負(fù)責(zé)行棋,紅黑兩方行為一致。

  • 棋盤:負(fù)責(zé)繪制棋盤畫面。

  • 裁判:負(fù)責(zé)判定吃子、犯規(guī)和輸贏等。

三者關(guān)系如下圖:

回歸架構(gòu)本真:從規(guī)劃、思維到設(shè)計(jì),構(gòu)建堅(jiān)不可摧的架構(gòu)根基

棋手對象行棋后,棋盤對象根據(jù)棋子布局的變化刷新棋盤畫面,裁判對象則對棋局進(jìn)行判定。

3、面向切面(Aspect Oriented)

面向切面,也就是AOP,是對面向?qū)ο蟮囊环N擴(kuò)展,為了彌補(bǔ)面向?qū)ο蟮木窒扌浴?/strong>面向?qū)ο笤O(shè)計(jì)主要是對業(yè)務(wù)領(lǐng)域進(jìn)行抽象封裝,但對于業(yè)務(wù)領(lǐng)域之外的內(nèi)容,比如日志記錄、權(quán)限檢查、事務(wù)支持等,在沒有AOP之前,只能將實(shí)現(xiàn)這些功能的代碼散布在所有對象層次中,但這些代碼與所散布的對象的核心業(yè)務(wù)功能是沒任何關(guān)系的。這種做法也導(dǎo)致了大量重復(fù)的代碼,而且難以復(fù)用。AOP就是為了解決這種問題而產(chǎn)生的,將這些與業(yè)務(wù)領(lǐng)域無關(guān)的部分分離出來,以橫切面的方式注入系統(tǒng),從而減少重復(fù)代碼、減低耦合度、增強(qiáng)擴(kuò)展性和維護(hù)性。

將日志記錄、權(quán)限檢查、事務(wù)支持等等使用橫切技術(shù)分別獨(dú)立成一個(gè)個(gè)服務(wù)模塊,這些模塊也稱為“橫切面”,這樣就可以將這些與業(yè)務(wù)無關(guān)的服務(wù)從業(yè)務(wù)核心中解耦出來,就可以將系統(tǒng)劃分為兩部分:業(yè)務(wù)核心和通用服務(wù)。業(yè)務(wù)核心依然采用面向?qū)ο蟮乃悸啡ピO(shè)計(jì),而通用服務(wù)則可以采用面向切面的思想來實(shí)現(xiàn)。

Spring就大量使用了AOP技術(shù),OkHttp的Interceptor也是AOP設(shè)計(jì)的一種實(shí)現(xiàn)。很多場景都可以使用AOP的思想去設(shè)計(jì),比如添加統(tǒng)一的Http Request Header,添加統(tǒng)一的登錄驗(yàn)證,添加統(tǒng)一的緩存,添加統(tǒng)一的錯(cuò)誤處理,等等,只要是通用的功能點(diǎn)基本都可以使用AOP的思想去設(shè)計(jì)和實(shí)現(xiàn)。

4、面向服務(wù)(Service Oriented)

不管是SOA還是現(xiàn)在流行的微服務(wù)架構(gòu),都是采用面向服務(wù)的思維方式。說到面向服務(wù),需要先了解一個(gè)概念:Monolith,也稱為單體架構(gòu)。在沒有SOA思想之前,軟件系統(tǒng)將所有功能整合成一個(gè)獨(dú)立的軟件包,然后部署在單一的平臺(tái)上。比如,在J2EE平臺(tái),一個(gè)軟件系統(tǒng)最終會(huì)打成一個(gè)包含所有功能的WAR包,然后部署到Web容器中。若要擴(kuò)展的話,則通過復(fù)制這個(gè)WAR包部署到多個(gè)Web容器來實(shí)現(xiàn)。這種方式,如果程序需要改動(dòng),不管多么微小的改動(dòng),都需要重新打包個(gè)新的WAR包,并替換掉所有Web容器的舊WAR包。

面向服務(wù)的架構(gòu)思想則是,將系統(tǒng)的不同功能分離成一個(gè)個(gè)單獨(dú)的應(yīng)用程序或組件,統(tǒng)稱為服務(wù),不同服務(wù)部署在不同容器中,不同服務(wù)之間通過一些輕量級(jí)的交互機(jī)制來通信,如HTTP,RPC等。這樣,相比單體架構(gòu),功能服務(wù)之間明顯是松耦合的,擴(kuò)展也會(huì)靈活很多。而且,不同服務(wù)還可以用不同編程語言實(shí)現(xiàn),部署到不同平臺(tái)。

不管是面向過程,面向?qū)ο?,面向切面,還是面向服務(wù),最本質(zhì)的區(qū)別還是在于看問題的角度不同。而在實(shí)際應(yīng)用中,也不會(huì)只使用一種架構(gòu)思維,而是綜合考慮的,系統(tǒng)的不同方面或不同層級(jí)可能會(huì)用不同的架構(gòu)思維去思考。比如,一個(gè)龐大的復(fù)雜系統(tǒng),整體上可能用面向服務(wù)的架構(gòu)思維去拆解各種服務(wù),業(yè)務(wù)核心方面的服務(wù)可能再用面向?qū)ο蟮募軜?gòu)思維進(jìn)行建模,通用功能服務(wù)還是用面向切面的架構(gòu)思維來設(shè)計(jì),事務(wù)流程當(dāng)然是采用面向過程的架構(gòu)思維最直觀。

四、架構(gòu)原則

架構(gòu)思維從面向過程,到現(xiàn)在的面向服務(wù),以后也不知道還會(huì)出現(xiàn)什么新的思維方式。但無論是何種思維方式,都存在一些共通性的架構(gòu)原則,可以指導(dǎo)我們?nèi)绾卧O(shè)計(jì)出一個(gè)合適的架構(gòu)。從另一方面來說,架構(gòu)設(shè)計(jì),不管是面向過程、面向?qū)ο?、面向切面,還是面向服務(wù),無一例外,主要都是在對復(fù)雜的系統(tǒng)進(jìn)行分解。那么,相應(yīng)地,就需要思考三個(gè)問題:分解為哪些?如何分解?分解到什么程度?相對應(yīng)地,有三個(gè)重要原則可以分別為解答這三個(gè)問題提供指引。

1、關(guān)注點(diǎn)分離原則

關(guān)注點(diǎn)分離原則主要就是為了解決將復(fù)雜系統(tǒng)分解為哪些部分的問題,分解出來的部分就是關(guān)注點(diǎn)。過程、對象、切面、服務(wù),只是分解的角度(也是關(guān)注點(diǎn))不同而已。將復(fù)雜的問題根據(jù)不同的關(guān)注點(diǎn)分解為多個(gè)相對簡單的問題,再對每個(gè)簡單的問題進(jìn)行分別處理,這就是關(guān)注點(diǎn)分離。分離之后,各個(gè)關(guān)注點(diǎn)相對獨(dú)立,每個(gè)關(guān)注點(diǎn)的變化基本不會(huì)影響到其他的關(guān)注點(diǎn),即使需要改變,改變的部分也很小。需要擴(kuò)展時(shí),影響也將會(huì)最小化。

關(guān)注點(diǎn)分離,最難的在于如何識(shí)別出有哪些關(guān)注點(diǎn)。要識(shí)別出有哪些關(guān)注點(diǎn),需要將復(fù)雜系統(tǒng)不同的方方面面抽象成一個(gè)個(gè)具有清晰明確的邊界的概念模型,或?yàn)椤皩ο蟆?,或?yàn)椤敖M件”,或“切面”,或“服務(wù)”,以將復(fù)雜問題分解為一個(gè)個(gè)相對簡單的問題。

從不同維度,可以有不同的分離方案。除了上面提到的面向過程、面向?qū)ο?、面向切面、面向服?wù)等思維角度之外,還有如下圖所示的其他幾種不同維度,該圖引自《軟件架構(gòu)設(shè)計(jì)》一書中的【2.1.1 關(guān)注點(diǎn)分離之道】一節(jié):

回歸架構(gòu)本真:從規(guī)劃、思維到設(shè)計(jì),構(gòu)建堅(jiān)不可摧的架構(gòu)根基

上圖分別從功能職責(zé)、通用性、大小粒度的不同維度進(jìn)行分離。從職責(zé)維度進(jìn)行分離,就可以分為三層架構(gòu):展現(xiàn)層、業(yè)務(wù)層、數(shù)據(jù)層,相應(yīng)的關(guān)注點(diǎn)就是:數(shù)據(jù)展示、數(shù)據(jù)加工、數(shù)據(jù)管理。另外,數(shù)據(jù)層還可以再分離為網(wǎng)絡(luò)層和緩存層。從通用性維度來看,就可以分離出技術(shù)通用部分、領(lǐng)域通用部分、特定應(yīng)用部分。一般,使用框架技術(shù)就可以用于分離各種不同的通用部分。從大小粒度的維度考慮,無非就是將復(fù)雜系統(tǒng)分離為各個(gè)子系統(tǒng),再分離為不同模塊,再細(xì)分到不同類。

在實(shí)際應(yīng)用中,并不會(huì)只采用一種維度,而是多種維度綜合考慮,不同部分采用不同維度的分離方案。比如,也許,整體上按職責(zé)分離為多層架構(gòu),然后,在某些層級(jí)根據(jù)大小粒度再進(jìn)行分離,例如將業(yè)務(wù)層按照不同業(yè)務(wù)模塊進(jìn)行分離。另外,也會(huì)將不同的通用部分進(jìn)行分離,例如可將技術(shù)通用部分的日志記錄、領(lǐng)域通用部分的權(quán)限檢查分別分離出來。

2、高內(nèi)聚低耦合原則

系統(tǒng)應(yīng)該如何分解?或者說關(guān)注點(diǎn)應(yīng)該如何分離?高內(nèi)聚低耦合原則就可以為該問題提供設(shè)計(jì)指引。

內(nèi)聚是指模塊內(nèi)部的功能和元素之間的緊密程度,而耦合則是指模塊與模塊之間的關(guān)聯(lián)程度。

內(nèi)聚可分為好多種:功能內(nèi)聚、順序內(nèi)聚、通信內(nèi)聚、過程內(nèi)聚、時(shí)間內(nèi)聚、邏輯內(nèi)聚、偶然內(nèi)聚。功能內(nèi)聚是最強(qiáng)最好的內(nèi)聚,模塊內(nèi)各元素共同協(xié)作完成一個(gè)單一的功能,這些元素緊密聯(lián)系、缺一不可。順序內(nèi)聚則是指,模塊中各個(gè)處理元素和同一個(gè)功能密切相關(guān),而且這些處理必須順序執(zhí)行,通常前一個(gè)處理元素的輸出時(shí)后一個(gè)處理元素的輸入。順序內(nèi)聚的內(nèi)聚度也比較高,但相比功能內(nèi)聚,缺點(diǎn)就是可維護(hù)性相對差些。偶然內(nèi)聚則是最弱的內(nèi)聚,模塊內(nèi)的各元素之間沒有任何聯(lián)系,只是偶然地被湊到一起。

耦合也分為好多種:非直接耦合、數(shù)據(jù)耦合、標(biāo)記耦合、控制耦合、外部耦合、公共耦合、內(nèi)容耦合。非直接耦合表示兩個(gè)模塊直接沒有直接關(guān)系,它們之間的聯(lián)系完全是通過主模塊的控制和調(diào)用來實(shí)現(xiàn)的,其耦合度是最弱的,模塊獨(dú)立性最強(qiáng)。數(shù)據(jù)耦合表示調(diào)用模塊和被調(diào)用模塊之間只傳遞簡單的數(shù)據(jù)項(xiàng)參數(shù),相當(dāng)于高級(jí)語言中的值傳遞。標(biāo)記耦合也稱為特征耦合,表示調(diào)用模塊和被調(diào)用模塊之間傳遞的不是簡單數(shù)據(jù),而是數(shù)據(jù)結(jié)構(gòu),像高級(jí)語言中的數(shù)據(jù)名、記錄名和文件名等數(shù)據(jù)結(jié)果,這些名字即為標(biāo)記,其實(shí)傳遞的是地址。控制耦合則表示模塊之間傳遞的不是數(shù)據(jù)信息,而是控制信息例如標(biāo)志、開關(guān)等,一個(gè)模塊控制了另一個(gè)模塊的功能。外部耦合則是指一組模塊都訪問同一全局簡單變量,而且不通過參數(shù)表傳遞該全局變量的信息。內(nèi)容耦合則是一個(gè)模塊直接訪問另一模塊的內(nèi)容,這是最強(qiáng)的耦合。

  • 高內(nèi)聚的設(shè)計(jì)原則是說:一個(gè)模塊只完成一個(gè)單一的功能,盡可能使模塊達(dá)到功能內(nèi)聚。

  • 低耦合的設(shè)計(jì)原則是說:若模塊間必須存在耦合,應(yīng)盡量使用數(shù)據(jù)耦合,少用控制耦合,慎用或有控制地使用公共耦合,并限制公共耦合的范圍,盡量避免內(nèi)容耦合。

3、適度設(shè)計(jì)

適度設(shè)計(jì)原則關(guān)注的就是系統(tǒng)分解到什么程度的問題。適度設(shè)計(jì)就是指設(shè)計(jì)不要過度,也不要不足。那么,怎樣才算設(shè)計(jì)過度?怎樣才算設(shè)計(jì)不足?一句話,設(shè)計(jì)過度就是想太多,設(shè)計(jì)不足就是想太少。感覺好虛,是吧?我也這么覺得。因?yàn)?,如何判斷一個(gè)設(shè)計(jì)是否過度或不足,并沒有標(biāo)準(zhǔn)的可量化指標(biāo)。因此,設(shè)計(jì)是否適度,更多在于主觀的判斷。而如何避免設(shè)計(jì)過度或不足,更多的也在于個(gè)人經(jīng)驗(yàn)積累所形成的直覺。

設(shè)計(jì)不足相對還比較容易判斷,導(dǎo)致設(shè)計(jì)不足的原因主要有兩個(gè):一是因?yàn)樾率值脑O(shè)計(jì)經(jīng)驗(yàn)不足而導(dǎo)致;二是因?yàn)橐晃蹲非罂焖賹?shí)現(xiàn)產(chǎn)品功能而跳過或大幅度減少了設(shè)計(jì)而導(dǎo)致。

也有些設(shè)計(jì)過度比較明顯的例子,比如Uncle Bob提出的Clean架構(gòu),每個(gè)關(guān)注點(diǎn)都有著清晰明確的邊界,架構(gòu)真的很清晰,可維護(hù)性、可測試性都非常不錯(cuò),高內(nèi)聚低耦合。但是,如果將其應(yīng)用到一個(gè)只有兩三個(gè)開發(fā)人員的小團(tuán)隊(duì)的小項(xiàng)目中,就會(huì)明顯發(fā)現(xiàn)代碼量大而且復(fù)雜,每需要添加一個(gè)小功能,卻需要編寫大量代碼。這對一個(gè)小團(tuán)隊(duì)小項(xiàng)目來說,明顯不適合。Clean架構(gòu)比較適用于人員較多的團(tuán)隊(duì),和中大型項(xiàng)目。

因此,判斷設(shè)計(jì)是否適度,不能脫離團(tuán)隊(duì)和項(xiàng)目的現(xiàn)狀。另外,還有其他現(xiàn)狀因素,包括各種商業(yè)需求、功能需求和質(zhì)量需求。大部分情況下,形成過度設(shè)計(jì)的原因在于:一是過多地考慮了未來可能發(fā)生的變化;二是為了追求設(shè)計(jì)而設(shè)計(jì)。適度設(shè)計(jì),首先應(yīng)該著眼于當(dāng)下,當(dāng)下的需求、當(dāng)下的開發(fā)成本、當(dāng)下的人員和項(xiàng)目現(xiàn)狀;其次才是適當(dāng)考慮如何應(yīng)對未來的變化。對于未來的變化,也不是任何可能都要考慮,只需考慮在可預(yù)見的未來里有非常大的幾率會(huì)發(fā)生的變化即可,這個(gè)非常大的幾率可以達(dá)到90%以上。比如,已經(jīng)確定要實(shí)現(xiàn)的需求,只是因?yàn)閮?yōu)先級(jí)問題而稍微延后;比如,已經(jīng)確定的人員擴(kuò)充計(jì)劃;比如,雙11要搞活動(dòng),交易量將會(huì)激增;等等。

也就是說,適度設(shè)計(jì)的原則,可以總結(jié)為:設(shè)計(jì)應(yīng)該優(yōu)先滿足當(dāng)前確定的需求,再滿足可預(yù)見未來里幾乎可以確定會(huì)發(fā)生的需求。只滿足當(dāng)前需求而不考慮未來,就容易導(dǎo)致設(shè)計(jì)不足;而過多地考慮未來可能發(fā)生的需求,就容易導(dǎo)致設(shè)計(jì)過度。因此,適度設(shè)計(jì)需要在當(dāng)前需求和未來需求之間做好平衡,而我覺得只考慮當(dāng)前需求和未來幾乎確定會(huì)發(fā)生的需求是最好的平衡點(diǎn)。

作者介紹 李紀(jì)鋼

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多