我最初有以下设置:
表示层使用 - >通过WCF生成的服务代理 - >实际服务程序集(从中生成代理;通过IIS托管) - >域层(业务逻辑) - > DAL
最初是这样,但发现Service和DAL也应该访问域层。现在我有一个场景,在Presentation Layer中,我有一个计算成绩的数据网格,我认为应该在Domain Objects中有规则和计算。
我的问题是:
表示层是否也应引用域对象?这是常见做法吗?
如果是,如果我可以直接访问域对象,为什么还需要服务层?或者我在想传统的n层?如果不是,我该怎么做呢?
非常感谢您的反馈。
UPDATE /编辑:
@Yorro:谢谢你的回复。在您的选项1中,这是我的问题。我无法将要计算的值发送到服务器。我需要立即在UI中反映出来。
例如,我有一个域对象:
public class Grade
{
List<CriterionGrade> children = new List<CriterionGrade>();
public decimal FinalGrade
{
get
{
decimal final = 0;
foreach (CriterionGrade grade in CriterionGrades)
total += line.LineTotal;
return total;
}
}
public IEnumerable<CriterionGrade> CriterionGrades
{
get { return children; }
}
public void AddCriterionGrade(CriterionGrade grade)
{
children.Add(grade);
}
}
我现在正在做的是我有一个DTO成绩,包括孩子,但是,作为DTO,没有商业逻辑。这个DTO与服务层一起在另一台机器上,我使用WCF获得了参考。现在我的演讲是WPF。所以我将DTO绑定到我的DataGrid。
我想要实现的是每当用户更改DataGrid中的等级时,应该强制执行FinalGrade规则(这也就是说,FinalGrade也显示在UI中)。现在,由于生成的代理不包含逻辑/规则,因此我无法访问该规则。我的要求是我需要计算FinalGrade并在任何更改后在UI上显示。
关于如何在不重复逻辑的情况下解决这个问题的任何想法?我唯一能想到的是引用实际的Domain对象并将计算放在服务中,因为DataGrid绑定到代理,但我不确定这是正确还是理想。
答案 0 :(得分:1)
这取决于。
&#34;服务&#34;你提到的是#34;应用服务&#34;在DDD。
如果您的表示层在物理上与域图层分离,您可能需要添加&#34;服务&#34;层(WCF服务,REST服务等),因为在这种情况下您无法引用域模型。
但是如果你的图层只是逻辑上分开,那么引用表示层中的域对象就可以了(在这种情况下,你可以删除你的&#34; service&#34;层)。
&#34;应用服务&#34;图层只是一个&#34; Facade&#34;。它可以通过向前端应用程序(网站,WPF应用程序等)公开更简单的特定于应用程序的API来隐藏域层的复杂性。实际上,拥有它没有对错。你必须问自己,你的域层是如此复杂,你必须添加一个&#34;应用服务&#34;层隐藏复杂性?我宁愿&#34;保持简单愚蠢&#34;在开始。
BTW:我更喜欢在表示层中使用MVVM模式,特别是当你已经在使用像MVF这样的MVVM框架时。在这种情况下,您在视图模型中处理UI逻辑,并将域逻辑委托给域层。
答案 1 :(得分:1)
引用演示文稿中的其他图层
演示文稿可以引用其他层,这是一种常见的做法,因为一些分层架构实现了IoC和DI,但这是另一个主题。
即使演示文稿引用其他图层,也并不意味着演示文稿可以直接访问域图层。您仍然需要考虑是否提交清晰的逻辑分离(或松散耦合的多层体系结构)。表示层仍与服务层通信,无论它们是否分开。
如果您可以直接访问域,为什么要使用服务层?
在DDD中,您只为域名创建一个单独的图层吗?您正确地封装和抽象此域层(使用服务),以便它与应用程序的其余部分(表示)松散耦合,这种松散耦合设计的目的是域中的任何更改都不会影响整个应用程序。 这是DDD的主要卖点。
如果您在整个地方引用域名,则域名中的更改需要您更改应用程序的其余部分,例如涟漪效应。但是如果层被正确分开,每层可以彼此独立地进化,这对于基于团队的开发来说是完美的。
如果您的演示文稿与域(nTier架构)在物理上是分开的并且仍然想要遵守DDD,我有两个建议:
选项1
您可以创建一个&#34;瘦客户端&#34;。它被称为&#34;瘦&#34;因为它不做任何计算或任何艰苦的工作,服务器为他们做了。如果客户端想要计算某些东西,它只是将参数发送到服务器(通过Web API或WCF),然后接收计算结果以供显示。
选项2
如果您的参数太大(整个数据网格)。您可以在演示文稿中包含服务图层。但是逻辑上,演示文稿和服务仍然是分开的。
实际上,您可以以JSON格式发送整个数据网格,并接收最终成绩作为响应。如果您担心表现,请问问自己:
这些是您应该回答的问题,因此您不会落入"premature optimization" trap。