2016-04-20 123 views
1

我在Gary McLean Hall的C#的單元測試/測試驅動開發部分的適應代碼。我的問題是基於本書中可能包含錯誤的示例。下面是UML圖的樣子爲例AccountService在一個三層架構:我該如何解決這個循環依賴問題?

UML Diagram

我有我的解決方案分成與層對應四個不同的項目:User_Interface,Business_Logic,Data_Access,和Unit_Tests。

我的問題涉及接口IAccountRepository。在這本書的作者寫道的假類用來嘲笑IAccountRepository接口的實現爲使用單元測試下面的代碼(在Unit_Tests項目):

class FakeAccountRepository : IAccountRepository 
{  
    private Account account; 

    public FakeAccountRepository(Account account) 
    { 
     this.account = account; 
    } 

    public Account GetByName(string accountName) 
    { 
     return account; 
    } 
} 

我遇到的問題是, GetByName()方法返回Account類型。如果我嘗試將IAccountRepository中的簽名更改爲Account返回類型,它將找不到該類型。由於Account類是業務邏輯層的一部分,如果我嘗試添加對Business_Logic項目的引用(來自Data_Access項目),Visual Studio會給我一個「循環依賴」錯誤。

circular dependency error

這是有道理的,因爲數據訪問層是底層,而不應依賴於任何層以上本身......但沒有引用我不能在IAccountRepository接口的Account返回類型。

作者是否忘記了一些東西?我應該製作一個IAccount接口,更改GetByName()方法以返回IAccount類型,並使Account實現IAccount接口?如果不是,我該如何解決這個問題?

回答

2

我在這裏看到兩種可能性:

  1. 添加一個名爲「公共」或類似的東西項目 - 商店有賬戶類,並在這兩個數據訪問添加引用通用業務邏輯項目
  2. 爲帳戶創建兩個類:一個在數據訪問中,一個在業務邏輯中。兩者都有相同的字段(屬性)。第二類應該是名稱AccountModel。 這是我見過的專業解決方案。基本上,數據訪問層具有實體類,業務邏輯層具有模型類。當服務從存儲庫中提取數據時,它將Account類型的對象映射到類型對象AccountModel
+0

感謝您的回覆。添加對「Common」項目的引用是否不會創建對它的依賴?我試圖學習最佳實踐,書中特別提到DAL應該能夠獨立地站在其他層面上。 DAL上的圖層取決於DAL,但DAL不能依賴於它上面的圖層。正因爲如此,我更傾向於選擇2.你認爲這是作者的意圖和意外遺漏嗎? –

+1

選項2似乎是更好的選擇 - 正如您所提到的,它使DAL成爲獨立的功能包。 「共同」項目的混亂,所以我不會真正使用它 - 它是在那裏指出第二種方法的優點。 關於作者縮進 - 我只能猜測。也許他希望讀者自己修復它,比如下面提到的@Robert - 作者可能已經把所有東西放在一個項目中,但是不同的名稱空間。我認爲這對於演示,教育目的來說很好。 –

2

作者很可能將其作爲單個可執行文件編寫並將所有內容都放在單個項目中,以便數據訪問層可以看到帳戶類。

你可以自己做,只需將「圖層」分成不同的命名空間以提供邏輯分離。

+0

感謝您的回覆。在這個例子之前的章節是通過多層架構/依賴管理的最佳實踐以及每個層應該如何在它自己的程序集中。這是本書的主要主題。因此,我不認爲作者在一個項目中完成了所有工作...... –

+0

另外,如何將應用程序分隔成名稱空間而不是項目,可以修復DAL仍然需要依賴於業務邏輯的事實它違背了DAL不應該依賴於它自身之上的任何層的原則? –

+1

這是理論達到實際應用的地方。您將不得不在重複代碼(爲每個項目創建一個Account類)和創建包含在不同層之間共享的代碼的共享庫之間進行選擇。這是微服務架構的一個常見問題。編輯:創建共享庫將創建一個依賴項,但它將允許獨立程序集。重複的類將允許獨立的程序集,但是更難管理代碼更改。 – Robert

0

我最終採取了不同於這裏的答案的方法。我在數據訪問層中創建了一個名爲IAccount的接口,並使用IAccount作爲GetByName()方法的返回類型。這解決了我的問題,並仍然保持分層架構。