8

我已經創建了一個基礎設施,我們的品牌新的Intranet項目,並試圖遵循幾乎所有的最佳實踐。另外我也想提一下,這是我第一次從零創建架構。爲基於實體框架的基礎設施實施有界的上下文

目前我的基礎架構的第一個版本已經準備就緒並且工作正常。但是我想在下一個版本中實現有界的上下文結構。

我試圖解釋下面的現狀。

DbCore:負責數據操作。實體框架5代碼首次使用。只有一個DbContext類和其中定義的所有DbSets。此外,GenericRepository模式和工作單元模式基於以下接口實現。

IGenericRepository

public interface IGenericRepository<TEntity> 
    where TEntity : class { 
     void Delete(object id); 
     void Delete(TEntity entityToDelete); 
     System.Collections.Generic.IEnumerable<TEntity> Get(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null, Func<System.Linq.IQueryable<TEntity>, System.Linq.IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = ""); 
     System.Collections.Generic.IEnumerable<TEntity> GetAll(); 
     TEntity GetByID(object id); 
     System.Collections.Generic.IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters); 
     void Insert(TEntity entity); 
     void Update(TEntity entityToUpdate); 
    } 

IUnitOfWork

public interface IUnitOfWork { 
     void Dispose(); 
     IGenericRepository<Test> TestRepository { 
      get; 
     } 
     IGenericRepository<Log> LogRepository { 
      get; 
     } 
     void Save(); 
    } 

型號:用於DbCore和Entity Framework負責存儲實體模型 域:表示業務邏輯層還存儲的DTO的實體存儲在Models項目中的對象。目前業務邏輯存儲在服務類中實現的界面如下 IService

public interface IService<TEntity> { 

     IEnumerable<TEntity> Get(); 
     TEntity GetByID(int id); 
     void Insert(TEntity entity); 
    } 

這個服務類構造函數通過參數得到的UnitOfWork和使用操作。此外Automapper實現將實體對象轉換爲DTO或反之亦然。 從現在起,所有上層不再對實體模型感興趣,只使用DTO。所以幾乎所有的項目(包括api和web)都引用這個項目。

常見問題:負責存儲常用的庫,如日誌記錄。

WebCore:負責存儲API或MVC等基於web的項目的常用庫。還包含基於MVC的項目的擴展,處理程序和過濾器。

Api: ASP.Net MVC Web API項目代表服務層。消費域層並服務於客戶。 控制器獲取IService接口作爲ctor參數,並使用它通過域層訪問數據層。

Web: ASP.Net基於MVC 4的web項目,負責與用戶交互。使用Api方法來訪問數據。所有控制器都有一個名爲IConsumeRepository的接口,它通過HttpClient連接API。

public interface IConsumeRepository<TEntity> { 
     Task<TEntity> Create(TEntity TestInfo); 
     Task Delete(int id);  
     Task<IEnumerable<TEntity>> Get(); 
     Task<TEntity> Get(int id); 
     TEntity New();  
     Task<TEntity> Update(TEntity TestInfo, int entityId); 
    } 

Autofac負責所有項目的IoC和DI。

現在這是我目前的基礎設施,我想我解釋了所有需要評估的內容。

現在,我試圖找出以下的事情,

問題1:有什麼事情一定不能impelemented我使用的方法是什麼?

問題2:實現有界上下文的最佳方法是什麼?我最近觀看了Julie Lerman的視頻並回顧了很多示例項目。常見的事情,我看到從DbContext派生BC。但我無法確定。因爲我曾經認爲BC應該位於域(業務邏輯)層而不是DbCore(數據訪問)層。

問題3:正如我上面提到的,我的Api和Web項目使用DTO,所以它們都需要引用Domain層。但我不喜歡它,因爲我正在使用API​​與UI分離業務層,並將它們再次耦合到實體。但我找不到比這更好的方法。

這成了一個很長的問題,但如果您與我分享您的想法以創建更好的建築,我將非常高興。

回答

30

問題1:假設您有一個複雜的業務領域和重要的業務邏輯,可能值得付出努力,因爲您必須將您的域層與基礎架構問題隔離開來。但是,情況往往不是這樣。如果您主要只是將數據從數據庫移動到UI並返回,那麼這就是過度工程,您應該使用更少的移動部件來尋找。

問題2:您有多少個不同的域模型(使用不同的泛在語言)?一?二?三?對於每個模型,儘可能將其與其他模型和基礎設施問題分開。

Eric Evans的定義界上下文,主要用作語言邊界(引自他的書):

一個限界上下文限定了特定模型的適用性所以 團隊成員有一個明確的並共同理解 的一致性以及它與其他上下文的關係。在該範圍內,努力保持模型在邏輯上統一,但不要擔心 關於在這些範圍之外的適用性。在其他上下文中,其他 模型適用,術語不同,概念和規則, 和通用語言的方言。

的DbContext可能指向你在正確的方向,但請記住它是一個基礎設施神器,域的概念。它「代表工作單元和存儲庫模式的組合,使您能夠查詢數據庫並將所做的更改分組在一起,然後將其作爲一個單元寫回商店。」_(來自MSDN Docs)。

DDD是關於領域建模:使用模型解決複雜業務領域的難題。從技術考慮中推導模型邊界可以感覺到尾巴搖擺狗。從概念上定義模型的邊界,然後相應地調整技術基礎架構。

問題3: DTO可以是一種強制執行上下文邊界的好方法,例如API。然後API可以作爲其他模型的反腐敗層。人們通常將它們用於UI的原因是爲了避免必須將UI概念放到域模型中。

不要尋求一個完美的建築。並意識到「最佳實踐」實際上只是基於特定情況的指導方針。遵循其他更有經驗的人所制定的指導方針,並瞭解到您的情況可能有微妙的差異。當你發現摩擦時,使用你所期望的重構設計決策的期望。例如,如果稍後您發現到用戶界面的DTO過量,則將其刪除。儘可能簡化。

+8

想要在這裏點擊+1幾百次! – 2013-02-15 14:32:35