2014-03-05 46 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 –