2014-03-05 74 views
4

我試圖避免此類ContentDomain成爲神級和隔離功能集成到特定的類別(按照SRP)這樣設計模式的選擇域/業務層

ContentDomain

public class ContentDomain : IContentDomain 
{ 
    private ISolutionDomain solutionDomain; 
    private IServiceDomain serviceDomain; 
    private IPhaseDomain phaseDomain; 

    public ContentDomain(IUnitOfWork _unitOfWork) 
    { 
     this.solutionDomain = new SolutionDomain(_unitOfWork); 
     this.serviceDomain = new ServiceDomain(_unitOfWork); 
     this.phaseDomain = new PhaseDomain(_unitOfWork); 
    } 

    public ISolutionDomain SolutionDomain { get { return solutionDomain; } } 
    public IServiceDomain ServiceDomain { get { return serviceDomain; } } 
    public IPhaseDomain PhaseDomain { get { return phaseDomain; } } 
} 

一個特定的領域類的

public class SolutionDomain : BaseDomain, ISolutionDomain 
{ 
    public SolutionDomain(IUnitOfWork _unitOfWork) 
     : base(_unitOfWork) 
    { 

    } 

    public IEnumerable<Solution> GetAllSolutions() 
    { 
     return base.GetAll<Solution>(sol => sol.IsActive == true).OrderBy(rec => rec.Name).Select(rec => rec).ToList(); 
    } 
} 

而且現在我的控制器只知道ContentDomain和從SolutionDomain/ServiceDomain/PhaseDomain調用具體方法爲,並在需要的時候:

public ContentController(IContentDomain domain, ICurrentUser currentUser) 
     : base(domain, currentUser) 
    { 

    } 


public ActionResult Home() 
    { 
     var myServices = domain.ServiceDomain.GetServicesWithDetails(rec => rec.CreatedBy == currentUser.Name); 
     var viewModelCollection = myServices.Select(service => new DashboardViewModel(service, domain)); 

     if (currentUser.IsInRole("SU")) 
      return View("Home_SU", viewModelCollection); 

     else if (currentUser.IsInRole("Reviewer")) 
      return View("Home_Reviewer", viewModelCollection); 

     else return View("Home", viewModelCollection); 
    } 

請注意,在首頁的第一條語句()

domain.ServiceDomain.GetServicesWithDetails(rec => rec.CreatedBy == currentUser.Name); 

我發現自己混合門面和ContentDomain類中的組合。

現在的問題是 -

  1. 是否合理使用組成直通門面公開特定域的功能?
  2. 如果不是的話,那可能是什麼情況?
  3. 機會我違反了這種方法的任何固體原則?
+0

我覺得很難理解這個問題,因爲它太抽象了(一切都是一個界面)。除了'currentUser.Name'之外,我並不真正看到你所暴露的「特定域功能」。你的問題3太寬泛。設計是各種各樣的妥協,所以答案很可能(在一個複雜的項目中)在某處違反了SOLID。 TL; DR你的問題需要更加具體才能得到答案。 – Fuhrmanator

+0

SolutionDomain類表示作爲domain公開的特定域功能。解決方案域 –

回答

4

通過Facade使用組合來公開具體的域功能是否合理?

基於該示例,ContentDomain類和IContentDomain接口不提供功能。組成一個更好的形式將客場都扔了,並基於最小的相關性集合它們需要定義控制器和其他客戶:

private readonly IServiceDomain serviceDomain; 
private readonly ICurrentUser currentUser; 

public ServiceController(IServiceDomain serviceDomain, ICurrentUser currentUser) 
{ 
    this.serviceDomain = serviceDomain; 
    this.currentUser = currentUser; 
} 

public ActionResult Home() 
{ 
    var myServices = this.serviceDomain.GetServicesWithDetails(
     rec => rec.CreatedBy == currentUser.Name); 
    var viewModelCollection = myServices.Select(
     service => new DashboardViewModel(service, domain)); 

    if (this.currentUser.IsInRole("SU")) 
     return View("Home_SU", viewModelCollection); 

    else if (this.currentUser.IsInRole("Reviewer")) 
     return View("Home_Reviewer", viewModelCollection); 

    else return View("Home", viewModelCollection); 
} 

這是真實成分,因爲您撰寫ServiceController與實現IServiceDomainICurrentUser

如果不是這樣,那可能是什麼情況?

IContentDomain的設計有幾個問題。

  • 它更難以維持,因爲每次你要到另一個服務添加到IContentDomain,您需要將其添加爲(只讀)屬性的接口,這是一個重大更改。
  • 它可能隱藏起來的依賴性比立即顯現的更多。看看ServiceController的建議構造函數,它看起來好像只有兩個依賴關係被傳入ServiceController,但實際數量是四個。扁平構造器注入的一大優點是it makes it quite clear when the Single Responsibility Principle is violated
  • 它違反了接口隔離原則(見下文)。

機會我用這種方法違反了任何SOLID原則?

是的,因爲,起碼,它違反了接口隔離原則,其中指出,客戶不應該被迫依賴於它們不使用成員這樣的設計違反了固體。

但是,在上面的示例中,ServiceController被迫依賴於SolutionDomainPhaseDomain屬性,儘管它不使用它。

這種設計很可能會導致違反單一職責原則,因爲您傳遞給客戶的功能越多,其傾向於自行執行的功能就越多,而不是依賴於其他部分系統。

這也可能導致違反Liskov替換原則(LSP),因爲一般趨勢是您在界面上定義的成員越多,遵守LSP的難度就越大。通常,Header Interfaces往往會導致LSP違規。

+0

謝謝@Mark。這很有幫助。但是我的ServiceController(現在的ContentController)需要比單獨的ServiceDomain多得多。它需要來自SolutionDomain,PhaseDomain等的功能。 而我不確定是否應該在我的ContentController中注入這些多個Domain類型。這就是我在ContentDomain類中包裝所有特定域類型的原因。這裏有幫助嗎? 查看我的編輯:ServiceController重命名爲ContentController。 –

+0

您是否建議在我的客戶端應用程序中爲ServiceDomain,SolutionDomain和PhaseDomain分別使用消費者(控制器)?是的,這樣它靠近ISP(和SRP),但它成爲一個ASP.NET MVC的特定問題。 –

+3

如果你的控制器有太多的依賴關係,你想知道它,因爲這是一個*問題*(它表明SRP被違反)。這是上面的第二個要點。隱藏IContentDomain背後的許多依賴不能解決那個問題:它只隱藏它;它使得很難發現你首先遇到了問題。這聽起來像你可以從引進門面服務中受益:http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices –