軟件設計“內聚度”“耦合度”介紹
?
一、聯系
?
??? 當個程序段或語句(指令)引用了其它程序段或語句(指令)中所定義或使用的數據名(即存貯區、地址等)或代碼時,他們之間就發生了聯系。一個程序被劃分為若干模塊時,聯系既可存在于模塊之間,也可存在于一個模塊內的程序段或語句之間,即模塊內部。聯系反映了系統中程序段或語句之間的關系,不同類型的聯系構成不同質量的系統。因此,聯系是系統設計必須考慮的重要問題。
?
??? 系統被分成若干模塊后,模塊同模塊的聯系稱為塊間聯系;一個模塊內部各成份的聯系稱為塊內聯系。顯然,模塊之間的聯系多,則模塊的相對獨立性就差,系統結構就混亂;相反,模塊間的聯系少,各個模塊相對獨立性就強,系統結構就比較理想。同時,一個模塊內部各成份聯系越緊密,該模塊越易理解和維護。
?
?
二、評判模塊結構的標準
?
???
1.模塊獨立性
???
??? 模塊化是軟件設計和開發的基本原則和方法,是概要設計最主要的工作。模塊的劃分應遵循一定的要求,以保證模塊劃分合理,并進一步保證以此為依據開發出的軟件系統可靠性強,易于理解和維護。根據軟件設計的模塊化、抽象、信息隱蔽和局部化等原則,可直接得出模塊化獨立性的概念。所謂模塊獨立性,即:不同模塊相互之間聯系盡可能少,應盡可能減少公共的變量和數據結構;一個模塊應盡可能在邏輯上獨立,有完整單一的功能。
?
??? 模塊獨立性(Moduleindependence)是軟件設計的重要原則。具有良好獨立性的模塊劃分,模塊功能完整獨立,數據接口簡單,程序易于實現,易于理解和維護。獨立性限制了錯誤的作用范圍,使錯誤易于排除,因而可使軟件開發速度快,質量高。
?
??? 為了進一步測量和分析模塊獨立性,軟件工程學引入了兩個概念,從兩個方面來定性地度量模塊獨立性的程度,這兩個概念是模塊的內聚度和模塊的耦合度。
?
??? 2.塊內聯系的度量——內聚度
?
??? 軟件概要設計是以需求分析所產生的文檔為依據,著手解決實現“需求”的軟件體系結構,簡稱軟件結構。這一階段確定軟件結構的具體任務是將系統分解成模塊,確定各模塊的功能及調用關系,將用戶的需求分配到適當的位置上去,得出系統的結構圖。
?
??? 軟件概要設計的原則是模塊化、抽象化和信息隱藏,要達到這些原則,就要求模塊具有獨立性。模塊內聚度用于衡量模塊內部各成分之間彼此結合的緊密程度,模塊內聚度由強到弱的順序如圖:
?
??? 高<----------------------------- 內聚度 -----------------------------低
??? | 功能內聚 | 信息內聚 | 通信內聚 | 過程內聚 | 時間內聚 | 邏輯內聚 | 巧合內聚 |
??? 強<--------------------------- 模塊獨立性 ----------------------------弱
?
??? 1> 功能內聚 (Functional Cohesion)
?
??? 功能內聚是內聚度最高的一種模塊類型。如果模塊僅完成一個單一的功能,且該模塊的所有部分是實現這一功能所必須的,沒有多余的語句,則該模塊為功能內聚。功能內聚模塊的結構緊湊、界面清晰,易于理解和維護,因而可靠性強;又由于其功能單一,故復用率高。所以它是模塊劃分時應注意追求的一種模塊類型。
?
??? 2> 信息內聚 (Informational Cohesion)
?
??? 這種模塊完成多個功能,各個功能都在同一數據結構上操作,每一項功能都一個唯一的入口。這個模塊將根據不同的要求,確定該執行哪一個功能。由于這個模塊的所有功能都是基于同一數據結構(符號表),因此它是一個信息內聚模塊。
?
??? 信息內聚模塊可以看作多個功能內聚模塊的組合,并且達到信息的隱蔽。即把某個數據結構、資源或設備隱蔽在一個模塊內,不為別的模塊所知曉。如果一個模塊的各個成分和同一個功能密切相關,而且一個成分的輸出作為另一個成分的輸入,則稱為順序內聚。
?
??? 順序內聚的模塊內,后執行的語句或語句段往往依賴先執行的語句或語句段,以先執行的部分為條件。由于模塊內各處理元素間存在著這種邏輯聯系,所以順序內聚模塊的可理解性很強,屬高內聚度類型模塊。
?
??? 3> 通信內聚 (Communication Cohesion)
?
??? 若一個模塊中的各處理元素需引用共同的數據(同一數據項、數據區或文件),即使用了相同的輸入數據或輸出數據,則稱其元素間的聯系為通信內聚。通信內聚的各部分間是借助共同使用的數據聯系在一起的,故有較好的可理解性。通常內聚模塊是通過數據流圖來定義的。
?
??? 4> 過程內聚 (Procedural Cohesion)
?
??? 如果一個模塊內的各個處理元素是相關的,而且必須按固定的次序執行,這種內聚就叫做過程內聚。過程內聚的各模塊內往往體現為有次序的流程。
?
??? 在使用流程圖作為工具設計程序時,把流程圖中的某一部分劃出組成模塊,就得到過程內聚模塊。例如把流程圖中的循環部分、判定部分、計算部分分成三個模塊,則這三個模塊都是過程內聚的。
?
??? 5> 時間內聚 (Classical Cohesion)
?
??? 時間內聚又稱為經典內聚或瞬時內聚。時間內聚是指一個模塊中包含的任務需要在同一時間內執行(如初始化,結束等所需操作)。與巧合內聚和邏輯內聚相比,這種內聚類型要稍強些,因為至少在時間上,這些任務可以一起完成。但時間內聚和偶然內聚、邏輯內聚一樣,都屬低內聚度類型。
?
??? 6> 邏輯內聚 (Logical Cohesion)
?
??? 一個模塊完成的任務在邏輯上屬于相同或相似的一類(例如用一個模塊產生各種類型的輸出),則該種模塊內的聯系稱為邏輯內聚。每次調用模塊時,由傳送給模塊的判定參數來確定該模塊應執行哪一種功能。
?
??? 邏輯內聚的模塊各成分之間在功能上并無關系,即使局部功能的修改有時也會影響全局,因此主要的困難有:
?
??? ① 修改困難,調用模塊中有一個要對其改動,還要考慮到其它調用模塊;
???
② 模塊內需要增加開關,以判別是誰調用,因而增加了塊間聯系;
???
③ 實際上每次調用只執行模塊中的一部分,而其它部分也一同被裝入內存,因而效率不高。
?
??? 7> 巧合內聚(Coincidental Cohesion)
?
??? 塊內的各個任務(通過語句或指令來實現的)沒有什么有意義的聯系,它們之所以能構成一個模塊完全是偶然的原因。
?
??? 這類模塊內部沒有實質性的聯系,很可能在某種情況下一個調用模塊需要對它修改而別的模塊不需要。這時就很難處理。同時,這種模塊的含義也不易理解,甚至難以為它取一個合適的名字,偶然內聚的模塊也難于測試。所以,在空間允許的情況下,不應使用這種模塊。
?
??? 3.塊間聯系的度量——耦合度
?
??? 耦合度是對一個軟件結構內不同模塊之間互連程度的度量。耦合強弱取決于模塊間接口的復雜程度、進入訪問一個模塊的點及通過接口的數據。在軟件設計中應該追求盡可能松散的耦合系統,在這樣的系統中可以研究、測試或修改、維護任何一個模塊,而不需要對系統的其它模塊有很多的了解或影響其它模塊的實現。此外,當某處發生錯誤時,低耦合度系統的錯誤傳播的范圍相對小些。
?
??? 耦合度取決于各個模塊間接口的復雜程度、調用模塊的方式,以及哪些信息通過接口。耦合度的強弱依賴以下幾個因素:
?
??? (1)一個模塊對另一個模塊的調用
??? (2)一個模塊向另一個模塊傳遞的數據量
??? (3)一個模塊施加到另一個模塊的控制的多少
??? (4)模塊之間接口的復雜度
?
??? 一般模塊之間可能的連接方式有以下幾種,耦合度由低到高如下所示:
?
??? 低<------------------------------ 耦合性 ------------------------------低
??? | 非直接耦合 | 數據耦合 | 標記耦合 | 控制耦合 | 外部耦合 | 公共耦合 | 內容耦合 |
??? 強<---------------------------- 模塊獨立性 -----------------------------弱
?
??? 1> 非直接耦合 (Nondirective Coupling)
?
??? 指兩個模塊彼此完全獨立,沒有直接聯系。它們之間的唯一聯系僅僅在于它們同屬于一個軟件系統或同有一個上層模塊。這是耦合程度最低的一種。當然,系統中只可能有一部分模塊屬此種聯系,因為一個程序系統中不可能所有的模塊都完全沒有聯系。
?
??? 2> 數據耦合 (Data Coupling)
?
??? 兩個模塊彼此交換數據,如一個模塊的輸出數據是另一個模塊的輸入數據,或一個模塊帶參數調用另一個模塊,下層模塊又返回參數,則稱為數據耦合。注意這里的數據指的是簡單數據,而不包括控制參數、公共數據結構或外部變量。
?
??? 應該說,在一個軟件系統中,此種耦合是不可避免的,且有其積極意義。因為任何功能的實現都離不開數據的產生、表示和傳遞。數據耦合的聯系程度也較低。
?
??? 3> 標記耦合 (Stamp Coupling)
?
??? 如果一組模塊通過參數傳遞記錄信息,這稱為標記耦合。這個記錄是某一數據結構的子結構,而不是簡單變量。
?
??? 4> 控制耦合 (Control Coupling)
?
??? 如果一個模塊通過開關、標志、名字等控制信息,明顯得控制選擇另一模塊功能,這種耦合稱為控制耦合。控制耦合屬于中等程度的耦合,較之數據耦合模塊間的聯系更為緊密。但控制耦合不是一種必須存在的耦合。
?
??? 當被調用模塊接收到控制信息作為輸入參數時,說明該模塊內部存在多個并列的邏輯路徑,即有多個功能。控制變量用以從多個功能中選擇所要執行的部分,因而控制耦合是完全可以避免的。排除控制耦合可按如下步驟進行:
?
??? ① 找出模塊調用時所用的一個或多個控制變量;
???
② 在被調模塊中根據控制變量找出所有的流程;
???
③ 將每一個流程分解為一個獨立的模塊;
???
④ 將原被調模塊中的流程選擇部分移到上層模塊,變為調用判斷。
?
??? 通過以上變換,可以將控制耦合變為數據耦合。由于控制耦合增加了設計和理解的復雜程度,因此在模塊設計時要盡量避免使用。當然,如果模塊內每一個控制流程規模相對較小,彼此共性較多,使用控制耦合還是合算的。
?
??? 5> 外部耦合 (External Coupling)
?
??? 一組模塊都訪問同一全局簡單變量而不是同一全局數據結構,而且不是通過參數傳遞該全局變量的信息,則稱之為外部耦合。
?
??? 6> 公共耦合 (Common Coupling)
?
??? 公共耦合又稱公共環境耦合或數據區耦合。若多個模塊對同一個數據區進行存取操作,它們之間的關系稱為公共耦合。公共數據區可以是全程變量、共享的數據區、內存的公共復蓋區、外存上的文件、物理設備等。當兩個模塊共享的數據很多,通過參數傳遞可能不方便時,可以使用公共耦合。公共耦合共享數據區的模塊越多,數據區的規模越大,則耦合程度越強。公共耦合最弱的一種形式是:兩個模塊共享一個數據變量,一個模塊只向里寫數據,另一個模塊只從里讀數據。
?
??? 當公共耦合程度很強時,會造成關系錯綜復雜,難以控制,錯誤傳遞機會增加,系統可靠性降低,可理解、維護性差。
?
??? 7> 內容耦合 (Content Coupling)
?
??? 內容耦合是耦合程序最高的一種形式。若一個模塊直接訪問另一模塊的內部代碼或數據,即出現內容耦合。內容耦合的存在嚴重破壞了模塊的獨立性和系統的結構化,代碼互相糾纏,運行錯綜復雜,程序的靜態結構和動態結構很不一致,其惡劣結果往往不可預測。
內容耦合往往表現為以下幾種形式:
?
??? ①一個模塊訪問另一模塊的內部代碼或數據;
??? ②一個模塊不通過正常入口而轉到另一個模塊的內部(如使用GOTO語句或JMP指令直接進入另一模塊內部);
??? ③兩個模塊有一部分代碼重迭(可能出現在匯編程序中,在一些非結構化的高級語言,如COBOL中也可能出現);
??? ④一個模塊有多個入口(這意味著一個模塊有多種功能)。
?
??? 一般講,在模塊劃分時,應當盡量使用數據耦合。少用控制耦合(盡量轉成數據耦合),限制公共耦合的范圍,完全不用內容耦合。
?
?
?
?
?