2009-08-31 16 views
17

從編碼風格的角度看,循環類依賴性是否不好?從編碼風格的角度看,循環類依賴性是否不好?

實施例:

在我們有兩個類,關於單個數據庫(DBInfo)和一類能夠創建數據庫連接一個封裝信息的數據庫應用程序。 (ConnFactory

DBInfo有一個getConnection方法,它使用ConnFactory創建連接。但ConnFactory本身需要一個DBInfo的對象來這樣做。

像這樣:(忽略了可讀性的原因任何編碼風格)

class DBInfo { 
    String name; 
    String connectionUrl; 

    Connection getConnection() { 
     return ConnFactory.getConnection(this); 
    } 
} 


class ConnFactory { 
    Connection getConnection(DBInfo toWhat) { 
     return new Connection(toWhat.connectionUrl); 
    } 
} 

我的同事認爲,這是不好的做法,如果有依賴和只有一個方向是倒不如不圓形的像這樣。

這是不好的做法,反模式還是代碼味道?有什麼缺點嗎?

回答

15

一般來說,我會調用循環依賴Code Code Smell。請注意,術語'Code Smell'主要表示'這裏是一段需要特別注意的代碼,並且很可能從重新設計中受益。'

在大多數情況下,我會強烈考慮循環依賴不是必要的設計,但在極少數情況下,它可能沒問題。

在你的例子中,ConnFactory似乎是多餘的,但這可能是因爲你的例子已被裁減。然而,在我看來,如果將連接創建邏輯移動到DBInfo類,它將會更好。當你已經有一個包含關於數據庫的數據的類時,似乎很自然地讓它負責創建到該數據庫的連接。

+0

我同意,但是有某種父母,子女關係並不是不自然的,其中連接引用了創建它的DBInfo並且DBInfo緩存/管理連接列表創建。 這就是說,在這個例子中,如果它只是我們需要從DBInfo得到的字符串,我只會將其作爲參數傳遞。正如你已經從示例代碼中所說的那樣,它不太清楚爲什麼它們需要相互引用,這使得很難提出正確的重構。 – Cohen 2010-01-07 10:38:22

1

我所知道的是,當您開始使用依賴注入框架(如結構圖)時,循環依賴可能會成爲一個問題。這些框架中的大多數在處理循環依賴時遇到了問題,有時會導致堆棧溢出異常(赦免雙關:-))。因此,我傾向於試圖擺脫它,除非絕對必要且無法避免。

4

此代碼僅適用於ConnFactory.getConnection()是靜態的。更好的解決方案是將getConnection()作爲ConnFactory的實例方法。然後,您的DBInfo可以將ConnFactory作爲參數(可能在構造函數中,如果您有重載的構造函數)。但是,我認爲在這種情況下使用靜態方法比循環引用更糟糕。

但是,如果您要走這條路線,我還會創建一個界面IConnFactory,即DBInfo將與之交互並且ConnFactory將實施。然後沒有循環參考 - DBInfoConnFactory都取決於IConnFactory,這兩者都不依賴。

+0

所以基本上你說,循環依賴是好的,如果類不緊密耦合? – 2009-08-31 08:03:58

+3

我想這將是其中一種方式。我認爲我的觀點是,如果你想要使用循環依賴,那麼你很可能(a)把事情緊緊地聯繫在一起,並且(b)在某處做其他事情。正如Anton Gogolev在另一個答案中指出的那樣,您違反了單一責任原則,這會加劇您的問題。 – 2009-08-31 08:17:53

+0

@Daniel Pryden:+1爲單一責任原則 – Cohen 2010-01-07 10:39:25

8

是的,一般來說循環依賴是不好的,但並不總是邪惡的。循環依賴的問題包括緊耦合,相互依賴的模塊和一般多米諾效應,當一個模塊的變化傳播到其他模塊時。

也就是說,您的代碼違反單一責任原則,因爲DBInfo不僅存儲有關數據庫的信息,還負責獲取Connection對象。將特定的功能移除到一個單獨的類,一切都會很好。

0

循環依賴是不好的,因爲:

  • 兩個依賴超過一個
  • 你無法增量測試(不嘲笑他們中的一個,這將是傻小,緊密耦合的東西)。

如果需要,你可以使用接口來打破循環依賴,但最簡單的解決方案是讓DBInfo成爲ConnFactory的嵌套類。引用自身的單位不是循環的。

7

不一定

我不認爲在粒度級別的循環依賴是不好的。如果兩個,三個或四個類相互依賴,我不會看到問題。 (我不是說這是你想要的東西,但在某些情況下可以確定)。

一個問題,如果你在包或模塊級別有相互依賴性,出於上述和下面提到的所有原因。

1

在任何使用ORM層的應用程序中,這種常見的雙向一對多關係如何?這不是循環依賴的情況嗎?

它不好/代碼味道?