2009-11-03 30 views
4

我在寫一個使用DDD技術的應用程序。這是我第一次嘗試DDD項目。這也是我的第一個綠地項目,我是唯一的開發者。我充實了域模型和用戶界面。現在我開始持久層。像往常一樣,我從單元測試開始。我在數據持久層中需要多少抽象級別?

[Test] 
public void ShouldAddEmployerToCollection() 
{ 
    var employerRepository = new EmployerRepository(); 
    var employer = _mockery.NewMock<Employer>(); 

    employerRepository.Add(employer); 
    _mockery.VerifyAllExpectationsHaveBeenMet(); 
} 

正如你所看到的,我沒有寫任何對Add()函數的期望。我得到了這一點,並意識到我還沒有解決特定的數據庫供應商。實際上,我甚至不確定它需要一個數據庫引擎。平面文件或xml可能同樣合理。所以我不知道我的下一步應該是什麼。

我應該添加一個抽象層......說一個DataStore接口或尋找一個已經爲我工作的現有庫嗎?如果可以的話,我想避免將程序綁定到特定的數據庫技術上。

回答

8

根據您的要求,您真正需要的唯一抽象是具有基本CRUD語義的存儲庫接口,以便您的客戶端代碼和協作對象僅處理IEmployerRepository對象而不處理具體存儲庫。你有幾個選擇去做:

1)沒有更多的抽象。只是構建您的頂級應用程序的具體信息庫在你需要它:

IEmployeeRepository repository = new StubEmployeeRepository(); 
IEmployee   employee = repository.GetEmployee(id); 

改變,在一百萬的地方會變老,所以這種技術只適用於非常小的項目確實可行。

2)創建倉庫工廠在應用程序中使用:

IEmployeeRepository repository = repositoryFactory<IEmployee>.CreateRepository(); 
IEmployee   employee = repository.GetEmployee(id); 

你可能倉庫工廠傳遞到將使用它的類,或者您可以創建一個應用程序級的靜態變量來保存它(這是一個單身人士,這是不幸的,但相當有限)。

3)使用依賴注入容器(本質上是通用的工廠和配置機制):

// A lot of DI containers use this 'Resolve' format. 
IEmployeeRepository repository = container.Resolve<IEmployee>(); 
IEmployee   employee = repository.GetEmployee(id); 

如果你還沒有使用DI容器之前,也有很多很好的問題及答案關於他們在這裏(如Which C#/.NET Dependency Injection frameworks are worth looking into?Data access, unit testing, dependency injection),你一定要讀馬丁福勒的Inversion of Control Containers and the Dependency Injection pattern)。

+0

針對存儲庫接口的+1 – 2009-11-03 14:37:12

+0

EmployerRepository實際上實現了IEmployerRepository接口,該接口公開CRUD操作。你是否建議我應該實現數據庫感知的具體類,如SQLServerEmployerRepository,OracleEmployerRepository,FlatFileEmployerRepository等,直到我決定數據庫技術? – 2009-11-03 14:49:37

+0

在這種情況下,我試圖TDD我的方式來實施IEmployerRepository,但我想我不能這樣做,除非我要在存儲庫下面添加另一個抽象級別(這似乎沒有添加任何有用的東西),編寫和測試幾個數據庫相關的實現,或者選擇一個數據庫並堅持使用它。 – 2009-11-03 15:08:00

1

在某些時候,您將不得不打電話瞭解您的存儲庫將如何處理數據。當你開始你的項目時,最好儘可能保持簡單,並且在必要時只添加抽象層。在這個階段簡單定義你的倉庫/ DAO可能就足夠了。

通常,存儲庫/存儲庫/ DAO應該知道您決定使用哪個數據庫或ORM的實現細節。我期望這就是你在DDD中使用倉庫的原因。通過這種方式,您的測試可以模擬存儲庫,並且可以不執行實現。

0

有一件事我已經與持久層發現的是,以確保有一個地方,你可以開始做抽象。如果數據庫增長,則可能需要開始實施分片,除非已經有可用的抽象層,否則稍後添加抽取層可能會很困難。

0

我相信你不應該爲了單元測試的目的在存儲庫類下面增加另一層,特別是如果你沒有選擇你的持久化技術。我不認爲你可以創建一個比「repository.GetEmployee(id)」更細粒度的接口,而不會公開有關持久化方法的細節。

如果你真的在考慮使用平面文本或XML文件,我相信最好的選擇是堅持存儲庫接口抽象。但是如果你決定使用數據庫,而你對供應商不確定,那麼一個ORM工具可能就是要走的路。