2013-05-14 67 views
8

我一直在使用Sonar代碼質量管理平臺,在大多數情況下,我發現它非常有助於揭示我的代碼庫的隱藏設計缺陷。Java包之間的每個循環引用都不好嗎?

但是,有一條規則讓我比幫助更煩惱,那就是它檢查'循環軟件包引用'違規。

我想我完全理解pacakges之間的這種依賴關係是一件壞事。例如,在一個典型的3層表示/服務/持久化分層設計中,讓數據庫處理代碼返回與UI相關的類的引用幾乎總是一個壞主意。把它稱爲「違規」我沒有問題。

但讓我們考慮其他情況,即像設計一個像應用程序的IDE一樣。說,我們有一個主包,其中包含一個應用程序接口,它定義了列表Application.getViews()方法來引用應用程序的視圖。

然而,當視圖接口具有應用getApplication()方法指回其原申請,我相信這是一個相當普遍的設計,它會引入一個循環引用,提供的每個接口的分別在com.myapp.uicom.myapp.ui.view中分開。

當然,你可以把查看接口到com.myapp.ui打破這種循環。但是,當你在com.myapp.ui.view其他各種視圖相關的API,其中許多是另一個抽象的API,如AbstractView內容查看AbstractContentView,等等,我不知道是否是更可取的,讓他們爲了管理目的在單獨的包中。

,並考慮上述應用具有許多其他類似的情況下,像com.myapp.ui.actioncom.myapp.ui.perspective等,這將真正使com.myapp.ui pacakge擁擠如果我們要把它們放在那裏。

那麼,您建議如何處理這種情況?真的每個循環軟件包引用一件壞事嗎?或者如果我必須和他們一起生活,你如何配置Sonar來檢查真正有問題的週期?

謝謝!

回答

6

每個絕對 - 除了這一個;) - 在某些時候會出錯。那麼,每個循環參考都不好嗎?不,你必須使用你的判斷。

但是,如果你確實引入了循環依賴,那麼值得問你是否真的需要它,以及爲什麼。 tl; dr往往不是這樣,你可能會發現打破循環可以提高你的模塊性,特別是你單獨測試組件的能力。

要使用您的示例,視圖是否真的需要getApplication(),這可能會返回一個相對「重」的對象(即其本身需要數據庫,網絡等的對象)? 也許 ......但也許不是。如果你真的需要從getApplication得到一些回調(比如當用戶啓動一些動作),那麼在這個回調的一些通用包中創建一個接口會很有用。因此,而不是:

com.foo.app.Application 
com.foo.view.View 
    Application getApplication() 

你必須:

com.foo.common.Callback // maybe just a Callable, Runnable, etc? 
com.foo.app.Application 
    provides a Callback for some action foo 
com.foo.view.View 
    Callback getFooCallback() 

你應該問的問題是:是什麼給我?這可能是因爲你必須剔除太多以至於不能給你太多的東西 - 儘管這可能意味着你可以將課堂分解一些。但它可能是因爲它實際上更容易測試你的視圖,因爲現在你的單元測試可以(1)在不旋轉整個應用程序的情況下測試視圖,並且(b)提供一個「虛擬」回調,描述動作的字符串,然後你的單元測試聲明它保存了正確的字符串。

+0

讓我請儘量想出其中View.getApplication()可能是合理的情況下。我想這可能是一個視圖通常需要引用通常與應用程序相關的其他資源,比如i18n消息包或JDBC數據源等。也許我們可以用DI方式將它們排序,但我相信定義,在這種情況下,一個視圖是一個複合整體的一部分,不能被認爲是分離的上下文。因此,JDBC數據源不能是任意的,而是其父應用程序提供的。在設計中展示這種依賴關係是不是更清楚? – mysticfall 2013-05-14 05:38:13

相關問題