2010-06-21 174 views
291

凝聚力和耦合力有什麼區別?凝聚力和耦合力

耦合和內聚如何導致軟件設計的好壞?

什麼是一些例子,概述了兩者之間的差異,以及它們對整體代碼質量的影響?

+1

檢查出來:http://msdn.microsoft.com/en-us/magazine/cc947917。aspx – Inv3r53 2010-06-21 14:03:37

+1

我想指出這篇文章:[S.O.L.I.D.軟件開發,一步到位](http://www.code-magazine.com/article.aspx?quickid=1001061&page=1)。 Grz,克里斯。 – XIII 2010-06-21 14:40:07

+3

[This](http://enterprisecraftsmanship.com/2015/09/02/cohesion-coupling-difference/)是關於此主題的最新帖子 – janisz 2015-09-02 12:22:00

回答

431

凝聚力指的是類(或模塊)能夠做什麼。低凝聚力意味着班級做了各種各樣的行動 - 範圍廣泛,不重視應該做什麼。高凝聚力意味着班級專注於應該做什麼,即只有與班級意圖有關的方法。低凝聚力的

實施例:

------------------- 
| Staff   | 
------------------- 
| checkEmail() | 
| sendEmail()  | 
| emailValidate() | 
| PrintLetter() | 
------------------- 

高凝聚力的實施例:

---------------------------- 
| Staff     | 
---------------------------- 
| -salary     | 
| -emailAddr    | 
---------------------------- 
| setSalary(newSalary) | 
| getSalary()    | 
| setEmailAddr(newEmail) | 
| getEmailAddr()   | 
---------------------------- 

至於耦合,它指的是如何相關的或依賴兩個類/模塊是朝向彼此。對於低年級的班級,改變某一班的主修課不應該影響其他班。高耦合會導致難以改變和維護你的代碼;因爲課程緊密結合在一起,所以做出改變可能需要整個系統改造。

良好的軟件設計有高凝聚力低耦合

+0

@ mauris.sg我試圖圍繞低耦合程度的低點以及凝聚力應該有多高。我有一個快速的問題。可以說我正在構建一個REST API。如果一個REST URL的一部分由一個類A表示,並且其他調用從這個部分分散到不同的類中,考慮到這些形成子樹S,可以肯定地說A類代表低耦合和高內聚性它也被視爲一個綁定子樹S的組?即我可以在A本身內調用表示A之外的不同端點的類嗎? 我希望我不是模糊的。 – Setafire 2014-08-05 22:57:14

+0

@ mauris.sg或者A可以是代表REST調用本身的構建器,也可以作爲其子樹S的組來使用。很抱歉,這個問題可能看起來很長,但前者是我的團隊主管堅持要做的事情,儘管我沒有真正從中獲得價值。 – Setafire 2014-08-05 23:03:51

+4

我不明白如何刪除一些方法,並添加一些其他方法增加內聚力。有人可以幫忙嗎? – 2016-01-27 09:44:07

54

高內聚內模塊和低耦合模塊之間往往被視爲背景下的面向對象編程語言的高品質。例如,每個Java類中的代碼必須具有較高的內部凝聚力,但儘可能與其他Java類中的代碼鬆散耦合。

Meyer's Object-Oriented Software Construction (2nd edition)的第3章是對這些問題的很好的描述。

30

增加凝聚力和減少耦合確實導致良好的軟件設計。

內聚將您的功能劃分爲簡潔和最接近與其相關的數據,而分離可確保功能實現與系統其餘部分隔離。

解耦允許您在不影響軟件其他部分的情況下更改實現。

凝聚力確保實施更具體到功能,同時更容易維護。

減少耦合和增加內聚力的最有效的方法是通過接口設計的

這是主要的功能對象應該只通過它們實現的接口互相「認識」。接口的實現引入了凝聚力作爲自然結果。

雖然在一些senarios中不現實,但它應該是一個設計目標。

例(非常粗略的):

public interface IStackoverFlowQuestion 
     void SetAnswered(IUserProfile user); 
     void VoteUp(IUserProfile user); 
     void VoteDown(IUserProfile user); 
} 

public class NormalQuestion implements IStackoverflowQuestion { 
     protected Integer vote_ = new Integer(0); 
     protected IUserProfile user_ = null; 
     protected IUserProfile answered_ = null; 

     public void VoteUp(IUserProfile user) { 
      vote_++; 
      // code to ... add to user profile 
     } 

     public void VoteDown(IUserProfile user) { 
      decrement and update profile 
     } 

     public SetAnswered(IUserProfile answer) { 
      answered_ = answer 
      // update u 
     } 
} 

public class CommunityWikiQuestion implements IStackoverflowQuestion { 
    public void VoteUp(IUserProfile user) { // do not update profile } 
    public void VoteDown(IUserProfile user) { // do not update profile } 
    public void SetAnswered(IUserProfile user) { // do not update profile } 
} 

一些別的地方在你的代碼庫,你可以有,無論是處理問題,它們是什麼模塊:

public class OtherModuleProcessor { 
    public void Process(List<IStackoverflowQuestion> questions) { 
     ... process each question. 
    } 
} 
11

凝聚力軟件工程是某個模塊的元素所屬的程度。因此,它是衡量軟件模塊的源代碼所表達的每個功能有多強烈關聯的度量。用簡單的話來說,一個組件(同樣,想象一個類,儘管不一定)知道另一個組件的內部運作或內部組件,即它對另一個組件有多少知識。

I wrote a blog post about this,如果你想通過例子和圖紙閱讀更多的細節。我認爲它回答了你的大部分問題。

16
凝聚力

最好的解釋來自鮑勃叔叔的乾淨代碼:

類應該有少量的實例變量。每個類的方法都應該操縱這些變量中的一個或多個。 通常,方法操作的變量越多,該方法對其類的內聚性越強。每個方法使用每個變量的類最大程度地具有內聚性。

一般來說,既不可能也不可能創建這樣的最大粘性類;另一方面,想凝聚力高。當凝聚力很高時,這意味着這個階級的方法和變量是相互依存的,並且作爲一個邏輯整體在一起。

保持函數較小並保持參數列表較短的策略有時會導致方法子集使用的實例變量激增。發生這種情況時,幾乎總是意味着至少有一個班級試圖擺脫大班級。你應該嘗試把變量和方法分成兩個或更多的類,這樣新的類更加緊密。

1

我認爲差異可以被置爲執行以下操作:

  • 銜接表示到其上的代碼庫的一部分形成了一個單一的邏輯,原子單元的程度。
  • 耦合表示單個單元獨立於其他單元的程度。
  • 在不破壞凝聚力的情況下完全解耦是不可能的,反之亦然。

In this blog post我寫了更詳細的內容。

0

凝聚力表示模塊的相對功能強度。

  • 一個內聚模塊執行一項任務,需要很少的 與程序其他部分的其他組件交互。簡單地說,一個有凝聚力的模塊應該(理想地)只做一件事。
  • Conventional視圖:

    「單意識」的模塊的

  • OO視圖:

    cohesion意味着一個部件或類只封裝屬性和操作是密切相互關聯以及相關類別或組件本身

  • 內聚力水平

    Functional

    Layer

    Communicational

    Sequential

    Procedural

    Temporal

    utility

耦合表示模塊之間相對相互依賴。

  • 耦合取決於模塊之間的接口的複雜性,在該條目或參考的 點到模塊製成,並且什麼數據 跨越接口通過。

  • 傳統觀點: 的程度的部件被連接到其他部件和外部世界

  • OO視圖:度定性度量給哪些類被連接到彼此

  • 級耦合的

    Content

    Common

    Control

    Stamp

    Data

    Routine呼叫

    Type使用

    Inclusion或導入

    External#

26

凝聚力表示軟件元素的職責是如何相關和集中的。

耦合指的是軟件元素與其他元素的連接程度。

軟件元素可以是類,包,組件,子系統或系統。並且,在設計系統時,建議具有高內聚和支持低耦合的軟件元素。

低凝聚力導致難以維護,理解和減少重複使用的單片類。類似地,高耦合會導致類型緊密耦合,並且更改傾向於不是非本地,難以更改並減少重用。

我們可以假設我們正在設計具有以下要求的典型監視器ConnectionPool。請注意,它可能看起來像一個簡單的類如ConnectionPool太多,但基本意圖只是示範低耦合高內聚與一些簡單的例子,我認爲應該幫助。

  1. 支持獲取連接
  2. 釋放連接
  3. 獲取有關連接VS使用次數
  4. 獲得統計數據有關連接與時間
  5. 存儲連接檢索和發佈信息的數據庫,報表統計數據後來。

隨着低凝聚力我們可以通過強制餡所有這些功能設計ConnectionPool類/責任到下面的類。我們可以看到,這個單獨的類負責連接管理,與數據庫交互以及維護連接統計信息。

Low Cohesion Connection Pool

隨着高內聚我們可以分配跨越類這些責任,並使其更容易維護和重用。

High Cohesion Connection Pool

爲了證明低耦合,我們將繼續與高凝聚力上述ConnectionPool圖。如果我們看上面的圖表,雖然它支持高凝聚力,但ConnectionPoolConnectionStatistics類別和PersistentStore緊密耦合,它直接與它們交互。相反,爲了減少耦合,我們可以引入一個ConnectionListener接口,讓這兩個類實現接口並讓它們在ConnectionPool類中註冊。 ConnectionPool將遍歷這些監聽器,並通知它們連接獲取和釋放事件,並允許更少的耦合。

Low Coupling ConnectionPool

注/ Word或警告:對於這個簡單的場景它可能看起來像矯枉過正,但如果我們想象到我們的應用程序需要與多個第三方服務交互完成一個實時情景事務:直接將我們的代碼與第三方服務耦合意味着第三方服務中的任何更改都可能導致我們的代碼在多個位置發生更改,相反,我們可以在內部與這些多個服務進行交互,並對服務進行任何更改成爲本地的Facade並強制與第三方服務的低耦合。

+2

優秀的答案!如果可能的話,你可以使用其他的例子嗎?連接池可能並不是每個人都清楚的。無論如何,它確實幫助了我。那謝謝啦! – 2016-01-27 09:56:45

+0

如何使用ConnectionListener接口幫助減少耦合?您可以提供一個更易於理解的示例。 – 2016-04-30 19:12:43

+0

@abhishekgupta在這個例子中,您可能已經注意到我們已經使用觀察者模式來實現低/鬆耦合。通過這將有助於[觀察者如何創建鬆散耦合設計?](http://programmers.stackexchange.com/questions/234230/how-does-observer-create-loosely-coupled-design) – 2016-05-01 04:36:07

0

耦合兩個模塊之間 =相互作用/關係... 銜接 =一個模塊內的兩個元素之間的相互作用。

軟件由許多模塊組成。模塊由元素組成。考慮一個模塊是一個程序。程序中的函數是一個元素。

在運行時,程序的輸出被用作另一個程序的輸入。這稱爲模塊到模塊的交互或進程來處理通信。這也被稱爲耦合。

在單個程序中,函數的輸出被傳遞給另一個函數。這稱爲模塊內元素的交互。這也被稱爲凝聚力。

例子:

耦合在2間不同的家庭 =通信... 凝聚力 =在父親的母子之間的家庭內部通信。

+0

那麼,你如何解釋它們對軟件的影響?** – 2016-11-19 19:23:00

+0

一個軟件包含許多模塊。模塊由元素組成。考慮一個模塊是一個程序。程序中的函數是一個元素。 – 2016-12-04 03:12:00

14

凝聚力指示之間的關係模塊。

耦合表示模塊之間的關係的指示。

enter image description here

檢查this鏈接

0

我們希望有關的行爲坐在一起,和無關的行爲在其他地方坐。爲什麼?那麼,如果我們想要改變行爲,我們希望能夠在一個地方改變它,並儘快釋放這個改變。如果我們必須在很多不同的地方改變這種行爲,我們將不得不釋放許多不同的服務(可能在同一時間)來實現這種改變。在很多不同的地方進行更改比較慢,而且立即部署大量服務存在風險 - 我們希望避免這兩種情況。所以我們希望找到問題領域內的邊界,以幫助確保相關行爲集中在一個地方。 - 凝聚力

,並與其他邊界爲鬆散地溝通。 - 耦合

0

凝聚(凝聚):這意味着一起HESION這意味着。將不同物質的粒子粘在一起的系統。

對於現實生活中的例子:
enter image description here
img Courtesy

整體大於部分 - 亞里士多德的總和。

  • 銜接是一個序類型的測量和通常被描述爲「高內聚」或「低凝聚力」。具有高凝聚力的模塊往往是優選的,因爲高凝聚力與軟件的一些理想特性相關,包括魯棒性,可靠性,可重用性和可理解性。相反,低凝聚力與不理想的特性相關,例如難以維護,測試,重用或甚至理解。 wiki

  • 耦合通常與凝聚力對比。低耦合通常與高內聚力相關,反之亦然。低耦合通常表明結構良好的計算機系統和良好的設計,並且與高內聚性相結合時,支持高可讀性和可維護性的總體目標。 wiki