c# - 领域/业务层的设计模式选择

标签 c# design-patterns composition facade

我试图避免此类 ContentDomain 成为上帝类,并将功能隔离到特定类中(以遵循 SRP),就像这样

内容域:

 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();
    }
}

现在我的 Controller 只知道 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);
    }

注意 Home() 中的第一条语句

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

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

现在的问题是-

  1. 使用组合通过 Facade 公开特定领域的功能是否合理?
  2. 如果不是,那有什么问题呢?
  3. 这种方法是否有可能违反任何 SOLID 原则?

最佳答案

Is it reasonable to expose specific domain functionality thru Facade using composition?

根据示例,ContentDomain 类和IContentDomain 接口(interface)不提供任何功能。更好的组合形式是抛弃两者,并根据它们需要的最小依赖集定义 Controller 和其他客户端:

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);
}

这是真正的组合,因为您将 ServiceControllerIServiceDomainICurrentUser 的实现组合在一起。

If not, what could be the catch?

IContentDomain 的设计存在几个问题。

  • 它更难维护,因为每次你想向 IContentDomain 添加另一个服务时,你需要将它作为一个(只读)属性添加到接口(interface)中,这是一个突破性的变化。
  • 它可能隐藏了比立即显现的更多的依赖关系。查看建议的 ServiceController 构造函数,看起来好像只有两个依赖项被传递到 ServiceController 中,但实际数量是四个。平面构造函数注入(inject)的一大好处是 it makes it quite clear when the Single Responsibility Principle is violated .
  • 它违反了接口(interface)隔离原则(见下文)。

Chances I am violating any of the SOLID principles with this approach?

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

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

这种设计也很可能会导致违反单一职责原则,因为你传递给客户端的功能越多,它就越倾向于自己做,而不是依赖于其他部分系统。

它也可能会导致违反 Liskov 替换原则 (LSP),因为一般趋势是您在接口(interface)上定义的成员越多,遵守 LSP 的难度就越大。通常,Header Interfaces往往会导致 LSP 违规。

关于c# - 领域/业务层的设计模式选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22193598/

相关文章:

java - 具有单例模式和静态方法和变量的多个子类

programming-languages - "compose well"对某些东西意味着什么?

c# - 您不需要将对象名称传递给构造函数吗? “new Class()”还不是对象

jsf - <f :viewParam> not working when using <ui:composition template>

c# - 在 .Net 中设置/删除事件处理程序

c# - Byte Vigenere Cipher,解密错误

c# - .Net 4.0 重构现有 "if"条件和 "is"运算符的优化代码

c# - 禁用和启用后 WPF 文本框焦点 "sticking"

c# - 如何正确设置执行子 powershell 脚本的路径?

design-patterns - 复制粘贴编码是否可以接受?