偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

軟件開(kāi)發(fā)必修課:你該知道的GRASP職責(zé)分配模式

開(kāi)發(fā) 開(kāi)發(fā)工具
軟件在本質(zhì)上是復(fù)雜的,軟件本身的復(fù)雜性在于除了要解決問(wèn)題域,還要解決非功能性需求和軟件域特有問(wèn)題:安全性、可用性、可維護(hù)性、可擴(kuò)展性、性能、一致性、容錯(cuò)性、穩(wěn)定性、可重用性、冪等、兼容等等,軟件開(kāi)發(fā)者的任務(wù)就是制造“簡(jiǎn)單”的假象。

軟件在本質(zhì)上是復(fù)雜的,軟件本身的復(fù)雜性在于除了要解決問(wèn)題域,還要解決非功能性需求和軟件域特有問(wèn)題:安全性、可用性、可維護(hù)性、可擴(kuò)展性、性能、一致性、容錯(cuò)性、穩(wěn)定性、可重用性、冪等、兼容等等,軟件開(kāi)發(fā)者的任務(wù)就是制造“簡(jiǎn)單”的假象。如何組織復(fù)雜的系統(tǒng)?把復(fù)雜的事物分解到不同的層次中,層次代表了不同級(jí)別的抽象,一層構(gòu)建于另一層之上,每一層都對(duì)上層屏蔽內(nèi)部復(fù)雜度。

一 為什么使用RDD?

在RDD中,我們認(rèn)為“軟件對(duì)象具有職責(zé)”,這個(gè)定義很符合人在社會(huì)群體中分工協(xié)作的方式,軟件也是人編寫的,所以根據(jù)職責(zé)思考設(shè)計(jì)的軟件系統(tǒng)符合人的行為習(xí)慣,同時(shí)更易于理解和管理。在微服務(wù)架構(gòu)中不同系統(tǒng)由不同的組織和人負(fù)責(zé),把系統(tǒng)當(dāng)作對(duì)象(人),系統(tǒng)提供的接口就是對(duì)象(人)的職責(zé)。

職責(zé)驅(qū)動(dòng)設(shè)計(jì)的核心是考慮怎樣給對(duì)象分配職責(zé),其適用于大到系統(tǒng)、小到對(duì)象等任何規(guī)模的軟件。職責(zé)分配的本質(zhì)是分工,勞動(dòng)分工是勞動(dòng)生產(chǎn)率提高的主要原因。

  • 熟練度的提高,專注于某個(gè)領(lǐng)域(降低復(fù)雜度)。
  • 時(shí)間的節(jié)約,同一個(gè)人在不同工作來(lái)回切換需要耗費(fèi)大量時(shí)間。
  • 人工發(fā)明的機(jī)器和應(yīng)用(特定領(lǐng)域的工具)。

二 如何給對(duì)象(元素)分配職責(zé)?

分配職責(zé)應(yīng)當(dāng)從清晰的描述職責(zé)開(kāi)始,對(duì)于軟件領(lǐng)域?qū)ο髞?lái)說(shuō),領(lǐng)域模型描述了領(lǐng)域?qū)ο蟮膶傩院完P(guān)聯(lián),對(duì)應(yīng)類的屬性和引用,用例模型包含一系列的行為活動(dòng),對(duì)應(yīng)類的方法。領(lǐng)域模型創(chuàng)建方式可參考《UML和模式應(yīng)用》、UDD、DDD。

使用GRASP(General Responsibility Assignment Software Patterns)模式分配職責(zé),GRASP是通用職責(zé)分配模式,是對(duì)一些基本的職責(zé)分配原則進(jìn)行了命名和描述,共9種模式(一些GRASP原則是對(duì)其他原則和設(shè)計(jì)模式的歸納,設(shè)計(jì)模式有上百種,只是記住GoF 23種設(shè)計(jì)模式就已經(jīng)很困難了,更別提還要記住每種模式的細(xì)節(jié),因此需要對(duì)設(shè)計(jì)模式進(jìn)行有效的歸類。GRASP中的原則描述了模式的本質(zhì),除了有助加速設(shè)計(jì)模式學(xué)習(xí)之外,對(duì)發(fā)現(xiàn)現(xiàn)有設(shè)計(jì)存在的問(wèn)題也更有效,這就是歸納的價(jià)值)。

當(dāng)談?wù)摰婉詈?、高?nèi)聚時(shí),我們具體是在談什么?問(wèn)題不在于耦合度高、內(nèi)聚性低,而是在于其產(chǎn)生的負(fù)面影響,負(fù)面影響往往是在發(fā)生變化時(shí)體現(xiàn)出來(lái)的,這些負(fù)面影響會(huì)影響到我們開(kāi)發(fā)的效率、穩(wěn)定性、可維護(hù)性、可擴(kuò)展性、可復(fù)用性等等,整個(gè)GRASP的核心是如何防止變異(變化)。

在學(xué)習(xí)過(guò)程中發(fā)現(xiàn)GRASP缺少結(jié)構(gòu)化的展示歸納結(jié)果,通過(guò)我自己的理解把開(kāi)發(fā)中常用的GoF設(shè)計(jì)模式、面向?qū)ο笤O(shè)計(jì)原則、架構(gòu)設(shè)計(jì)原則和GRASP進(jìn)行關(guān)聯(lián):

 

??

??


注:這個(gè)圖可能總結(jié)的還不夠準(zhǔn)確,正在逐步學(xué)習(xí)修改。

 

 

三 GRASP職責(zé)分配模式

1 防止變異

該模式基本等同于信息隱藏和開(kāi)閉原則。如何做到在不修改原來(lái)功能的前提下對(duì)變化的部分進(jìn)行擴(kuò)展?識(shí)別不穩(wěn)定因素是特別困難的,也決定了我們能否做出符合開(kāi)閉原則的設(shè)計(jì)。

問(wèn)題:如何設(shè)計(jì)對(duì)象、子系統(tǒng)和系統(tǒng),使其內(nèi)部的變化或不穩(wěn)定性不會(huì)對(duì)其他元素產(chǎn)生不良影響。

解決方案:識(shí)別預(yù)計(jì)變化或不穩(wěn)定之處,分配職責(zé)用以在這些變化之外創(chuàng)建穩(wěn)定接口。

相關(guān)原則和模式:

  • GRASP:間接性、多態(tài)
  • GoF:大量模式
  • 其他:接口、數(shù)據(jù)封裝

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

耦合是對(duì)某元素與其他元素之間的連接、感知和依賴程度的度量,內(nèi)聚是對(duì)元素職責(zé)的相關(guān)性和集中度的度量(這里的元素指類、系統(tǒng)、子系統(tǒng)等等),耦合和內(nèi)聚是從不同角度看待問(wèn)題,他們互相依賴的互相影響的(以下兩點(diǎn)也可以反過(guò)來(lái)說(shuō)):

  • 內(nèi)聚過(guò)低,相關(guān)功能分散在不同模塊中,需要增加額外的耦合使這些功能聚合在一起,發(fā)生變更時(shí)影響多個(gè)模塊。
  • 內(nèi)聚過(guò)高,不相關(guān)的功能聚集在一個(gè)模塊中,耦合度高,發(fā)生變更時(shí)會(huì)產(chǎn)生意想不到的影響。

??

??

 

低耦合

耦合是對(duì)某元素與其他元素之間的連接、感知和依賴程度的度量。這里的元素指類、系統(tǒng)、子系統(tǒng)等等。

問(wèn)題:怎樣降低依賴性,減少變化帶來(lái)的影響,提高重用性?

解決方案:分配職責(zé),使耦合盡可能低。利用這一原則評(píng)估可選方案。

相關(guān)模式或原則:

  • GRASP:防止變異

注意:耦合不能脫離專家、高內(nèi)聚等其他原則獨(dú)立考慮。

緊密耦合的系統(tǒng)在開(kāi)發(fā)階段有以下的缺點(diǎn):

  • 一個(gè)模塊的修改會(huì)產(chǎn)生漣漪效應(yīng),其他模塊也需隨之修改(通常是內(nèi)聚低引起的)。
  • 由于模塊之間的相依性,模塊的組合會(huì)需要更多的精力及時(shí)間,可復(fù)用性低(通常是耦合高引起的)。

解讀:耦合表示元素之間存在依賴,當(dāng)談?wù)摗榜詈细摺睍r(shí),我們具體是在談?wù)撌裁茨?是依賴產(chǎn)生的負(fù)面影響,所以低耦合的核心是解決不良依賴。高低是度量并不是評(píng)判耦合結(jié)果好壞的標(biāo)準(zhǔn),使用“不良耦合”、“松耦合”描述的更為準(zhǔn)確。不良耦合產(chǎn)生的負(fù)面影響主要有兩點(diǎn):

  • 依賴關(guān)系本身錯(cuò)綜復(fù)雜難以維護(hù)和理解,很容易產(chǎn)生遺漏和問(wèn)題(這點(diǎn)針對(duì)人,人處理復(fù)雜性事物時(shí)能力是局限的)。
  • 與不穩(wěn)定元素產(chǎn)生依賴時(shí)很容易受到變化的影響(通常無(wú)法避免不依賴)。

那么如何做呢?先對(duì)依賴關(guān)系的好壞進(jìn)行評(píng)估:依賴方式、依賴方向、依賴鏈路。

??

??

 

方向:

  • 雙向依賴(差)
  • 相互依賴的兩個(gè)元素不能獨(dú)立行動(dòng),在微服務(wù)系統(tǒng)架構(gòu)的系統(tǒng)中類級(jí)別不會(huì)產(chǎn)生特別復(fù)雜的問(wèn)題,但是在模塊 or 系統(tǒng)級(jí)別就特別容易受到變化帶來(lái)的影響。
  • 舉例:A <-> B,A調(diào)用B的b接口,B的b接口依賴A的a接口,如果a b接口都要變更,兩個(gè)系統(tǒng)如何發(fā)布?A依賴B先發(fā)布,B也依賴A先發(fā)布,相互依賴的兩個(gè)元素不能獨(dú)立行動(dòng)。
  • 循環(huán)依賴(更差)
  • 循環(huán)依賴比雙向依賴的的鏈路更長(zhǎng),影響的范圍更大。
  • 單向依賴(好)

鏈路:

  • 深度
  • B調(diào)用A.getC().getD().getE().getF() 獲取到F。
  • 廣度
  • 在鏈路變寬的過(guò)程中不加以約束和管理很容易產(chǎn)生大雜燴的元素,也很容易產(chǎn)生雙向和循環(huán)依賴。

方式:

  • 內(nèi)容耦合(高)
  • 當(dāng)一個(gè)模塊直接使用另一個(gè)模塊的內(nèi)部數(shù)據(jù),或通過(guò)非正常入口而轉(zhuǎn)入另一個(gè)模塊內(nèi)部。
  • 共享耦合/公共耦合(高)
  • 指通過(guò)一個(gè)公共數(shù)據(jù)環(huán)境相互作用的那些模塊間的耦合。
  • 公共耦合的復(fù)雜程度隨耦合模塊的個(gè)數(shù)增加而增加。
  • 控制耦合(中)
  • 指一個(gè)模塊調(diào)用另一個(gè)模塊時(shí),傳遞的是控制變量(如開(kāi)關(guān)、標(biāo)志等),被調(diào)模塊通過(guò)該控制變量的值有選擇地執(zhí)行塊內(nèi)某一功能;
  • 特征耦合/標(biāo)記耦合(中)
  • 指幾個(gè)模塊共享一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu),如高級(jí)語(yǔ)言中的數(shù)組名、記錄名、文件名等這些名字即標(biāo)記,其實(shí)傳遞的是這個(gè)數(shù)據(jù)結(jié)構(gòu)的地址;
  • 數(shù)據(jù)耦合(低)
  • 指模塊借由傳入值共享數(shù)據(jù),每一個(gè)數(shù)據(jù)都是最基本的數(shù)據(jù),而且只分享這些數(shù)據(jù)(例如傳遞一個(gè)整數(shù)給計(jì)算平方根的函數(shù))。
  • 非直接耦合(低)
  • 兩個(gè)模塊之間沒(méi)有直接關(guān)系,它們之間的聯(lián)系完全是通過(guò)主模塊的控制和調(diào)用來(lái)實(shí)現(xiàn)的。耦合度最弱,模塊獨(dú)立性最強(qiáng)。
  • 無(wú)耦合(無(wú))
  • 模塊完全不和其他模塊交換信息。

解決不良依賴:

  • 管理復(fù)雜的依賴關(guān)系
  • 依賴方向:使用單向依賴,去除或弱化雙向依賴,不使用循環(huán)依賴。
  • 依賴鏈路:遵守最少認(rèn)知原則。
  • 依賴方式:盡量使用數(shù)據(jù)耦合,少用控制和特征耦合,控制公共耦合的范圍,不使用內(nèi)容耦合,如果依賴的對(duì)象不穩(wěn)定使用非直接耦合來(lái)弱化耦合緊密程度。
  • 分配正確的職責(zé)減少不必要的依賴:專家、創(chuàng)建者。
  • 通過(guò)其他原則和模式減少不穩(wěn)定元素帶來(lái)的影響:高內(nèi)聚、純虛構(gòu)、控制器、多態(tài)、間接性、最少認(rèn)知。

高內(nèi)聚

內(nèi)聚是對(duì)元素職責(zé)的相關(guān)性和集中度的度量。

問(wèn)題:怎么樣保持對(duì)象是有重點(diǎn)的、可理解的、可維護(hù)的,并且能夠支持低耦合?

解決方案:按照相關(guān)性分配職責(zé),可保持較高的內(nèi)聚。

優(yōu)點(diǎn):

  • 分解后的元素更加簡(jiǎn)單易于理解和維護(hù)。
  • 按照相關(guān)性拆分可以提高重用性。

相關(guān)原則和模式:?jiǎn)我宦氊?zé)原則、關(guān)注點(diǎn)分離、模塊化。

低內(nèi)聚的缺點(diǎn):內(nèi)聚性較低的類要做許多不相關(guān)的工作,或需要完成大量的工作,這樣的類會(huì)導(dǎo)致以下問(wèn)題:

  • 難以理解
  • 難以復(fù)用
  • 難以維護(hù)
  • 經(jīng)常會(huì)受到變化影響

??

??

 

例子:A的變更影響從3個(gè)模塊變?yōu)?個(gè)。

??

??

 

小結(jié)

通過(guò)結(jié)構(gòu)化管理來(lái)保持低耦合、高內(nèi)聚。

??

??

 

3 創(chuàng)建者

創(chuàng)建者指導(dǎo)我們分配那些與創(chuàng)建對(duì)象有關(guān)的職責(zé)。如此選擇是為了保持低耦合。

問(wèn)題:誰(shuí)應(yīng)該負(fù)責(zé)創(chuàng)建某類的新實(shí)例?

解決方案:滿足以下條件之一時(shí),將創(chuàng)建類A的職責(zé)分配給類B(當(dāng)滿足1條以上時(shí),通常首選包含或聚合)。

  • B“包含”或聚合A。
  • B記錄A。
  • B頻繁使用A。
  • B具有A的初始化數(shù)據(jù),該數(shù)據(jù)將在創(chuàng)建時(shí)傳遞給A。

優(yōu)點(diǎn):支持低耦合,因?yàn)閯?chuàng)建者和被創(chuàng)建者已經(jīng)存在關(guān)聯(lián),所以這種方式不會(huì)增加耦合性。

相關(guān)模式或原則:

  • GRASP:低耦合
  • GoF:具體工廠、抽象工廠
  • 其他:整體-部分

注:包含(作者在這里標(biāo)注了“”,因?yàn)榘趗ml是表達(dá)用例關(guān)系的,用來(lái)說(shuō)明對(duì)象關(guān)系也可以)、聚合、整體-部分 看UML定義;包含強(qiáng)調(diào)了強(qiáng)依賴(A是B的子集,A屬于B,缺少了A時(shí)B不是整體),聚合是弱依賴(B由A組成,A不屬于B)。

例子:

??

??

 

  • Order包含Goods(Order脫離Goods就失去了完整性,沒(méi)有存在的意義)。
  • Order記錄相關(guān)的Goods。
  • Goods初始化數(shù)據(jù):
  • 情況一:只需要訂單上的Goods數(shù)據(jù),這種情況Order具有Goods的初始化數(shù)據(jù)。
  • 情況二:訂單上的Goods數(shù)據(jù)不完整,這種情況Order只有Goods初始化數(shù)據(jù)的一小部分,Order不能做為創(chuàng)建者。

4 信息專家(or 專家)

“信息”不單指數(shù)據(jù)。

問(wèn)題:給對(duì)象分配職責(zé)的基本原則是什么?

解決方案:把職責(zé)分配給信息專家,它具有實(shí)現(xiàn)這個(gè)職責(zé)所必需的信息

優(yōu)點(diǎn):

  • 對(duì)象使用自身信息來(lái)完成任務(wù),所以信息的封裝性得以維持,因此支持了低耦合(至少不會(huì)增加耦合性)。
  • 行為分布在那些具有所需信息的類之間,這樣功能更集中,因此支持了高內(nèi)聚。

相關(guān)模式或原則:

  • GRASP:低耦合、高內(nèi)聚

注意:和“關(guān)注點(diǎn)分離”一起使用使得對(duì)象進(jìn)一步內(nèi)聚,從而達(dá)到高內(nèi)聚,也能降低耦合。

舉例:獲取所有買的商品總金額,Order和Goods是一對(duì)多的關(guān)系。

??

??

 

分析:Order本身關(guān)聯(lián)了Goods,并且理解Goods的結(jié)構(gòu)。在圖例中Client通過(guò)Order獲取了Goods并做了邏輯運(yùn)算得出商品總金額,這種做法產(chǎn)生了不必要的依賴增加了耦合數(shù)量,商品總金額計(jì)算的職責(zé)由Order承擔(dān)最合適。

??

??

 

延伸:在某些情況下,該方案并不合適,通常是由于耦合與內(nèi)聚問(wèn)題產(chǎn)生的,如:誰(shuí)應(yīng)該把對(duì)象A存入數(shù)據(jù)庫(kù)?按照原則每個(gè)類都應(yīng)該具有把自己持久化的能力。

5 純虛構(gòu)

為了保持良好的耦合和內(nèi)聚,捏造業(yè)務(wù)上不存在的對(duì)象來(lái)承擔(dān)職責(zé)。

問(wèn)題:當(dāng)你并不想違背高內(nèi)聚和低耦合或者其他目標(biāo),但是基于專家模式所提供的方案又不合適時(shí),哪些對(duì)象應(yīng)該承擔(dān)這一職責(zé)?

解決方案:對(duì)人為制造的類分配一組高內(nèi)聚的職責(zé),該類并不代表問(wèn)題領(lǐng)域的概念--虛構(gòu)的事物,用以支持高內(nèi)聚、低耦合和復(fù)用。

優(yōu)點(diǎn):

  • 支持高內(nèi)聚,因?yàn)槁氊?zé)被解析為細(xì)粒度的類,這種類只著重于極為特定的一組相關(guān)任務(wù)。
  • 增加了潛在的復(fù)用性。

相關(guān)原則和模式:

  • GRASP:低耦合、高內(nèi)聚。
  • 通常接納本來(lái)是基于專家模式所分配給領(lǐng)域類的職責(zé)。
  • 所有GoF設(shè)計(jì)模式都是純虛構(gòu),事實(shí)上所有其他設(shè)計(jì)模式也都是純虛構(gòu)。

舉例:計(jì)算商品總數(shù)量。根據(jù)專家模式計(jì)算商品總數(shù)量的職責(zé)也應(yīng)該是分配給Order,照這樣分配下去商品相關(guān)的還會(huì)有:總重量、總體積、總XX,這時(shí)Order的職責(zé)就會(huì)越來(lái)越多也可能會(huì)產(chǎn)生額外的耦合,通過(guò)純虛構(gòu)對(duì)象把這些職責(zé)分配出去能夠得到更好的設(shè)計(jì)。

??

??

 

通過(guò)虛構(gòu)對(duì)象GoodsItems承擔(dān)和商品聚合計(jì)算相關(guān)的職責(zé)。

延伸:經(jīng)常發(fā)現(xiàn)代碼中會(huì)使用Util、Handler、Service這樣的虛構(gòu)類,缺點(diǎn)是這些類通常是單例并共用的,這些虛構(gòu)類的職責(zé)會(huì)越來(lái)越多(一個(gè)Util類2000行代碼),創(chuàng)建和業(yè)務(wù)更相近的虛構(gòu)對(duì)象才能便于理解和管理耦合關(guān)系。

6 控制器

解決方案:把職責(zé)分配給能代表以下選擇之一的類:

  • 代表整個(gè)“系統(tǒng)”、“根對(duì)象”、運(yùn)行軟件的設(shè)備或主要子系統(tǒng),這些是外觀控制器的所有變體。
  • 代表用例場(chǎng)景,在該場(chǎng)景中發(fā)生系統(tǒng)事件。

相關(guān)模式:

  • GRASP:純虛構(gòu)
  • GoF:命令、外觀
  • 其他:層

控制器的核心是提供一個(gè)統(tǒng)一入口,避免客戶對(duì)元素內(nèi)部進(jìn)行耦合,很好的維護(hù)了邊界:

  • api層
  • 根對(duì)象
  • 接口

7 多態(tài)

問(wèn)題:如何處理給予類型的選擇?如何創(chuàng)建可插拔的軟件構(gòu)件?

解決方案:當(dāng)相關(guān)選擇或行為隨類型有所不同時(shí),使用多態(tài)操作為變化的行為類型分配職責(zé)。

優(yōu)點(diǎn):可擴(kuò)展性強(qiáng),同時(shí)不影響客戶。

相關(guān)原則和模式:

  • GRASP:防止變異
  • GoF:大量模式

訂單退款時(shí)需要計(jì)算出用戶退款金額和商戶扣款金額,在沒(méi)有新零售業(yè)務(wù)進(jìn)來(lái)之前直接使用計(jì)算服務(wù)返回的數(shù)據(jù)結(jié)構(gòu),新零售進(jìn)來(lái)后數(shù)據(jù)結(jié)構(gòu)未統(tǒng)一,需要進(jìn)行適配,實(shí)現(xiàn)多態(tài)后的代碼擴(kuò)展性很強(qiáng)。

??

??

 

在微服務(wù)架構(gòu)中,比較復(fù)雜的多態(tài)問(wèn)題通常會(huì)選擇增加一層去解決,如:支付網(wǎng)關(guān)、交付網(wǎng)關(guān)。

8 間接性

計(jì)算機(jī)學(xué)科中的大多數(shù)問(wèn)題都可以通過(guò)增加一層解決,如果不行再加一層。反過(guò)來(lái)大多數(shù)性能問(wèn)題都可以通過(guò)去掉一層來(lái)解決。

問(wèn)題:為了避免兩個(gè)或多個(gè)事物之間直接耦合,應(yīng)該如何分配職責(zé)?

解決方案:將職責(zé)分配給中介對(duì)象,使其作為其他構(gòu)建或服務(wù)之間的媒介,以避免他們之間的直接耦合。

優(yōu)點(diǎn):實(shí)現(xiàn)了構(gòu)件之間的低耦合。

相關(guān)原則和模式:

  • GRASP:防止變異、低耦合、大量間接性中介都是純虛構(gòu)
  • GoF:大量模式

注意:間接性通常用來(lái)支持防止變異。

四 架構(gòu)模式

除了職責(zé)分配原則,還需要一些架構(gòu)模式幫助我們更好的落地。

1 分層架構(gòu)

在分布式系統(tǒng)中系統(tǒng)是獨(dú)立存在的,可以單獨(dú)變更而不對(duì)其他系統(tǒng)產(chǎn)生影響,但是隨著業(yè)務(wù)整體復(fù)雜度的提升也帶來(lái)了一些負(fù)面影響:由于整體被分解成大量獨(dú)立的系統(tǒng),隨著復(fù)雜度提升系統(tǒng)之間的依賴關(guān)系會(huì)變的錯(cuò)綜復(fù)雜,某個(gè)系統(tǒng)的變更會(huì)影響其他系統(tǒng),同時(shí)也會(huì)產(chǎn)生意想不到的問(wèn)題,效率也隨之下降。這時(shí)就需要重新對(duì)分布式系統(tǒng)的邏輯架構(gòu)做設(shè)計(jì),以解決系統(tǒng)間的不良耦合和內(nèi)聚,從而提效。

分層架構(gòu)是非常實(shí)用和常見(jiàn)的方式,TCP/IP、HTTP、操作系統(tǒng)等等都運(yùn)用了分層,分層的本質(zhì)很簡(jiǎn)單:通過(guò)分離關(guān)注點(diǎn),達(dá)到高內(nèi)聚;通過(guò)向下依賴、拒絕循環(huán)依賴、使用接口,達(dá)到低耦合。

??

??

 

分層架構(gòu)也是存在缺點(diǎn)的:按照分層架構(gòu)定義消息消費(fèi)應(yīng)該在基礎(chǔ)設(shè)施層,但是消息消費(fèi)是為了執(zhí)行某個(gè)業(yè)務(wù)邏輯,這樣就需要依賴應(yīng)用層 或 領(lǐng)域?qū)?,如果真的這樣寫就會(huì)出現(xiàn)循環(huán)依賴問(wèn)題。通過(guò)依賴倒置可以解決依賴問(wèn)題。

2 六(多)邊形架構(gòu)(洋蔥圈架構(gòu))

六邊形架構(gòu)(Hexagonal Architecture),又稱為端口和適配器架構(gòu)風(fēng)格,其中的“六”具體數(shù)字沒(méi)有特殊的含義,僅僅表示一個(gè)“量級(jí)”的意思,六邊形的定義只是方便更加形象的理解。

??

??

 

六邊形架構(gòu)提倡用一種新的視角來(lái)看待整個(gè)系統(tǒng),該架構(gòu)中存在兩個(gè)區(qū)域:“外部區(qū)域”和“內(nèi)部區(qū)域”。在外部區(qū)域中不同的客戶均可以提交輸入(網(wǎng)絡(luò)請(qǐng)求、定時(shí)腳本、消息消費(fèi)等),而內(nèi)部區(qū)域則是處理具體邏輯的地方。

??

??

圖源:https://www.jianshu.com/p/d3e8b9ac097b

 

五 案例

案例1:Jpa替換為Mybatis

@Component 
public class CloseOrderService {
@Autowired(required = false)
@Qualifier("rstOrderTransactionManager")
JpaTransactionManager tm;

public void invalid_order(Long orderId, Long userId, Short processGroup)
throws UserException, SystemException, UnknownException {
//其他邏輯。。。省略

// 開(kāi)啟事務(wù)
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus ts = tm.getTransaction(def);

try {
order = orderDAO.get(orderId);
order.setStatusCode(toStatus);
order.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
orderDAO.save(order);
//提交事務(wù)
tm.commit(ts);
} catch (Exception e) {
if (!ts.isCompleted()) {
//回滾
tm.rollback(ts);
}
if (e instanceof SatisfiedStateException) {
return;
}
throw e;
}
}
@Transactional(transactionManager = "rstOrderTransactionManager", rollbackFor = Exception.class)
public void invalidOrder(){
}
}

@Component
public interface OrderDAO extends JpaRepository<OrderPO, Long> {
@Query(value = "sql語(yǔ)句", nativeQuery = true)
Long generateGlobalOrderId(@Param("userId") Long userId,
@Param("restaurantId") Long restaurantId,
@Param("seqName") String seqName);
}

變化帶來(lái)的影響:如果不出意外對(duì)Jpa的使用方式不會(huì)產(chǎn)生變更,意味著其相對(duì)穩(wěn)定,所以在當(dāng)前階段來(lái)看以上耦合是正常的也不會(huì)產(chǎn)生負(fù)面影響。但是在以下場(chǎng)景會(huì)讓我們對(duì)高耦合有很明顯的體感:大家覺(jué)得Jpa不好用,想替換為Mybatis該怎么做?代碼中直接使用了繼承JpaRepository的OrderDAO做數(shù)據(jù)操作,由于Jpa和Mybatis的寫法不同,所以需要把使用到OrderDAO的地方都做替換:

  • 調(diào)用OrderDAO的類(70多個(gè)類)都需要替換為新的dao。
  • 使用JpaTransactionManager.getTransaction()的位置需要替換為MyBatis的TransactionManager。
  • 使用@Transactional(transactionManager = "rstOrderTransactionManager")的位置需要改為編寫事務(wù)提交和回滾的代碼塊兒,便于做灰度。
  • 以上改動(dòng)的位置需要增加開(kāi)關(guān)做灰度。

結(jié)論:由于變更涉及到70多個(gè)類,同時(shí)事務(wù)管理器獲取方式也需要修改,其帶來(lái)的影響還是挺大的,不滿足“低耦合”原則,可以使用“多態(tài)”原則重新設(shè)計(jì)。

案例2:訂單對(duì)應(yīng)的支付單應(yīng)該由誰(shuí)來(lái)創(chuàng)建?

拿餓了么交易系統(tǒng)舉例,當(dāng)前創(chuàng)建支付單的職責(zé)是由bos服務(wù)承擔(dān)(面向app的一個(gè)后端服務(wù))的,接下我們進(jìn)行分析。

??

??

 

支付單創(chuàng)建分為兩種場(chǎng)景:

  • 創(chuàng)建訂單和支付單是在一次操作中完成。
  • 用戶回到訂單列表頁(yè)點(diǎn)擊“去支付”時(shí)創(chuàng)建支付單。

支付單創(chuàng)建依賴:

  • 訂單號(hào)
  • 支付金額
  • 支付類型
  • 一堆支付系統(tǒng)分配的用于識(shí)別業(yè)務(wù)的參數(shù)

??

??

 

注1:如果餓了么只會(huì)有外賣一種交易業(yè)務(wù),當(dāng)前的設(shè)計(jì)還是很穩(wěn)定的,不會(huì)出現(xiàn)太大變化。所以識(shí)別變化點(diǎn)才能更好的評(píng)判當(dāng)前系統(tǒng)設(shè)計(jì)是否合理,如:餓了么將升級(jí)為本地生活服務(wù)公司,根據(jù)公司戰(zhàn)略多少能看出我們將來(lái)不只外賣業(yè)務(wù)存在,還會(huì)有很多和本地生活相關(guān)的交易業(yè)務(wù),這些業(yè)務(wù)會(huì)有自己的展示層(app、h5、web)同時(shí)對(duì)應(yīng)會(huì)有類似bos的服務(wù),如果有10個(gè)業(yè)務(wù)方,在支付場(chǎng)景就需要去對(duì)接10次,而由order做就只需要一次(支付作為工具已經(jīng)比較穩(wěn)定,不會(huì)有太大變化)。

  • bos比order多出識(shí)別訂單結(jié)構(gòu)的成本。
  • bos比order多出認(rèn)知交易域業(yè)務(wù)知識(shí)的成本。需要深入了解交易狀態(tài),這樣才知道什么狀態(tài)才能去支付(一般是去問(wèn)order服務(wù)的開(kāi)發(fā)),打破了邊界。

結(jié)論:bos服務(wù)不應(yīng)該承擔(dān)創(chuàng)建支付單的職責(zé),由order承擔(dān)最合適。

【本文為51CTO專欄作者“阿里巴巴官方技術(shù)”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】

??戳這里,看該作者更多好文??

 

責(zé)任編輯:武曉燕 來(lái)源: 51CTO專欄
相關(guān)推薦

2009-09-29 10:35:42

Linux系統(tǒng)系統(tǒng)提速Linux

2015-07-29 10:25:05

數(shù)據(jù)開(kāi)發(fā)產(chǎn)品必修課

2010-11-25 10:55:34

2014-02-17 09:22:37

2022-03-11 10:53:32

UML建模語(yǔ)言

2009-02-10 15:08:41

2012-01-06 14:10:42

數(shù)據(jù)質(zhì)量管理大數(shù)據(jù)數(shù)據(jù)管理

2023-09-27 22:18:41

2022-08-15 15:03:57

數(shù)字化轉(zhuǎn)型數(shù)字技術(shù)中小企業(yè)

2018-04-28 10:05:17

2025-06-10 08:05:00

錯(cuò)誤返回GoAPI

2020-01-13 16:26:57

AI人工智能機(jī)器

2014-06-23 15:37:50

2023-09-12 11:28:10

2025-09-05 10:17:27

服務(wù)器運(yùn)維磁盤RAID

2017-04-12 09:24:45

開(kāi)發(fā)編程Java

2025-09-17 07:07:00

智能體GenAI人工智能

2013-02-28 09:46:18

程序員巖機(jī)Hacker News

2022-09-19 10:04:44

人工智能AIIT領(lǐng)導(dǎo)者
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)