




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、對(duì)高內(nèi)聚,低耦合的理解內(nèi)聚:一個(gè)模塊內(nèi)各個(gè)元素彼此結(jié)合的緊密程度耦合:一個(gè)軟件結(jié)構(gòu)內(nèi)不同模塊之間互連程度的度量(耦合性也叫塊間聯(lián)系。指 軟件系統(tǒng)結(jié)構(gòu)中個(gè)模塊間相互聯(lián)系緊密程度的一種度量。模塊之間聯(lián)系越緊密, 其耦合性就越強(qiáng),模塊的獨(dú)立性則越差,模塊間耦合的高低取決于模塊間接口的 復(fù)雜性,調(diào)用的方式以及傳遞的信息。)最近編碼的時(shí)候,總是在猶豫是把某個(gè)方法封裝在一個(gè)類里,還是單獨(dú)的封裝成 一個(gè)類。這讓我突然想起內(nèi)聚耦合這兩個(gè)名詞。我們一直追求著,高內(nèi)聚,低耦合。對(duì)于低耦合,粗淺的理解是:一個(gè)完整的系統(tǒng),模塊與模塊之間,盡可能的使其獨(dú)立存在。也就是說(shuō),讓每個(gè)模塊,盡可能的獨(dú)立完成某個(gè)特定的子功能。模
2、塊與模塊之間的接口,盡量的少而簡(jiǎn)單。如果某兩個(gè)模塊間的關(guān)系比較復(fù)雜的話,最好首先考慮進(jìn)一步的模塊劃分。這樣有利于修改和組合。對(duì)于低耦合,我粗淺的理解是:在一個(gè)模塊內(nèi),讓每個(gè)元素之間都盡可能的緊密相連。也就是充分利用每一個(gè)元素的功能,各施所能,以最終實(shí)現(xiàn)某個(gè)功能。如果某個(gè)元素與該模塊的關(guān)系比較疏松的話,可能該模塊的結(jié)構(gòu)還不夠完善,或 者是該元素是多余的。內(nèi)聚和耦合,包含了橫向和縱向的關(guān)系。功能內(nèi)聚和數(shù)據(jù)耦合,是我們需要達(dá)成 的目標(biāo)。橫向的內(nèi)聚和耦合,通常體現(xiàn)在系統(tǒng)的各個(gè)模塊、類之間的關(guān)系,而縱 向的耦合,體現(xiàn)在系統(tǒng)的各個(gè)層次之間的關(guān)系。對(duì)于我在編碼中的困惑,我是這樣想的,用面向?qū)ο蟮乃枷肴タ紤]一
3、個(gè)類的封裝。 一個(gè)方法,如何封裝,拿到現(xiàn)實(shí)生活中來(lái)看,看這種能力(方法)是否是屬于這 類事物(類)的本能。如果是,就封裝在這個(gè)類里。如果不是,則考慮封裝在其它類里。如果這種能力,很多事物都具有,則一定要封裝在這類事物的總類里。如果這種能力,很多事物都會(huì)經(jīng)常用到,則可以封裝成一個(gè)總類的靜態(tài)方法。關(guān)于耦合內(nèi)聚的概念這些是軟件工程中的知識(shí),我上網(wǎng)查過(guò),總結(jié)著幾位大蝦的評(píng)論,關(guān)于耦合的概念 應(yīng)該是這樣的:對(duì)象之間的耦合度就是對(duì)象之間的依賴性.指導(dǎo)使用和維護(hù)對(duì)象的主要問(wèn)題是 對(duì)象之間的多重依賴性.對(duì)象之間的耦合性越高.維護(hù)成本越高.因此對(duì)象的設(shè)計(jì) 應(yīng)使類和構(gòu)件之間的耦合最小.耦合性是程序結(jié)構(gòu)中各個(gè)模塊之
4、間相互關(guān)聯(lián)的度量.它取決于各個(gè)模塊之間的 接口的復(fù)雜程度,調(diào)用模塊的方式一級(jí)哪些信息通過(guò)接口,一般模塊之間可能的 連接方式有七種,耦合性由低到高分別是:非直接耦合,數(shù)據(jù)耦合,標(biāo)記耦合,控制 耦合,外部耦合,公共耦合,內(nèi)容耦合.一個(gè)軟件是由多個(gè)子程序組裝而成,而一個(gè)程序由多個(gè)模塊(方法)構(gòu)成.耦合是指各個(gè)外部程序(子程序)之間的關(guān)系緊密度而內(nèi)聚就是指程序內(nèi)的各個(gè)模塊之間的關(guān)系緊密度所以說(shuō),為什么要高內(nèi)聚,模塊之間的關(guān)系越緊密,出錯(cuò)就越少!低耦合就是說(shuō),子 程序之間的關(guān)系越復(fù)雜,就會(huì)產(chǎn)生出更多的意想不到的錯(cuò)誤!會(huì)給以后的維護(hù)工 作帶來(lái)很多麻煩一個(gè)優(yōu)秀軟件開(kāi)發(fā)人員的必修課:GRASP你是一個(gè)優(yōu)秀軟件
5、開(kāi)發(fā)人員嗎?你知道GRASP嗎? GRASP軟件開(kāi)發(fā)模式,全 稱通用職責(zé)分配軟件模式(General Responsibility Assignment Software Patterns),是與著名的軟件模式GoF(Gang of Four,即我們常說(shuō)的那23種 軟件開(kāi)發(fā)模式)齊名的另一種軟件開(kāi)發(fā)模式。但是與GoF不同的是,它并不是 提出一些具體的軟件組織結(jié)構(gòu),而是提出,在將現(xiàn)實(shí)世界的業(yè)務(wù)功能抽象成軟件 開(kāi)發(fā)中具體對(duì)象的過(guò)程中,我們應(yīng)當(dāng)遵循的一些基本原則。遵循這些基本原則, 我們才可以開(kāi)發(fā)出高質(zhì)量的軟件出來(lái)。對(duì)于我們要開(kāi)發(fā)的軟件項(xiàng)目,我們可以不 使用工廠模式、可以不使用單例模式、我們也可以不
6、使用觀察者模式,但是我 們不可能不將現(xiàn)實(shí)世界的業(yè)務(wù)功能抽象成軟件開(kāi)發(fā)中具體對(duì)象。從這個(gè)角度說(shuō), 我們要提高自己的軟件開(kāi)發(fā)質(zhì)量,深入理解GRASP比深入理解GoF更重要。但是 我看到現(xiàn)在介紹GoF的文章多,介紹GRASP文章少。正因?yàn)槿绱?,我現(xiàn)在把GRASP 介紹給大家。GRASP包含了 9個(gè)模式,也就是9個(gè)基本原則。這在軟件設(shè)計(jì)大師Craig Larman的經(jīng)典著作UML和模式應(yīng)用中進(jìn)行了深入地講解。GRASP叫通用職責(zé)分配軟 件模式要理解GRASP,我們首先必須理解的一個(gè)問(wèn)題是,我們?cè)趯?duì)象分析和設(shè)計(jì) 過(guò)程中為什么要進(jìn)行職責(zé)分配。一.職責(zé)分配和職責(zé)驅(qū)動(dòng)設(shè)計(jì)在一個(gè)軟件項(xiàng)目開(kāi)始的時(shí)候,我們通常需要
7、進(jìn)行需求分析,了解客戶需要 設(shè)計(jì)一個(gè)什么樣的軟件,這個(gè)軟件中應(yīng)當(dāng)有什么功能。需求分析了解到的是現(xiàn)實(shí) 世界中客戶需求的業(yè)務(wù)功能,每個(gè)業(yè)務(wù)功能往往是一個(gè)業(yè)務(wù)流程,即客戶在日 常工作中不斷在完成的業(yè)務(wù)流程。同時(shí),在用戶的問(wèn)題世界中,必然有一些東西 或者說(shuō)事物,它們之間存在著相互的關(guān)聯(lián)。拿一個(gè)軟件評(píng)審管理系統(tǒng)作為一個(gè)例子吧。評(píng)審管理系統(tǒng)的業(yè)務(wù)需求如下:評(píng)審組織者制訂評(píng)審計(jì)劃,提交領(lǐng)導(dǎo)審批,然后通過(guò)郵件通知評(píng)審者。評(píng)審者接到通知,分別對(duì)評(píng)審對(duì)象進(jìn)行評(píng)審,填寫評(píng)審表,并可以對(duì)評(píng) 審對(duì)象提出疑問(wèn)。評(píng)審組織者匯總評(píng)審者的疑問(wèn),召開(kāi)評(píng)審會(huì)議討論這些疑問(wèn)。在會(huì)上, 有些疑問(wèn)變?yōu)閱?wèn)題,有些疑問(wèn)不是問(wèn)題,有些則依然不
8、能夠確認(rèn)。會(huì)后,評(píng)審組織者整理疑問(wèn),形成評(píng)審報(bào)告,然后由評(píng)審者分別表決該 評(píng)審是否通過(guò)。最后評(píng)審組織者匯總表決結(jié)果,形成評(píng)審結(jié)論。評(píng)審組織者跟蹤問(wèn)題的解決。通過(guò)以上需求的描述,我們不難發(fā)現(xiàn)整個(gè)問(wèn)題世界中的相關(guān)事物:評(píng)審組 織者、評(píng)審計(jì)劃、評(píng)審者、評(píng)審對(duì)象、評(píng)審表、疑問(wèn)、評(píng)審報(bào)告、評(píng)審結(jié)論、問(wèn) 題。我們也不難分析出這些事物相互關(guān)系,比如評(píng)審計(jì)劃與評(píng)審者是一對(duì)多,而 評(píng)審報(bào)告與評(píng)審結(jié)論是一對(duì)一。在RUP中,業(yè)務(wù)需求將形成用例模型及其描述文檔中的用例,事物及其關(guān) 系將形成領(lǐng)域模型中的對(duì)象,當(dāng)然如何制作用例模型和領(lǐng)域模型超出了本文討論 的范圍,有興趣的朋友可以看看相關(guān)文章。領(lǐng)域模型中的對(duì)象將成為軟件開(kāi)
9、發(fā)中形成具體對(duì)象的基礎(chǔ)(軟件開(kāi)發(fā)中形 成什么對(duì)象是根據(jù)軟件開(kāi)發(fā)的具體需求而定的,并不一定要與領(lǐng)域模型的對(duì)象一 致)。用例模型中的用例,將通過(guò)賦予這些對(duì)象行為 而得以實(shí)現(xiàn)?,F(xiàn)在的問(wèn)題 就出來(lái)了,用例模型中的功能,或者說(shuō)一系列行為,應(yīng)當(dāng)如何分配給這些對(duì)象呢。 也就是說(shuō),為了完成同一個(gè)任務(wù),我可以將行為A交給對(duì)象X,也可以交給對(duì)象 Y。雖然交給對(duì)象X與交給對(duì)象Y,我對(duì)行為A的具體實(shí)現(xiàn)不一樣,但是都可以 完成行為A的任務(wù)。那么,我到底應(yīng)當(dāng)交給對(duì)象X還是對(duì)象Y呢?有沒(méi)有一個(gè) 基本原則呢?有,那就是按照職責(zé)分配任務(wù)。雖然從理論上說(shuō),我可以任意定義 對(duì)象,可以讓對(duì)象沒(méi)有任何意義,或者去完成任意的工作,但是通
10、常我們不會(huì) 這樣去設(shè)計(jì)。通常我們會(huì)將對(duì)象與現(xiàn)實(shí)世界的對(duì)象聯(lián)系起來(lái),比如設(shè)計(jì)一個(gè)評(píng)審 計(jì)劃對(duì)象、評(píng)審者對(duì)象。并且我們?cè)谠O(shè)計(jì)對(duì)象的時(shí)候應(yīng)當(dāng)做到“低表示差異”。 低表示差異就是我們?cè)O(shè)計(jì)的對(duì)象應(yīng)當(dāng)與現(xiàn)實(shí)世界的對(duì)象盡量一致。比如說(shuō)我們?cè)O(shè) 計(jì)一個(gè)對(duì)象叫“評(píng)審者”,是因?yàn)槲覀冊(cè)诂F(xiàn)實(shí)世界中有評(píng)審者。同時(shí),我們?yōu)樵u(píng) 審者對(duì)象賦予的行為也應(yīng)當(dāng)盡量與現(xiàn)實(shí)世界一致,比如增加評(píng)審者、修改評(píng)審 者、得到評(píng)審者信息。那么哪些是這個(gè)對(duì)象應(yīng)當(dāng)賦予的行為呢,這應(yīng)當(dāng)由職責(zé)來(lái) 決定。我們通過(guò)對(duì)現(xiàn)實(shí)世界的分析,或者說(shuō)對(duì)于領(lǐng)域模型的分析,設(shè)計(jì)出了軟件 系統(tǒng)中的對(duì)象,這時(shí)候我們應(yīng)當(dāng)為每一個(gè)對(duì)象分配職責(zé)。什么是對(duì)象的職責(zé)呢, 當(dāng)然是通過(guò)對(duì)現(xiàn)
11、實(shí)世界的分析,定義的這個(gè)對(duì)象應(yīng)當(dāng)完成的任務(wù)。比如評(píng)審者 對(duì)象的職責(zé)是存取與評(píng)審者相關(guān)的數(shù)據(jù)。當(dāng)然對(duì)象的職責(zé)不一定是一個(gè),比如評(píng) 審計(jì)劃包含了評(píng)審對(duì)象和評(píng)審者的子項(xiàng),所以它在工作不繁忙的情況下可以代 理處理評(píng)審對(duì)象和評(píng)審者的信息存取。但是一個(gè)對(duì)象的職責(zé)不應(yīng)當(dāng)過(guò)多(也就2、 3個(gè)就行了)并且高度相關(guān)。比如評(píng)審表對(duì)象如果分配職責(zé)處理評(píng)審表的同時(shí), 又去處理評(píng)審計(jì)劃的數(shù)據(jù),這就叫職責(zé)無(wú)關(guān)。職責(zé)分配現(xiàn)在已經(jīng)被普遍認(rèn)為是一個(gè)優(yōu)秀的軟件設(shè)計(jì)應(yīng)當(dāng)遵循的原則,它 有以下好處:1.低表示差異使軟件結(jié)構(gòu)清晰,易于理解,因?yàn)檐浖_(kāi)發(fā)并不是一個(gè)人的 事情。在多人共同開(kāi)發(fā)的軟件項(xiàng)目中,一目了然的軟件結(jié)構(gòu)可以避免開(kāi)發(fā)人員因
12、 誤解而造成的不必要錯(cuò)誤。2.易于維護(hù)和變更。假如評(píng)審計(jì)劃出了問(wèn)題或需要修改,我們就去找評(píng)審 計(jì)劃,如果是評(píng)審者的問(wèn)題我們就去找評(píng)審者,而絕對(duì)不會(huì)與其它對(duì)象有關(guān)。這種通過(guò)考慮對(duì)象、職責(zé)、協(xié)作的對(duì)象設(shè)計(jì)及構(gòu)件方式,被稱為“職責(zé)驅(qū) 動(dòng)設(shè)計(jì)(RDD,Responsibility Drive Design)”。職責(zé)驅(qū)動(dòng)設(shè)計(jì)是通過(guò)先設(shè) 計(jì)用例模型、用例模型描述、操作契約、系統(tǒng)順序圖、領(lǐng)域模型、詞匯表,再一 步步制作分析模型、設(shè)計(jì)模型,寫出每個(gè)功能的交互圖、類圖的很復(fù)雜的過(guò)程, 我在這里就不再詳述了。但是請(qǐng)大家注意一個(gè)非常重要的細(xì)節(jié),前面我們說(shuō),軟 件系統(tǒng)中的對(duì)象是根據(jù)現(xiàn)實(shí)世界抽象得到,對(duì)象職責(zé)的分配是根
13、 據(jù)對(duì)象的定義, 分配一些不多并且高度相關(guān)的任務(wù)。然而我們即使遵照這些原則,也有相當(dāng)大的 設(shè)計(jì)彈性空間,不同人根據(jù)自己的理解,對(duì)于同一個(gè)功能依然有各自不同的設(shè) 計(jì)。GRASP中文譯為“通用職責(zé)分配軟件模式”,就是對(duì)對(duì)象分析和設(shè)計(jì)中職責(zé) 分配問(wèn)題提出數(shù)個(gè)基本原則。同時(shí),這幾個(gè)基本原則也應(yīng)當(dāng)掌握一個(gè)度,即并 不是所有情況下都適用,也不是一個(gè)絕對(duì)的指標(biāo)。比如低耦合,并不是絕對(duì)的不 耦合,不耦合軟件 就沒(méi)法設(shè)計(jì)了;高內(nèi)聚也不能無(wú)限度地高內(nèi)聚,否則系統(tǒng)就 繁復(fù)異常了。一個(gè)優(yōu)秀軟件開(kāi)發(fā)人員的必修課:GRASP (2)低耦合關(guān)鍵字:設(shè)計(jì)模式 我偶然在google或yahoo這樣的搜索引擎搜索GRASP發(fā)現(xiàn),
14、除了國(guó)外的網(wǎng)站,國(guó)內(nèi)網(wǎng)站多 介紹和討論GoF而很少介紹GRASP,即使這少量的文章也講解非常粗略。個(gè)人認(rèn)為作為優(yōu) 秀的開(kāi)發(fā)人員,理解GRASP比GoF更重要,故寫此文章。前面我在(原創(chuàng))一個(gè)優(yōu)秀 軟件開(kāi)發(fā)人員的必修課:GRASP軟件開(kāi)發(fā)模式淺析中介紹了使用GRASP的目的,今天 允許我調(diào)換一下順序,先從低耦合講起,因?yàn)橹T如創(chuàng)建者模式、信息專家模式的根本目的就 是降低耦合。低耦合(Low Coupling)“低耦合”這個(gè)詞相信大家已經(jīng)耳熟能詳,我們?cè)诳磗pring的書籍、MVC的數(shù)據(jù)、設(shè)計(jì)模 式的書籍,無(wú)處不提到“低耦合、高內(nèi)聚”,它已經(jīng)成為軟件設(shè)計(jì)質(zhì)量的標(biāo)準(zhǔn)之一。那么什 么是低耦合?耦合就是對(duì)
15、某元素與其它元素之間的連接、感知和依賴的量度。這里所說(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ò)度,比如
16、說(shuō)我們?cè)O(shè)計(jì)一個(gè)類可以不與JDK 耦合,這可能嗎?除非你不是設(shè)計(jì)的Java程序。再比如我設(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)。幸運(yùn)的是,目前已經(jīng)有大量的框架幫助我們降低我們系統(tǒng)的耦合度。比如,使用struts我們 可以應(yīng)用MVC模型,使頁(yè)面展現(xiàn)與業(yè)
17、務(wù)邏輯分離,做到了頁(yè)面展現(xiàn)與業(yè)務(wù)邏輯的低耦合。 當(dāng)我們的頁(yè)面展現(xiàn)需要變更時(shí),我們只需要修改我們的頁(yè)面,而不影響我們的業(yè)務(wù)邏輯;同 樣,我們的業(yè)務(wù)邏輯需要變更的時(shí)候,我們只需要修改我們的java程序,與我們的頁(yè)面無(wú) 關(guān)。使用spring我們運(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
18、了,耦合度降低,重用性提高了。使用hibernate 則是使我們的業(yè)務(wù)邏輯與數(shù)據(jù)持久化分離,也就是與將數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)的操作分離。我們 在業(yè)務(wù)邏輯中只需要將數(shù)據(jù)放到值對(duì)象中,然后交給hibernate,或者從hibernate那里得到 值對(duì)象。至于用Oracle、MySQL還是SQL Server,如何執(zhí)行的操作,與我無(wú)關(guān)。但是,作為優(yōu)秀的開(kāi)發(fā)人員,僅僅依靠框架提供的降低軟件耦合的方法是遠(yuǎn)遠(yuǎn)不夠的。根據(jù) 我的經(jīng)驗(yàn),以下一些問(wèn)題我們應(yīng)當(dāng)引起注意:1)根據(jù)可能的變化設(shè)計(jì)軟件我們采用職責(zé)驅(qū)動(dòng)設(shè)計(jì),設(shè)計(jì)中盡力做到“低耦合、高內(nèi)聚”的一個(gè)非常重要的前提是,我 們的軟件是在不斷變化的。如果沒(méi)有變化我們當(dāng)然
19、就不用這么費(fèi)勁了;但是如果有變化,我 們希望通過(guò)以上的設(shè)計(jì),使我們?cè)谶m應(yīng)或者更改這樣的變化的時(shí)候,付出更小的代價(jià)。這里 提供了一個(gè)非常重要的信息是,我們努力降低耦合的是那些可能發(fā)生變更的地方,因?yàn)榻?低耦合是有代價(jià)的,是以增加資源耗費(fèi)和代碼復(fù)雜度為代價(jià)的。如果系統(tǒng)中某些元素不太 可能變更,或者降低耦合所付出的代價(jià)太大,我們當(dāng)然就應(yīng)當(dāng)選擇耦合。有一次我試圖將 我的表現(xiàn)層不依賴于struts,但發(fā)現(xiàn)這樣的嘗試代價(jià)太大而失去意義了。對(duì)于軟件可能變更 的部分,我們應(yīng)當(dāng)努力去降低耦合,這就給我們提出一個(gè)要求是,在軟件設(shè)計(jì)的時(shí)候可以預(yù) 判日后的變化。根據(jù)以往的經(jīng)驗(yàn)我認(rèn)為,一個(gè)軟件的業(yè)務(wù)邏輯和采用的技術(shù)框架
20、往往是容易 變化的2個(gè)方面??蛻粜枨笞兏俏覀冘浖O(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è)方面,現(xiàn)在技術(shù)變更之快,EJB、hibernate、 spring, ajax,一個(gè)一個(gè)的技術(shù)像走馬燈一樣從我們腦海中滑過(guò),我們真不知道明天我在用 什么。在這樣的情況下,適應(yīng)變化就是我們最佳的選擇。2)合理的職責(zé)劃分合
21、理的職責(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 (如圖A),則評(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)的 耦合度
22、就降低了。3)使用接口而不是繼承通過(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àn)在使用hibernate和spring設(shè)計(jì)DAO對(duì)象的方式,具 體的描述參見(jiàn)我寫的如何在struts + spring + hibe
23、rnate的框架下構(gòu)建低耦合高內(nèi)聚的軟件 結(jié)構(gòu)一文。總之,“低耦合”給軟件項(xiàng)目帶來(lái)的優(yōu)點(diǎn)是:易于變更、易于重用一個(gè)優(yōu)秀軟件開(kāi)發(fā)人員的必修課:高內(nèi)聚高內(nèi)聚Java軟件工程軟件模式一個(gè)重要的模式:高內(nèi)聚。高內(nèi)聚(High Cohesion)高內(nèi)聚是另一個(gè)普遍用來(lái)評(píng)判軟件設(shè)計(jì)質(zhì)量的標(biāo)準(zhǔn)。內(nèi)聚,更為專業(yè)的說(shuō)法叫功能內(nèi)聚,是 對(duì)軟件系統(tǒng)中元素職責(zé)相關(guān)性和集中度的度量。如果元素具有高度相關(guān)的職責(zé),除了這些職 責(zé)內(nèi)的任務(wù),沒(méi)有其它過(guò)多的工作,那么該元素就具有高內(nèi)聚性,反之則為低內(nèi)聚性。高內(nèi) 聚要求軟件系統(tǒng)中的各個(gè)元素具有較高的協(xié)作性,因?yàn)樵谖覀冊(cè)谕瓿绍浖枨笾械囊粋€(gè)功 能,可能需要做各種事情,但是具有高內(nèi)聚
24、性的一個(gè)元素,只完成它職責(zé)內(nèi)的事情,而把那 些不在它職責(zé)內(nèi)的事情拿去請(qǐng)求別人來(lái)完成。這就好像,如果我是一個(gè)項(xiàng)目經(jīng)理,我的職責(zé) 是監(jiān)控和協(xié)調(diào)我的項(xiàng)目各個(gè)階段的工作。當(dāng)我的項(xiàng)目進(jìn)入需求分析階段,我會(huì)請(qǐng)求需求分析 員來(lái)完成;當(dāng)我的項(xiàng)目進(jìn)入開(kāi)發(fā)階段,我會(huì)請(qǐng)求軟件開(kāi)發(fā)人員來(lái)完成;當(dāng)我的項(xiàng)目需要測(cè)試 的時(shí)候,我會(huì)請(qǐng)求測(cè)試人員。如果我參與了開(kāi)發(fā),我就不是一個(gè)高內(nèi)聚的元素,因?yàn)?開(kāi)發(fā)不是我的職責(zé)。我們的項(xiàng)目為什么要高內(nèi)聚呢?我覺(jué)得可以從可讀性、復(fù)用性、可維護(hù) 性和易變更性四個(gè)方面來(lái)理解??勺x性一個(gè)人寫文章、講事情,條理清晰才能易于理解,這同樣發(fā)生在讀寫軟件代碼上。如果一堆 代碼寫得一團(tuán)亂麻,東一個(gè)跳轉(zhuǎn)西一個(gè)調(diào)
25、用,讀它的人會(huì)感覺(jué)非常頭疼。這種事情也許一直 在寫程序的你我都曾經(jīng)有過(guò)經(jīng)歷。如果一段程序條理非常清晰,每個(gè)類通過(guò)名稱或說(shuō)明都能 清楚明白它的意義,類的每個(gè)屬性、函數(shù)也都是易于理解的它所應(yīng)當(dāng)完成的任務(wù)和行為,這 段程序的可讀性必然提高。在軟件產(chǎn)業(yè)越來(lái)越密集,軟件產(chǎn)業(yè)中開(kāi)發(fā)人員協(xié)作越來(lái)越緊密、 分工越來(lái)越細(xì)的今天,軟件可讀性的要求相信也越來(lái)越為人們所重視。復(fù)用性 在軟件開(kāi)發(fā)中,最低等級(jí)的復(fù)用是代碼拷貝,然后是函數(shù)的復(fù)用、對(duì)象的復(fù)用、組件的復(fù)用。 軟件開(kāi)發(fā)中最懶的人是最聰明的人,他們總是想到復(fù)用。在代碼編寫的時(shí)候突然發(fā)現(xiàn)某個(gè)功 能是曾經(jīng)實(shí)現(xiàn)過(guò)的功能,直接把它拷貝過(guò)來(lái)就ok 了。如果這段代碼在同一個(gè)對(duì)
26、象中,那么 就提出來(lái)寫一個(gè)函數(shù)到處調(diào)用就行了。如果不是在同一個(gè)對(duì)象中呢,就將其抽象成一個(gè)對(duì)象 到處調(diào)用吧。如果不在一個(gè)項(xiàng)目中呢,那就做成組件給各個(gè)項(xiàng)目引用吧。代碼復(fù)用也使我們 的代碼在復(fù)用的過(guò)程中不斷精化、不斷健壯、提高代碼質(zhì)量。代碼的復(fù)用的確給我們的開(kāi)發(fā) 帶來(lái)了不少便利,但是一段代碼能否在各個(gè)需要的地方都能復(fù)用呢?這給我們的軟件開(kāi)發(fā)質(zhì) 量提出了新的要求:好的代碼可以復(fù)用,不好的則不行。軟件中的一個(gè)對(duì)象如果能保證能完 成自己職能范圍內(nèi)的各項(xiàng)任務(wù),同時(shí)又不去理會(huì)與自己職能無(wú)關(guān)的其它任務(wù),那么它就能夠 保證功能的相對(duì)獨(dú)立性,也就可以脫離自己所處的環(huán)境而復(fù)用到其它環(huán)境中,這是一個(gè)具有 內(nèi)聚性的對(duì)象。
27、可維護(hù)性和易變更性在前面如何在struts+spring+hibernate的框架下構(gòu)建低耦合高內(nèi)聚的軟件中我提到,我們 現(xiàn)在的軟件是在不斷變更的,這種變更不僅來(lái)自于我們的客戶,更來(lái)自于我們的市場(chǎng)。如果 我們的軟件通過(guò)變更能及時(shí)適應(yīng)我們的市場(chǎng)需求,我們就可以在市場(chǎng)競(jìng)爭(zhēng)中獲勝。如何能及 時(shí)變更以適應(yīng)我們的市場(chǎng)呢,就是通過(guò)調(diào)整軟件的結(jié)構(gòu),使我們每次的變更付出的代價(jià)最小, 耗費(fèi)的人力最小,這種變更才最快最經(jīng)濟(jì)。高內(nèi)聚的軟件,每個(gè)系統(tǒng)、模塊、類的任務(wù)都高 度相關(guān),就使每一次的變更涉及的范圍縮小到最小。比如評(píng)審表發(fā)生了變更,只會(huì)與評(píng)審表 對(duì)象有關(guān),我們不會(huì)去更改其它的對(duì)象。如果我們能做到這一點(diǎn),我們的系
28、統(tǒng)當(dāng)然是可維護(hù) 性好、易變更性好的系統(tǒng)。那么,我們?nèi)绾巫龅礁邇?nèi)聚呢?就拿前面我提到的評(píng)審項(xiàng)目舉例。我現(xiàn)在要為“評(píng)審表”對(duì) 象編寫一段填寫并保存評(píng)審表的代碼。評(píng)審表對(duì)象的職責(zé)是更新和查詢?cè)u(píng)審表的數(shù)據(jù),但是 在顯示一個(gè)要填寫的評(píng)審表的時(shí)候,我需要顯示該評(píng)審計(jì)劃的名稱、該評(píng)審計(jì)劃有哪些評(píng)審 對(duì)象需要評(píng)審?,F(xiàn)在我如何編寫顯示一個(gè)要填寫的評(píng)審表的代碼?我在評(píng)審表對(duì)象的這個(gè)相 應(yīng)的函數(shù)中編寫一段查詢?cè)u(píng)審計(jì)劃和評(píng)審對(duì)象的代碼嗎?假如你這樣做了,你的代碼就不是 高內(nèi)聚的,因?yàn)椴樵冊(cè)u(píng)審計(jì)劃和評(píng)審對(duì)象的數(shù)據(jù)不是它的職責(zé)。正確的方法應(yīng)當(dāng)去請(qǐng)求“評(píng) 審計(jì)劃”對(duì)象和“評(píng)審對(duì)象”對(duì)象來(lái)完成這些工作,而“評(píng)審表”對(duì)象只是獲
29、取其結(jié)果。另外,如果一個(gè)對(duì)象要完成一個(gè)雖然在自己職責(zé)范圍內(nèi),但過(guò)程非常復(fù)雜的任務(wù)時(shí),也應(yīng)當(dāng) 將該任務(wù)分解成數(shù)個(gè)功能相對(duì)獨(dú)立的子函數(shù)來(lái)完成。我曾經(jīng)看見(jiàn)一個(gè)朋友寫的數(shù)百行的一個(gè) 函數(shù),讓人讀起來(lái)非常費(fèi)勁。同時(shí)這樣的函數(shù)中一些相對(duì)獨(dú)立的代碼,本可以復(fù)用到其它代 碼中,也變成了不可能。所以我給大家的建議是,不要寫太長(zhǎng)的函數(shù),超過(guò)一百行就可以考 慮將一些功能分解出去。與“低耦合”一樣,高內(nèi)聚也不是一個(gè)絕對(duì),而是一個(gè)相對(duì)的指標(biāo),應(yīng)當(dāng)適當(dāng)而不能過(guò)度。 正如我們?cè)诂F(xiàn)實(shí)生活中,如果在一個(gè)十來(lái)人的小公司,每個(gè)人的分工可能會(huì)粗一些,所分配 的職責(zé)會(huì)廣一些雜一些,因?yàn)槠淇傮w的任務(wù)少;而如果在一個(gè)一兩百人的大公司,每個(gè)
30、人的 分工會(huì)細(xì)一些,所分配的任務(wù)會(huì)更加專一些,因?yàn)榭傮w任務(wù)多,更需要專業(yè)化的分工來(lái)提高 效率。軟件開(kāi)發(fā)也是一樣,如果“評(píng)審計(jì)劃”對(duì)象完成的業(yè)務(wù)功能少,并且不復(fù)雜,它完全 可以代理它的子表“評(píng)審對(duì)象”和“評(píng)審者”的管理。但是“評(píng)審計(jì)劃”對(duì)象需要完成的“對(duì) 評(píng)審計(jì)劃表的管理”這個(gè)基本職責(zé)包含的業(yè)務(wù)功能繁多或者復(fù)雜,它就應(yīng)當(dāng)將“對(duì)評(píng)審對(duì)象 表的管理”交給“評(píng)審對(duì)象”對(duì)象,將“對(duì)評(píng)審者表的管理”交給“評(píng)審者”對(duì)象。同樣, 高內(nèi)聚的可維護(hù)性好、易變更性好只能是一個(gè)相對(duì)的指標(biāo)。如果一個(gè)變更的確是大范圍的變 更,你永遠(yuǎn)不可能通過(guò)內(nèi)聚就不進(jìn)行大范圍的變更了。同時(shí)內(nèi)聚也是要付出代價(jià)的,所以你 也不必要去為了一個(gè)
31、不太可能的變更去進(jìn)行過(guò)度設(shè)計(jì),應(yīng)當(dāng)掌握一個(gè)度。過(guò)度的內(nèi)聚必將增 加系統(tǒng)中元素之間的依賴,提高耦合度。所以“高內(nèi)聚”與“低耦合”是矛盾的,必須權(quán)衡 利弊,綜合地去處理。在李洋等人翻譯的UML和模式應(yīng)用中,將內(nèi)聚和耦合翻譯為軟 件工程中的陰與陽(yáng),是中國(guó)人對(duì)內(nèi)聚和耦合的最佳解釋。綜上所述,“高內(nèi)聚”給軟件項(xiàng)目帶來(lái)的優(yōu)點(diǎn)是:可讀性強(qiáng)、易維護(hù)和變更、支持低耦合、 移植和重用性強(qiáng)。當(dāng)我們分析清楚客戶需求設(shè)計(jì)出用例模型以后,當(dāng)我們分析清楚客戶的業(yè)務(wù)環(huán)境制 作出領(lǐng)域模型以后,當(dāng)我們綜合用例模型、領(lǐng)域模型和我們的聰明才智設(shè)計(jì)出一個(gè)又一個(gè)的 類和它們各自的方法以后,當(dāng)就在一切都準(zhǔn)備就緒只欠東風(fēng)的關(guān)鍵時(shí)刻,一個(gè)對(duì)象
32、發(fā)出了 撕心裂肺的怒吼一一誰(shuí)來(lái)創(chuàng)建我? ! 一個(gè)對(duì)象,不管擁有多么強(qiáng)大的功能,不管進(jìn)行了 多么精巧的設(shè)計(jì),如果不能被創(chuàng)建,就如同韓信不能做將軍,孫臏不能當(dāng)軍師,勾踐不能回 越國(guó),劉備不能得荊州,一切一切的雄才武略都如廢紙一張。既然“創(chuàng)建”對(duì)于對(duì)象如此重 要,我們就來(lái)好好探討一下GRASP中關(guān)于對(duì)象創(chuàng)建的問(wèn)題。3.創(chuàng)建者(Creator)當(dāng)我們完成了用例模型、領(lǐng)域模型、對(duì)象分析的設(shè)計(jì),初步完成了對(duì)象設(shè)計(jì)和職責(zé) 分配的工作,開(kāi)始進(jìn)一步細(xì)化的時(shí)候,一個(gè)我們不得不考慮的問(wèn)題就擺在我們的面前 誰(shuí)來(lái)創(chuàng)建這些對(duì)象?也許現(xiàn)在的你會(huì)覺(jué)得好笑,這也是問(wèn)題嗎?在軟件實(shí)際開(kāi)發(fā)過(guò)程中,誰(shuí) 需要使用某個(gè)對(duì)象,就去創(chuàng)建它就
33、行了,有什么好討論的。但是,我不得不說(shuō)的是,如果 你只是漫不經(jīng)心地想要隨意開(kāi)發(fā)一套軟件系統(tǒng),僅僅是完成自己工作而已,你完全不用考慮 創(chuàng)建對(duì)象的問(wèn)題。然而如果你希望開(kāi)發(fā)一套高質(zhì)量的、低耦合的、封裝性和復(fù)用性高的軟 件系統(tǒng),你必須得認(rèn)真考慮這個(gè)問(wèn)題。為什么呢?因?yàn)橄到y(tǒng)中如果一個(gè)對(duì)象A創(chuàng)建另一個(gè) 對(duì)象B,那么對(duì)象A就必將與對(duì)象B耦合,這個(gè)我已經(jīng)在前面(原創(chuàng))一個(gè)優(yōu)秀的軟件開(kāi) 發(fā)人員的必修課:GRASP(2)低耦合中提到。我們可以想像,如果在你的系統(tǒng)中,對(duì)于 對(duì)象B,你也去創(chuàng)建,我也去創(chuàng)建,大家都去創(chuàng)建,對(duì)象B勢(shì)必與許多對(duì)象發(fā)生耦合,耦 合度將大大提高;但如果對(duì)象B可以都由對(duì)象A來(lái)創(chuàng)建,然后由對(duì)象A向
34、其它需要對(duì)象B 的對(duì)象提供對(duì)象B,即其它對(duì)象需要使用對(duì)象B的時(shí)候都向?qū)ο驛索要,那么整個(gè)系統(tǒng)對(duì) 對(duì)象B的耦合將會(huì)大大降低,同時(shí)對(duì)象A和B也可以形成一個(gè)封裝的、可復(fù)用的獨(dú)立系統(tǒng), 則這個(gè)軟件系統(tǒng)的設(shè)計(jì)質(zhì)量勢(shì)必提高。所以,對(duì)象創(chuàng)建的問(wèn)題不可不察。那么為了降低系統(tǒng)耦合,提高系統(tǒng)的清晰度、封裝性和可復(fù)用性,應(yīng)該有一些通用的 原則,以用于對(duì)象職責(zé)分配中,關(guān)于“創(chuàng)建對(duì)象”這類職責(zé)的分配。這些原則的描述就在 GRASP的“創(chuàng)建者”模式中。1)創(chuàng)建者模式的描述如果以下條件之一為真(越多越好),則將創(chuàng)建類A的實(shí)例的職責(zé)分配給類B (B是 對(duì)象A的創(chuàng)建者):B包含或組成聚集A。B記錄A。B直接使用A。B具有A的初
35、始化數(shù)據(jù),并且在創(chuàng)建A時(shí)會(huì)將這些數(shù)據(jù)傳遞給A。因此對(duì)于A的 創(chuàng)建而言,B是信息專家(關(guān)于“信息專家”模式我會(huì)在后面描述)。如果有以上多個(gè)選項(xiàng)適用,通常首先條件1 (B包含或組成聚集A)。2)何時(shí)使用在理解創(chuàng)建者模式的時(shí)候,我認(rèn)為一個(gè)首先必須理解的問(wèn)題是,在軟件項(xiàng)目的整個(gè)過(guò) 程中,它應(yīng)該是在什么階段使用。一個(gè)網(wǎng)友曾經(jīng)發(fā)帖問(wèn)我,他不清楚GRASP一般適應(yīng)于軟 件開(kāi)發(fā)的什么階段。我認(rèn)為,GRASP作為職責(zé)驅(qū)動(dòng)的基本原則,一般適用于對(duì)象分析和設(shè) 計(jì)的中前期。在軟件項(xiàng)目的前期,也就是需求分析階段,我們通常是制作用例模型和領(lǐng)域模 型。用例模型往往描述的是用戶對(duì)整個(gè)項(xiàng)目提出的所有功能的集合。對(duì)于每個(gè)功能,我
36、們 通常使用用例,并在用例描述中描述該用例的主要流程。因此用例模型描述的通常是需求分 析中動(dòng) 態(tài)的部分。領(lǐng)域模型往往描述的是用戶提出的整個(gè)問(wèn)題空間中的各種事物及它們的 相互關(guān)系,因此領(lǐng)域模型描述的是需求分析中靜態(tài)部分。領(lǐng)域模型雖然不是完全,但卻是 以此為基礎(chǔ),形成軟件系統(tǒng)中的軟件類。為什么不是“完全”呢?因?yàn)檐浖到y(tǒng)中需要什么類, 是軟件系統(tǒng)功能的要求。假如在領(lǐng)域模型中的某個(gè)對(duì)象,它的確是用戶問(wèn)題空間中的事物, 但是它在軟件系統(tǒng)功能的要求中使用不到它,那么在軟件系統(tǒng)中它同樣不能成為一個(gè)軟件 類。當(dāng)我們?cè)O(shè)計(jì)好了軟件類以后,我們就將根據(jù)用例模型,為所有的軟件類分配職責(zé),確 定它們各自應(yīng)具有的行為及
37、相互的協(xié)作。每個(gè)軟件類應(yīng)當(dāng)如何分配它們的職責(zé),也就是說(shuō)用 例模型中描述的各個(gè)功能應(yīng)當(dāng)交給哪個(gè)或哪些軟件類去實(shí)現(xiàn),這個(gè)工作就是對(duì)軟件類的職 責(zé)分配。完成這個(gè)工作的階段主要在對(duì)象分析的中前期,也正是我們大量運(yùn)用GRASP的時(shí) 期。職責(zé)分配需要一定的原則,這個(gè)原則將是GRASP“信息專家”模式將要討論的內(nèi)容。當(dāng) 我們將一個(gè)一個(gè)的軟件類的職責(zé)分配好了,其各自的行為和屬性也確定下來(lái)了,下一步需要 考慮的問(wèn)題就是它們應(yīng)當(dāng)在何時(shí),由誰(shuí)來(lái)創(chuàng)建。解決對(duì)象創(chuàng)建問(wèn)題當(dāng)然應(yīng)當(dāng)交給創(chuàng)建者模 式來(lái)完成。因此不難理解,創(chuàng)建者模式應(yīng)當(dāng)運(yùn)用在對(duì)象分析中前期稍靠后一點(diǎn)兒的階段,即 軟件類的主要職責(zé)及其行為都設(shè)計(jì)好了,討論該何時(shí),
38、由誰(shuí)來(lái)創(chuàng)建它的時(shí)候。3)為什么我們做事往往有個(gè)習(xí)慣,凡事問(wèn)個(gè)為什么。前面我提到,使用創(chuàng)建者模式的主要目的 是可以降低系統(tǒng)的耦合。那么,我們?cè)谑褂脛?chuàng)建者模式的這幾個(gè)建議的時(shí)候是如何降低耦合 的呢?這一直是困擾了我很久的一個(gè)疑問(wèn),C raig Larman對(duì)于這一點(diǎn)沒(méi)有清楚地描述。但是, 我們接受一個(gè)新事物,如果都沒(méi)有弄清楚為什么就盲目接受,這是一種十分不嚴(yán)謹(jǐn)?shù)膽B(tài)度。 我現(xiàn)在通過(guò)我在項(xiàng)目中的一些實(shí)踐和自己的一點(diǎn)兒愚悟,談?wù)勛约旱目捶?。?chuàng)建者模式告訴我們,如果系統(tǒng)中存在包含者容納被包含者,或整體聚集部分,則 包含者往往是被包含者的最佳創(chuàng)建者,整體往往是部分的最佳創(chuàng)建者。為什么呢?首先, 這樣的設(shè)計(jì)易
39、于理解,可讀性強(qiáng)。為什么這么說(shuō)呢,我們用我們常見(jiàn)的單據(jù)與單據(jù)明細(xì)來(lái)說(shuō) 明吧。一張單據(jù)有多條單據(jù)明細(xì),這些單據(jù)明細(xì)聚集于單據(jù)中,是單據(jù)的一個(gè)部分。對(duì)于 某張單據(jù),我們只有去填寫這張單據(jù),才會(huì)去填寫它的明細(xì)。同樣,我們要查看和修改這張 單據(jù)的明細(xì),首先肯定是找到這張單據(jù)。以上這些是我們?cè)趯?shí)際生活中大家都認(rèn)同的管理 單據(jù)的方式。GRASP所提倡的一個(gè)十分重要觀念就是低表示差異,也就是說(shuō)實(shí)際生活中是 怎樣的,我們就怎樣設(shè)計(jì)。用更加專業(yè)點(diǎn)兒的術(shù)語(yǔ)表述為:軟件設(shè)計(jì)應(yīng)當(dāng)與用戶的問(wèn)題空間 保持低表示差異。正因?yàn)槿绱?,我的軟件設(shè)計(jì)中,一個(gè)單據(jù)對(duì)象存在了,它的單據(jù)明細(xì)對(duì) 象才可以存在;要得到一個(gè)單據(jù)明細(xì)對(duì)象,應(yīng)當(dāng)
40、先找到它所在的單據(jù)對(duì)象。既然單據(jù)對(duì)象與 單據(jù)明細(xì)對(duì)象是如此的邏輯關(guān)系,我們假設(shè)單據(jù)明細(xì)對(duì)象不是由單據(jù)對(duì)象創(chuàng)建,而是另一 個(gè)對(duì)象X,那么對(duì)象X即要?jiǎng)?chuàng)建單據(jù)對(duì)象,又要?jiǎng)?chuàng)建單據(jù)明細(xì)對(duì)象,還要維持單據(jù)對(duì)象與 單據(jù)明細(xì)對(duì)象的聚集關(guān)系。這樣的設(shè)計(jì)不難看出,代碼實(shí)現(xiàn)比較復(fù)雜,可讀性差。不僅如此, 其耦合度也必然增加。對(duì)象X與單據(jù)對(duì)象和單據(jù)明細(xì)對(duì)象都需要耦合,單據(jù)對(duì)象與單據(jù)明 細(xì)對(duì)象之間同樣需要耦合。如果修改一下設(shè)計(jì),對(duì)象X創(chuàng)建單據(jù)對(duì)象,而單據(jù)對(duì)象去創(chuàng)建 單據(jù)明細(xì)對(duì)象,則對(duì)象X只與單據(jù)對(duì)象耦合,單據(jù)對(duì)象再與單據(jù)明細(xì)對(duì)象耦合,耦合度就 降低了。所以,包含者創(chuàng)建被包含者,整體創(chuàng)建部分可以有效降低耦合。同時(shí),這樣的
41、設(shè)計(jì), 單據(jù)明細(xì)對(duì)象的創(chuàng)建只與單據(jù)對(duì)象有關(guān),整個(gè)系統(tǒng)都由單據(jù)對(duì)象向其它對(duì)象提供單據(jù)明細(xì) 對(duì)象,那么單據(jù)對(duì)象與單據(jù)明細(xì)對(duì)象則可以比較容易地形成一個(gè)關(guān)于單據(jù)的獨(dú)立系統(tǒng)。這 樣一個(gè)獨(dú)立系統(tǒng)可以比較便利地應(yīng)用到其它需要使用單據(jù)的地方,其可移植性也就提高了。盡管包含者往往是被包含者的最佳創(chuàng)建者,整體往往是部分的最佳創(chuàng)建者,但是在一 個(gè)軟件系統(tǒng)中,并不是所有類都有它的包含者或者整體。如果沒(méi)有,誰(shuí)應(yīng)當(dāng)創(chuàng)建它呢?記錄 者當(dāng)然是另一個(gè)可以考慮的人選。倉(cāng)庫(kù)管理員管理進(jìn)出庫(kù)是ERP系統(tǒng)一個(gè)非常重要模塊。 在實(shí)際生活中,一批產(chǎn)品存入倉(cāng)庫(kù),倉(cāng)庫(kù)管理員當(dāng)然是需要填寫入庫(kù)單。這個(gè)入庫(kù)單在倉(cāng)庫(kù) 管理員填寫之前,本沒(méi)有,是倉(cāng)庫(kù)
42、管理員填寫之后才有,我們是不是可以說(shuō)倉(cāng)庫(kù)管理員創(chuàng) 建了一個(gè)入庫(kù)單。既然現(xiàn)實(shí)生活中如此,我們?cè)谲浖O(shè)計(jì)中是不是也應(yīng)該由倉(cāng)庫(kù)管理員對(duì)象 負(fù)責(zé)創(chuàng)建入庫(kù)單對(duì)象,符合低表示差異,不言而喻也符合低耦合。同樣,在這個(gè)軟件系統(tǒng) 中倉(cāng)庫(kù)管理員填寫入庫(kù)單,在其它的系統(tǒng)中也同樣是倉(cāng)庫(kù)管理員填寫入庫(kù)單。倉(cāng)庫(kù)管理員與 入庫(kù)單這對(duì)封裝的獨(dú)立體也同樣可以應(yīng)用到別的系統(tǒng),可移植性和封裝性也得以提高。因 此記錄者創(chuàng)建記錄內(nèi)容也是我們可以考慮的一個(gè)方案。如果我們正在設(shè)計(jì)的軟件類也沒(méi)有記錄者,這可如何是好?具有創(chuàng)建這個(gè)類所需數(shù)據(jù) 的那個(gè)類可以考慮,那個(gè)類就是信息專家(什么是“信息專家”,我會(huì)在以后對(duì)信息專家模式 的文章中詳細(xì)描述)
43、。在我們的設(shè)計(jì)過(guò)程中,很多類的創(chuàng)建是需要一些初始化數(shù)據(jù)的。最典 型的就是我們的vo (值對(duì)象)。在java程序中,vo往往是用來(lái)傳輸數(shù)據(jù)的,也就是說(shuō)創(chuàng)建 vo的初始化數(shù)據(jù)就是這些它需要傳遞的數(shù)據(jù)。如果這些數(shù)據(jù)在某個(gè)Action中,創(chuàng)建vo的當(dāng) 然就是這個(gè)Action。而如果這個(gè)vo的初始化數(shù)據(jù)來(lái)自BUS,則該vo的創(chuàng)建當(dāng)然應(yīng)當(dāng)是這 個(gè)BUS中。如果以上方法還不行,那我們就只有找使用者了。尋找使用者是我們創(chuàng)建類最常用 的一種方法,但它的缺點(diǎn)也非常明顯。正如前面我描述的,我們系統(tǒng)中對(duì)某個(gè)軟件類的使 用可能分布到系統(tǒng)的各個(gè)角落。當(dāng)我們因?yàn)槟硞€(gè)需求需要修改這個(gè)類的時(shí)候,我們根本不知 道誰(shuí)在使用它。正因
44、為如此,這樣的修改變得如夢(mèng)魘一般,不斷地搜索,不斷地修改。我 們前面說(shuō)過(guò),合理的軟件構(gòu)造是為了使我們的變更代價(jià)最小,而這樣的變更將使我們的代價(jià) 太大了,也許一個(gè)不經(jīng)意的變更錯(cuò)誤將造成我們的系統(tǒng)中一個(gè)意想不到的地方發(fā)生異常。 故我們變更后測(cè)試的代價(jià)也就因此而增大??傊?,尋找使用者作為創(chuàng)建者是我們業(yè)務(wù)分析階 段最后的終極選擇。4)創(chuàng)建者模式是原則,不是準(zhǔn)則“創(chuàng) 建者模式是原則,不是準(zhǔn)則難道“原則”和“準(zhǔn)則”還有不同嗎?當(dāng)然。創(chuàng)建者模式 是原則,所以我們?cè)跇I(yè)務(wù)分析階段應(yīng)當(dāng)盡量遵守。但創(chuàng)建者模式不是準(zhǔn)則,因?yàn)椴⒎俏覀?的所有軟件類都必須遵守。為什么這么說(shuō)呢?隨著項(xiàng)目的進(jìn)行,我們的分析設(shè)計(jì)就不再停留 在
45、業(yè)務(wù)的分析上,各種具體的框架和技術(shù)將不斷引進(jìn)項(xiàng)目中,這時(shí)對(duì)象的創(chuàng)建就不一定符 合創(chuàng)建者模式。比如,為了提高系統(tǒng)的性能和可維護(hù)性、更好地處理對(duì)象的創(chuàng)建與回收等復(fù) 雜的問(wèn)題,我們常常把對(duì)象的創(chuàng)建交給工廠,如spring的beanFactory、hibernate的sessionFactory等等?!肮S”不論是“具體工廠”還是“抽象工廠”,都不符合創(chuàng)建者模式中的 任何一個(gè)條件。為什么呢?因?yàn)閯?chuàng)建者模式中的各個(gè)條件都是來(lái)自對(duì)領(lǐng)域模型和設(shè)計(jì)模型 的分析,說(shuō)得更加直白一點(diǎn)兒就是對(duì)客戶現(xiàn)實(shí)世界的分析,與技術(shù)無(wú)關(guān)。在技術(shù)領(lǐng)域的對(duì)象 分析和設(shè)計(jì)已經(jīng)超出了創(chuàng)建者模式適用的范圍,這更多的是出現(xiàn)在對(duì)象分析和設(shè)計(jì)的中后 期。所以,正如我前面所述的,創(chuàng)建者模式適用的時(shí)期,是對(duì)象分析和設(shè)計(jì)的中前期,對(duì)象 的業(yè)務(wù)分析稍晚一點(diǎn)兒的階段??傊?,合理地創(chuàng)建對(duì)象可以有效的提供可讀性、降低耦合度、提高系統(tǒng)的封裝性和可 移植性,我們應(yīng)當(dāng)引起重視。模塊的耦合與內(nèi)聚DELPHI 技術(shù) 2009-08-05 00:07 閱讀 52 評(píng)論 0字號(hào):大中小 模塊的耦合與內(nèi)聚 耦合(C oupling)是模塊之間依賴程度的度量。內(nèi)聚和耦合是密切相關(guān)的,與其它模塊存在強(qiáng)耦 合的模塊通常意味著弱內(nèi)聚,而強(qiáng)內(nèi)聚的模塊通常意味著與其它模塊之間存在弱耦合。模塊設(shè)計(jì)追求強(qiáng)內(nèi) 聚,弱耦合。內(nèi)聚(Cohesion)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 旅游會(huì)展行業(yè)發(fā)展趨勢(shì)考核試卷
- 醫(yī)療器械技術(shù)人才培養(yǎng)考核試卷
- 收養(yǎng)家庭育兒指導(dǎo)手冊(cè)編制考核試卷
- 化學(xué)纖維在餐飲美食等行業(yè)的應(yīng)用考核試卷
- 出租車行業(yè)聯(lián)盟與合作模式探索考核試卷
- 企業(yè)人力資源戰(zhàn)略規(guī)劃考核試卷
- 建筑物清潔服務(wù)心理素質(zhì)培養(yǎng)考核試卷
- 收納培訓(xùn)課件模板
- 汽車按揭合同抵押合同范本
- 廠房抵押合同范本簡(jiǎn)短
- 智能交通概論全套教學(xué)課件
- 生物醫(yī)學(xué)工程倫理 課件全套 第1-10章 生物醫(yī)學(xué)工程與倫理-醫(yī)學(xué)技術(shù)選擇與應(yīng)用的倫理問(wèn)題
- 燒結(jié)機(jī)安裝使用說(shuō)明書
- 新戰(zhàn)略營(yíng)銷課件
- (完整版)部編一年級(jí)下冊(cè)語(yǔ)文《春夏秋冬》ppt
- 人文地理學(xué)考試名詞解釋全套
- 新華書店業(yè)務(wù)崗位職責(zé)共3篇
- 統(tǒng)編版五年級(jí)下冊(cè)第五單元 習(xí)作:形形色色的人 課件 (共16張PPT)
- 大數(shù)據(jù)介紹課件
- 幼兒園多媒體PPT課件制作PPT完整全套教學(xué)課件
- 2023離婚協(xié)議模板下載
評(píng)論
0/150
提交評(píng)論