什麼是共生性 (Connascence) ?聊聊軟體物件導向的耦合指標

文章最後更新於 2023 年 2 月 18 日

什麼是共生性 (Connascence) ?

共生性(Connascence)是一個軟件工程領域的術語,指的是在軟件系統中,兩個或多個模塊之間的相互依賴關係。

共生性可以分為高度共生性和低度共生性兩種。高度共生性表示兩個模塊之間的依賴關係非常強烈,一旦其中一個模塊發生了變化,另一個模塊也必須相應地進行修改才能保持正常運行。低度共生性則表示模塊之間的依賴關係比較弱,修改一個模塊不會對另一個模塊造成太大的影響。

共生性是一個重要的軟件設計原則,因為過度的共生性會使系統變得脆弱且難以維護。如果兩個模塊之間存在過多的依賴關係,那麼一個模塊的修改可能會對整個系統造成意想不到的後果。因此,設計師應該盡可能地減少共生性,使系統更加靈活、可擴展和易於維護。

靜態共生性 (Static Connascence)

靜態共生性(Static Connascence)是指在軟件系統中,兩個或多個模塊之間的相互依賴關係是在編譯時或者語法檢查時就可以檢測到的共生性。

靜態共生通常包括以下幾種類型:

  • 命名共生性 (Connascence of Name (CoN))
    • 指在軟件系統中,兩個或多個模塊之間的相互依賴關係是通過共享變量名稱、函數名稱或常量名稱來實現的一種共生性。
    • CoN 通常有以下幾種類型:
      • CoN 0:表示兩個或多個模塊沒有名稱相同的元素,也就是它們之間不存在命名共生。
      • CoN 1:表示兩個或多個模塊之間存在一個共享的名稱元素,但是這個名稱元素的類型和作用域不同。例如,兩個模塊中都有一個名稱為 “count” 的變量,但是它們的類型和作用域不同。
      • CoN 2:表示兩個或多個模塊之間存在一個共享的名稱元素,它們的類型和作用域相同,但是它們的值和語義不同。例如,兩個模塊中都有一個名稱為 “pi” 的常量,但是它們的值和語義不同,一個是表示數學中的圓周率,另一個是表示計算機中的精度。
      • CoN 3:表示兩個或多個模塊之間存在一個共享的名稱元素,它們的類型、作用域、值和語義都相同。例如,兩個模塊中都有一個名稱為 “MAX_LENGTH” 的常量,它們的值和語義都是相同的。
      • CoN 是一個比較容易出現的共生性,因為設計師在進行命名時可能會出現名稱重複或者不夠描述性的情況。然而,CoN 可能會導致程式碼的可讀性和可維護性下降,因為它增加了程式碼理解和維護的難度。因此,在設計程式碼時,應試圖減少 CoN 的發生,例如通過更加描述性的名稱、更好的命名規則等方式。
  • 型別共生性 (Connascence of Type(CoT))
    • 指在軟件系統中,兩個或多個模塊之間的相互依賴關係是通過共享數據類型來實現的一種共生性。
    • CoT 通常有以下幾種類型:
      • CoT 0:表示兩個或多個模塊沒有共享的數據類型,也就是它們之間不存在類型共生。
      • CoT 1:表示兩個或多個模塊之間存在一個共享的數據類型,但是它們的使用方式不同。例如,兩個模塊中都使用了一個類型為 “Person” 的類,但是它們的成員變量和方法的使用方式不同。
      • CoT 2:表示兩個或多個模塊之間存在一個共享的數據類型,它們的使用方式相同,但是它們的名稱不同。例如,兩個模塊中都使用了一個類型為 “integer” 的數據類型,但是它們的名稱分別為 “int” 和 “Integer”。
      • CoT 3:表示兩個或多個模塊之間存在一個共享的數據類型,它們的使用方式和名稱都相同。例如,兩個模塊中都使用了一個類型為 “string” 的數據類型,它們的使用方式和名稱都相同。
      • CoT 可能會導致程式碼的可讀性和可維護性下降,因為當一個數據類型的定義發生改變時,可能需要修改多個模塊的程式碼。因此,在設計程式碼時,應試圖減少 CoT 的發生,例如通過更好的類型設計、減少共享數據類型的使用等方式。
  • 含義共生性 (Connascence of Meaning(CoM))和約定共生性 (Connascence of Convention(CoC))
    • CoM 表示在軟件系統中,兩個或多個模塊之間的相互依賴關係是通過共享特定含義的概念或詞語來實現的。例如,如果兩個模塊中都使用了 “login” 這個詞語來表示用戶登錄的操作,那麼這兩個模塊之間就存在 CoM 關係。如果其中一個模塊把這個詞改成了 “sign in”,那麼就需要修改另一個模塊的程式碼來保持它們之間的一致性。
    • CoC 表示在軟件系統中,兩個或多個模塊之間的相互依賴關係是通過約定的規範或慣例來實現的。例如,如果一個程式設計團隊規定了特定的程式碼編寫風格,例如變量名要求使用小寫字母和下劃線,那麼在這個團隊中的所有程式設計師都需要遵循這個約定,這就是 CoC。如果有一個程式設計師沒有遵循這個約定,那麼在這個程式碼中就會存在 CoC 關係。
    • CoM 和 CoC 的存在也會影響程式碼的可讀性和可維護性,因此在程式設計中,應試圖減少這些共生性,例如通過清晰的命名和統一的程式碼編寫風格來減少 CoM 和 CoC 的發生。
  • 位置共生性 (Connascence of Position (CoP))
    • CoP 表示在軟件系統中,兩個或多個模塊之間的相互依賴關係是通過位置的相對關係來實現的。例如,如果模塊 A 中的函數 foo() 依賴於模塊 B 中的函數 bar(),並且這些函數定義在文件中的相對位置,那麼這就是 CoP。如果要修改模塊 B 中的函數,可能需要修改模塊 A 中的程式碼來適應這些更改,因為它們之間的相對位置已經發生了變化。
  • 算法共生性 (Connascence of Algorithm (CoA))
    • CoA 表示在軟件系統中,兩個或多個模塊之間的相互依賴關係是通過共享特定的算法或邏輯實現的。例如,如果模塊 A 中的函數 foo() 依賴於模塊 B 中的函數 bar(),並且這些函數實現了相同的算法或邏輯,那麼這就是 CoA。如果要修改這個算法或邏輯,可能需要修改多個模塊中的程式碼來適應這些更改。

動態共生(Dynamic connascence)

動態共生性(Dynamic Connascence)是指軟件系統中的兩個或多個元素之間的相互依賴關係是在運行時動態建立的。與靜態共生性不同,動態共生性依賴於執行期間的特定狀態或數據,因此往往更難以檢測和管理。

動態共生性有幾種不同的類型,包括:

  • Connascence of Timing (CoT):
    • CoT 發生當一個模塊的行為依賴於另一個模塊的時間行為。例如,如果一個模塊在另一個模塊運行之前必須被初始化,那麼它們之間就存在 CoT。這種共生性可能會導致軟件的性能問題,因為它需要等待初始化完成才能繼續執行。
  • Connascence of Control Flow (CoCF):
    • CoCF 發生當一個模塊的行為依賴於另一個模塊的控制流程。例如,如果一個模塊需要等待另一個模塊的回應,那麼它們之間就存在 CoCF。這種共生性可能會導致死鎖或競爭條件等問題,因為它需要等待另一個模塊的行為才能繼續執行。
  • Connascence of State (CoS):
    • CoS 發生當一個模塊的行為依賴於另一個模塊的狀態。例如,如果一個模塊需要知道另一個模塊的內部狀態才能繼續執行,那麼它們之間就存在 CoS。這種共生性可能會導致軟件的可維護性問題,因為它需要瞭解另一個模塊的內部實現才能正確執行。
  • Connascence of Value (CoV):
    • CoV 發生當一個模塊的行為依賴於另一個模塊的輸入值。例如,如果一個模塊需要使用另一個模塊的輸出作為輸入,那麼它們之間就存在 CoV。這種共生性可能會導致軟件的可測試性問題,因為它需要訪問其他模塊的內部狀態或輸出,從而增加了測試的複雜度。
  • Connascence of Environment (CoE): CoE 發生當一個模塊的行為依賴於外部環境。例如,如果一個模塊需要訪問操作系統的文件系統或網絡環境,那麼它們之間就存在 CoE。這種共生性可能會導致軟件的可移植性問題,因為它需要在不同的環境下進行調整或重新編寫。
  • 動態共生性與靜態共生性相比,更難以檢測和管理。因此,在設計軟件系統時,應盡量減少動態共生性的發生,並使用適當的設計模式和技術來管理和隔離共生性的影響。

架構師在確定動態共生關係時比較困難,因為我們缺乏分析運行時調用的工具,來達到分析調用圖那樣的效果。

共生屬性(Connascence properties)

共生(Connascence)是架構師和開發人員的分析工具,它的一些屬性有助於開發人員合理使用它。以下是對這些屬性的一一描述:

  • 強度(Strength)
    • 架構師通過開發人員對某類型耦合進行重構的難易程度來確定共生的強度,不同類型的共生顯然更可取,如下圖所示,架構師和開發人員可以通過重構來改善代碼的耦合,使之向更好的共生髮展。 架構師應該傾向於靜態共生而不是動態共生,因為開發人員可以通過簡單的源碼分析來定位,而且現代IDE更是顯得靜態共生微不足道。例如含義共生,開發人員可以通過創建一個良好命名的常量,而不是用一個magic value來重構,從而改善這種共生。
      • 20230218013008 56
  • 連帶性(Locality)
    • 連帶性衡量的是代碼庫中各模塊之間的近似程度,近距離的代碼(比如在同一模塊中)通常比分開的代碼(在不同的模塊或代碼庫中)具有更多和更高的連帶性。換句話說,相隔較遠時表示耦合性較差的共生,相隔較近時則沒有問題。例如,如果同一個組件中的兩個類具有共生意義,那麼相比具有相同共生形式的兩個組件,它對項目代碼健康的損害要更小。 開發者必須將強度和連帶性放在一起考慮。在同一模塊內發現的較強的共生形式,相比分散開來的相同共生形式要更合適。
  • 程度(Degree)
    • 共生的程度與它造成的影響大小有關——比如它影響的是個別幾個類還是許多類?較低程度的共生對項目代碼的損害較小。比如說,你的項目只有零星幾個模塊,擁有高動態共生並無大礙。然而,現實中代碼庫往往會隨時間增長,一個小問題也會發酵。 Page-Jones( Object-Oriented Design 一書作者)提供了三條利用共生來提高系統模塊化程度的建議:
      1. 通過將系統分解成許多封裝的元素來最小化整體的共生最大限度地減少任何超出封裝邊界的剩餘共生最大限度地提高封裝邊界內的共生
      Jim Weirich重新普及了共生的概念,並給出了兩個很好的建議: 程度法則:將強勢的共生形式轉化為弱勢的共生形式。 連帶性法則:隨著軟件元素之間距離的增加,使用較弱的共生形式。

統一耦合和共生度量標準

從架構師的角度來看,耦合(Coupling)和共生(Connascence)這兩種觀點可能重疊的。Page-Jones所認定的靜態共生代表了出入耦合的程度,結構化編程只關心進或出,而共生關心的是事物如何耦合在一起。為了更好的理解和區分這兩種觀點,可參考下圖:

20230218013153 6

在上圖中,左邊是結構化編程的耦合概念,右邊是共生特性。結構化編程中所謂的數據耦合(方法調用),共生為它應該如何表現提供了建議。另外,結構化編程並沒有涉及到動態共生所涵蓋的領域。

參考資料:

https://connascence.io/

關於作者

卡哥
卡哥
我是Oscar (卡哥),前Yahoo Lead Engineer、高智商同好組織Mensa會員,超過十年的工作經驗,服務過Yahoo關鍵字廣告業務部門、電子商務及搜尋部門,喜歡彈吉他玩音樂,也喜歡投資美股、虛擬貨幣,樂於與人分享交流!

如果對文章內容有任何問題,歡迎在底下留言讓我知道。
如果你喜歡我的文章,可以按分享按鈕,讓更多的人看見我的文章。

網友留言