“低耦合顷啼、高內(nèi)聚”踏枣,它已經(jīng)成為軟件設(shè)計(jì)質(zhì)量的標(biāo)準(zhǔn)之一。那么什么是低耦合钙蒙?耦合就是對(duì)某元素與其它元素之間的連接茵瀑、感知和依賴的量度。這里所說(shuō)的元素躬厌,即可以是功能马昨、對(duì)象(類),也可以指系統(tǒng)扛施、子系統(tǒng)鸿捧、模塊。假如一個(gè)元素A去連接元素B疙渣,或者通過(guò)自己的方法可以感知B匙奴,或者當(dāng)B不存在的時(shí)候就不能正常工作,那么就說(shuō)元素A與元素B耦合妄荔。耦合帶來(lái)的問(wèn)題是泼菌,當(dāng)元素B發(fā)生變更或不存在時(shí)谍肤,都將影響元素A的正常工作,影響系統(tǒng)的可維護(hù)性和易變更性灶轰。同時(shí)元素A只能工作于元素B存在的環(huán)境中谣沸,這也降低了元素A的可復(fù)用性。正因?yàn)轳詈系姆N種弊端笋颤,我們?cè)谲浖O(shè)計(jì)的時(shí)候努力追求“低耦合”。低耦合就是要求在我們的軟件系統(tǒng)中内地,某元素不要過(guò)度依賴于其它元素伴澄。請(qǐng)注意這里的“過(guò)度”二字。系統(tǒng)中低耦合不能過(guò)度阱缓,比如我設(shè)計(jì)了一個(gè)類非凌,它不與我的系統(tǒng)中的任何類發(fā)生耦合。如果有這樣一個(gè)類荆针,那么它必然是低內(nèi)聚(關(guān)于內(nèi)聚的問(wèn)題我隨后討論)敞嗡。耦合與內(nèi)聚常常是一個(gè)矛盾的兩個(gè)方面。最佳的方案就是尋找一個(gè)合適的中間點(diǎn)航背。
哪些是耦合呢喉悴?
元素B是元素A的屬性,或者元素A引用了元素B的實(shí)例(這包括元素A調(diào)用的某個(gè)方法玖媚,其參數(shù)中包含元素B)箕肃。
元素A調(diào)用了元素B的方法。
元素A直接或間接成為元素B的子類今魔。
元素A是接口B的實(shí)現(xiàn)勺像。
現(xiàn)在很多框架都是頁(yè)面展現(xiàn)與業(yè)務(wù)邏輯分離,做到了頁(yè)面展現(xiàn)與業(yè)務(wù)邏輯的低耦合错森。當(dāng)我們的頁(yè)面展現(xiàn)需要變更時(shí)吟宦,我們只需要修改我們的頁(yè)面,而不影響我們的業(yè)務(wù)邏輯涩维;同樣殃姓,我們的業(yè)務(wù)邏輯需要變更的時(shí)候,我們只需要修改我們的C#程序激挪,與我們的頁(yè)面無(wú)關(guān)辰狡。并運(yùn)用IoC(反向控制),降低了業(yè)務(wù)邏輯中各個(gè)類的相互依賴垄分。假如類A因?yàn)樾枰δ蹻而調(diào)用類B宛篇,在通常的情況下類A需要引用類B,因而類A就依賴于類B了薄湿,也就是說(shuō)當(dāng)類B不存在的時(shí)候類A就無(wú)法使用了叫倍。使用了IoC偷卧,類A調(diào)用的僅僅是實(shí)現(xiàn)了功能F的接口的某個(gè)類,這個(gè)類可能是類B吆倦,也可能是另一個(gè)類C听诸,由spring的配置文件來(lái)決定。這樣蚕泽,類A就不再依賴于類B了晌梨,耦合度降低,重用性提高了须妻。但是仔蝌,作為優(yōu)秀的開(kāi)發(fā)人員,僅僅依靠框架提供的降低軟件耦合的方法是遠(yuǎn)遠(yuǎn)不夠的荒吏。根據(jù)我的經(jīng)驗(yàn)敛惊,以下一些問(wèn)題我們應(yīng)當(dāng)引起注意:
根據(jù)可能的變化設(shè)計(jì)軟件
我們采用職責(zé)驅(qū)動(dòng)設(shè)計(jì),設(shè)計(jì)中盡力做到“低耦合绰更、高內(nèi)聚”的一個(gè)非常重要的前提是瞧挤,我們的軟件是在不斷變化的。如果沒(méi)有變化我們當(dāng)然就不用這么費(fèi)勁了儡湾;但是如果有變化特恬,我們希望通過(guò)以上的設(shè)計(jì),使我們?cè)谶m應(yīng)或者更改這樣的變化的時(shí)候盒粮,付出更小的代價(jià)鸵鸥。這里提供了一個(gè)非常重要的信息是,我們努力降低耦合的是那些可能發(fā)生變更的地方丹皱,因?yàn)榻档婉詈鲜怯写鷥r(jià)的妒穴,是以增加資源耗費(fèi)和代碼復(fù)雜度為代價(jià)的。如果系統(tǒng)中某些元素不太可能變更摊崭,或者降低耦合所付出的代價(jià)太大讼油,我們當(dāng)然就應(yīng)當(dāng)選擇耦合。對(duì)于軟件可能變更的部分呢簸,我們應(yīng)當(dāng)努力去降低耦合矮台,這就給我們提出一個(gè)要求是,在軟件設(shè)計(jì)的時(shí)候可以預(yù)判日后的變化根时。根據(jù)以往的經(jīng)驗(yàn)我認(rèn)為瘦赫,一個(gè)軟件的業(yè)務(wù)邏輯和采用的技術(shù)框架往往是容易變化的2個(gè)方面「蛴客戶需求變更是我們軟件設(shè)計(jì)必須考慮的問(wèn)題确虱。在RUP的開(kāi)發(fā)過(guò)程中,為什么需要將分析設(shè)計(jì)的過(guò)程分為分析模型和設(shè)計(jì)模型替裆,愚以為校辩,從分析模型到設(shè)計(jì)模型的過(guò)程實(shí)際上是系統(tǒng)從滿足直接的客戶需求到優(yōu)化系統(tǒng)結(jié)構(gòu)窘问、適應(yīng)可預(yù)見(jiàn)的客戶需求變更的一個(gè)過(guò)程。這種客戶需求的變更不僅僅指對(duì)一個(gè)客戶需求的變更宜咒,更是指我們的軟件從適應(yīng)一個(gè)客戶需求到適應(yīng)更多客戶需求的過(guò)程惠赫。另一個(gè)方面,適應(yīng)變化就是我們最佳的選擇故黑。
合理的職責(zé)劃分
合理的職責(zé)劃分儿咱,讓系統(tǒng)中的對(duì)象各司其職,不僅是提高內(nèi)聚的要求场晶,同時(shí)也可以有效地降低耦合概疆。比如評(píng)審計(jì)劃BUS、評(píng)審表BUS峰搪、評(píng)審報(bào)告BUS都需要通過(guò)評(píng)審計(jì)劃DAO去查詢一些評(píng)審計(jì)劃的數(shù)據(jù),如果它們都去直接調(diào)用評(píng)審計(jì)劃DAO凯旭,則評(píng)審計(jì)劃BUS概耻、評(píng)審表BUS、評(píng)審報(bào)告BUS三個(gè)對(duì)象都與評(píng)審計(jì)劃DAO耦合罐呼,評(píng)審計(jì)劃DAO一旦變更將與這三個(gè)對(duì)象都有關(guān)鞠柄。在這個(gè)實(shí)例中,實(shí)際上評(píng)審計(jì)劃BUS是信息專家(關(guān)于信息專家模式我將在后面討論)嫉柴,評(píng)審表BUS和評(píng)審報(bào)告BUS如果需要獲得評(píng)審計(jì)劃的數(shù)據(jù)厌杜,應(yīng)當(dāng)向評(píng)審計(jì)劃BUS提出需求,由評(píng)審計(jì)劃BUS提供數(shù)據(jù)(如圖B)计螺。經(jīng)過(guò)這樣的調(diào)整夯尽,系統(tǒng)的耦合度就降低了。
使用接口而不是繼承
通過(guò)對(duì)耦合的分析登馒,我們不難發(fā)現(xiàn)匙握,繼承就是一種耦合。如果子類A繼承了父類B陈轿,不論是直接或間接的繼承圈纺,子類A都必將依賴父類B。子類A必須使用在存在父類B的環(huán)境中麦射,父類B不存在子類A就不能使用蛾娶,這樣將影響子類A的可移植性。一旦父類B發(fā)生任何變更潜秋,更改或去掉一個(gè)函數(shù)名蛔琅,或者改變一個(gè)函數(shù)的參數(shù),都將導(dǎo)致子類A不得不變更半等,甚至重寫揍愁。假如父類B的子類數(shù)十上百個(gè)呐萨,甚至貫穿這個(gè)項(xiàng)目各個(gè)模塊,這樣的變更是災(zāi)難性的莽囤∶粒總之,“低耦合”給軟件項(xiàng)目帶來(lái)的優(yōu)點(diǎn)是:易于變更朽缎、易于重用惨远。
本文作者:蔡永堅(jiān)
<上一篇 | 目錄 | 下一篇> |
---|