我试图避免这个类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);
}
注意Home()
中的第一个语句domain.ServiceDomain.GetServicesWithDetails(rec => rec.CreatedBy == currentUser.Name);
我发现自己在ContentDomain类中混合了Facade和Composition。
现在的问题是 -
答案 0 :(得分: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);
}
这是 true Composition ,因为您使用ServiceController
和IServiceDomain
的实现撰写ICurrentUser
。
如果没有,可能会有什么问题?
IContentDomain
的设计存在一些问题。
IContentDomain
添加其他服务时,都需要将其作为(只读)属性添加到接口,这是一个重大变化。 ServiceController
的建议构造函数,看起来好像只有两个依赖项传递给ServiceController
,但实际的数字是4。平面构造函数注入的一大好处是it makes it quite clear when the Single Responsibility Principle is violated。我有可能通过这种方法违反任何SOLID原则吗?
是的,这种设计违反了SOLID,因为它至少违反了接口隔离原则,该原则规定不应强迫客户端依赖于他们不使用的成员。
但是,在上面的示例中,ServiceController
被强制依赖SolutionDomain
和PhaseDomain
属性,尽管它不使用它。
这种设计很可能会导致违反单一责任原则,因为您传递给客户的功能越多,它本身就越倾向于做,而不是依赖于其他部分。系统
它也可能导致违反Liskov替换原则(LSP),因为一般的趋势是你在接口上定义的成员越多,就越难以遵守LSP。通常,Header Interfaces往往会导致LSP违规。