2008-12-22 63 views
3

我正在重構我們的BI層以使我們的代碼更「鬆散耦合」,我有興趣聽到你們認爲可能會有趣的改進?更改我們的BL設計 - 哪種模式最有用?

目前,我們的API是類似以下內容: -

// Fetch a collection of objects 
ProductCollection prods = Product.GetProducts(); 

// Load an individual object, make change and save it back 
Product p = new Product(); 
if(p.Load(productID)) 
{ 
    p.Name = "New Name"; 
    p.Save(); 
} 

正如你所看到的,我們用來獲取對象的集合/加載單個對象和保存更改方法都是建立在「模式」類。我們的每個Model類都繼承自一個ObjectBase基類,該基類包含數據庫訪問函數和更改跟蹤,所以當有人通過屬性更改值時,該對象會自動標記爲髒,並且通知會觸發任何對象(UI)訂閱了這些事件。

我想要做的就是使用「存儲庫模式」,以便我們可以將數據庫實現從模型中抽象出來。然而,我一直在研究的大部分代碼似乎都暗示「模型」類不應該包含任何智能,應該只是數據的容器。相反,邏輯應該通過使用服務來應用。這是否意味着,然後完成上述,我需要做的是這樣

List<Product> prods = ProductService.GetProducts(); 

Product p = ProductService.GetSingleProduct(productID); 
p.Name = "New Name"; 

ProductService.SaveProduct(p); 

這似乎做的更復雜的方式使得它更難的業務對象中封裝的功能。

有人可以解釋爲什麼這是一個更好的做法,或者我誤解了這些概念?

感謝

詹姆斯

回答

6

您當前的API是Active Record Pattern的實施。 當代碼中使用的對象模型是與數據庫模型的一對一匹配時,此模式可以正常工作。另一個優點是存在工具來生成這些類,包括持久性代碼和數據庫表。

您建議的替代方法是存儲庫模式。正如你已經提到的那樣,這有點複雜,但有幾個優點。 由於您可以實現任何種類的ORM工具,因此您不僅限於一對一映射,還可以實現更復雜的映射,其中對象模型可能與數據庫模型不同。因此,您不必強制數據庫中的對象模型或其他方式。 然而,更復雜的映射,除了一對一之外無法生成,並且需要一些

另一個優點是您可以更容易地創建測試,因爲您可以創建一個甚至不需要的模擬存儲庫一個數據庫。

使用存儲庫模式,您還可以將模型與持久性邏輯分開。

在這兩種情況下,都可以使用通用方式編寫持久性方法,以便持久性代碼是通用的,不需要了解需要持久化的特定對象。這對於Active Record Pattern來說是顯而易見的,因爲所有這些對象都實現了保存,刪除,更新等。對於Repository Pattern,您還可以使用適用於任何對象的ORM工具,以便可以這樣編碼:

Repository.Save(ObjectOfAnyType); 

只要ORM工具爲該對象的類型定義/實現了一些映射,ObjectOfAnyType就可以是任何東西。

所以你選擇,你想要或需要這些優勢,但增加一點複雜性的代價。或者,活動記錄模式的簡單性就足夠了。

我總是傾向於使用存儲庫模式,但有時會使用活動記錄模式,主要用於快速原型設計。

2

我認爲這裏的主要問題是關注點分離:爲什麼你的業務對象照顧它是如何堅持?爲什麼你的持久層關心你的業務對象是如何驗證或執行業務邏輯的呢?通過將兩者分開,可以清楚地區分對象如何從業務角度運行以及如何從數據庫中保存/檢索它們。因此,您的業務對象變得不那麼複雜(這很好),並且您可以更容易地在持久層中利用共同優勢來減少所需的代碼量。

這真的幫了我一個例子,就是模型對象的子類化。當我將保存邏輯構建到模型中時,我將從BI基類中派生出相當多的邏輯,並實現一個虛擬方法來在Model類中實際保存對象。只要我的BI模型層次結構是平坦的,這就工作得很好。當想要對模型進行子類化時,它會爆炸。那時我不得不重新實現了很多保存的代碼,因爲如果不重新使用父代碼,我不能使用Base類代碼 - 這是我無法做到的。

我已經轉向使用LINQ作爲ORM,現在保存/檢索邏輯位於DataContext中,業務邏輯在每個業務實體的部分類中實現。這些類通過知名接口實現驗證(和其他業務邏輯)和負載檢查。 DataContext使用該接口來執行所需的操作,以確保在保持對象之前已滿足業務規則。現在我的模型類更單一,更容易維護。 LINQ強制對子類進行一些約束,但是我可以通過構造接口來解決這個問題,或者如果需要的話,可以重新修改我的數據庫表以支持它們的子類約束。總而言之,我發現它是一個巨大的改進。

0

@tvanfosson,@Marco Tolk 感謝您的迴應,非常有用。

我真的很喜歡存儲庫模式帶來的問題分離。它確實增加了對象之間的更多依賴關係,但我想使用像StructureMap之類的東西可以有效地將其作爲一個障礙。

但是,我仍然不喜歡簡化的'模型'概念。與對象有關的邏輯(比如上面例子中的「產品」)不應該包含在對象本身中嗎?例如,如果我將產品對象綁定到編輯器,我希望它修改對象的屬性,然後當用戶點擊保存時,讓產品自己保存(可能通過存儲庫)。當業務對象「知道」足以在不通過另一個服務管道的情況下堅持自己時,在UI和業務對象之間提供服務是沒有意義的。