我试图避免此类 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。
现在的问题是-
- 使用组合通过 Facade 公开特定领域的功能是否合理?
- 如果不是,那有什么问题呢?
- 这种方法是否有可能违反任何 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);
}
这是真正的组合,因为您将 ServiceController
与 IServiceDomain
和 ICurrentUser
的实现组合在一起。
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
被迫依赖于 SolutionDomain
和 PhaseDomain
属性,尽管它没有使用
这种设计也很可能会导致违反单一职责原则,因为你传递给客户端的功能越多,它就越倾向于自己做,而不是依赖于其他部分系统。
它也可能会导致违反 Liskov 替换原则 (LSP),因为一般趋势是您在接口(interface)上定义的成员越多,遵守 LSP 的难度就越大。通常,Header Interfaces往往会导致 LSP 违规。
关于c# - 领域/业务层的设计模式选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22193598/