Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 域/业务层的设计模式选择_C#_Design Patterns_Composition_Facade - Fatal编程技术网

C# 域/业务层的设计模式选择

C# 域/业务层的设计模式选择,c#,design-patterns,composition,facade,C#,Design Patterns,Composition,Facade,我试图避免此类ContentDomain成为一个God类,并将功能隔离到特定类中(遵循SRP),如下所示 ContentDomain: public class ContentDomain : IContentDomain { private ISolutionDomain solutionDomain; private IServiceDomain serviceDomain; private IPhaseDomain phaseDomain; public

我试图避免此类ContentDomain成为一个God类,并将功能隔离到特定类中(遵循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();
    }
}
注意Home()中的第一条语句

我发现自己在ContentDomain类中混合了Facade和Composition

现在问题是-

  • 使用组合通过Facade公开特定的域功能合理吗
  • 如果没有,可能有什么问题
  • 我用这种方法违反任何坚实原则的可能性
  • 使用组合通过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);
    }
    
    这是真正的组合,因为您使用
    IServiceDomain
    ICurrentUser
    的实现组合
    ServiceController

    如果没有,可能有什么问题

    IContentDomain
    的设计存在几个问题

    • 它更难维护,因为每次您想向
      IContentDomain
      添加另一个服务时,都需要将其作为(只读)属性添加到接口中,这是一个突破性的更改
    • 它可能隐藏了更多的依赖性,而不是显而易见的。查看提议的
      ServiceController
      构造函数,看起来只有两个依赖项被传递到
      ServiceController
      ,但实际数量是四个。平面构造函数注入的最大好处之一是
    • 它违反了接口隔离原则(见下文)
    我用这种方法违反任何坚实原则的可能性

    是的,此设计违反了SOLID,因为它至少违反了接口隔离原则,该原则规定不应强迫客户端依赖于他们不使用的成员

    但是,在上面的示例中,
    ServiceController
    被强制依赖于
    SolutionDomain
    PhaseDomain
    属性,尽管它没有使用它

    这种设计也很可能会违反单一责任原则,因为您向客户传递的功能越多,客户就越倾向于自行完成,而不是依赖系统的其他部分


    它还可能导致违反Liskov替换原则(LSP),因为有一种普遍趋势,即在接口上定义的成员越多,就越难遵守LSP。通常,这会导致LSP冲突。

    我发现很难理解这个问题,因为它太抽象了(一切都是一个接口)。除了
    currentUser.Name
    之外,我真的看不出您正在公开什么“特定域功能”。你的问题3太宽泛了。设计是各种各样的折衷,所以答案是你最有可能(在一个复杂的项目中)在某个地方违反实体。TL;DR您的问题需要更具体才能得到答案。SolutionDomain类表示特定的域功能,该功能公开为domain.solutionDomainHanks@Mark。这很有帮助。但是我的ServiceController(现在的ContentController)需要的不仅仅是ServiceDomain。它需要SolutionDomain、PhasedMain等的功能。我不确定这些域类型是否应该注入到我的ContentController中。这就是我在ContentDomain类中包装所有特定域类型的原因。有人帮忙吗?请参阅我的编辑:ServiceController重命名为ContentController。您是否建议在我的客户端应用程序中为ServiceDomain、SolutionDomain和PhaseDomain设置单独的使用者(控制器)?是的,通过这种方式,它更接近ISP(和SRP),但随后它变成了一个ASP.NET MVC特定的问题。如果您的控制器有太多依赖项,您希望了解它,因为这是一个问题(它表明违反了SRP)。这是上面的第二个要点。在
    IContentDomain
    后面隐藏许多依赖项并不能解决这个问题:它只会隐藏它;一开始就很难发现你有问题。听起来你可以从引入Facade服务中获益:这是一个很好的答案,有一些宝贵的链接,就像
    Facade Services
    @MarkSeemann,一篇关于聚合的好文章。但我更倾向于将客户端的每个域功能隔离到单独的控制器中。例如,带有ISolutionDomain注入的SolutionController。
    domain.ServiceDomain.GetServicesWithDetails(rec => rec.CreatedBy == currentUser.Name);
    
    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);
    }