2

大约一年前,我建立了一个由 ASP.Net MVC 3(现在)表示层、应用程序层、域层和基础设施层(横切材料和数据)组成的解决方案。我决定将域模型与域逻辑保持在一个单独的项目中,并通过传递域实体而不是 DTO 对表示层使用一种轻松的方法,因为我们现在实际上只有一个前端。

除了我们的主网站之外,我们将很快为分布式层提供服务,我将在那里使用 DTO,但我也在考虑在主网站中使用 DTO。我还想知道我是否应该费心在域层(IRepository、IUnitOfWork、实体/值对象超类型等)中分解框架代码。那么在这里,让我列出我需要反馈的问题:

1) 我非常努力地避免没有贫血的领域模型,并且还注意特定于演示问题的行为。所需的大多数业务计算都在域实体上,表示层可以直接调用此行为还是应该调用应用程序服务,然后调用域实体?这向我表明,没有理由让表示层知道域实体,而是可以使用 DTO。或者,我可以让 DTO 公开这些行为,但是我觉得我在抢劫域实体。所以我猜这是最好的 3 个选项(直接调用丰富的域对象、服务层或具有行为的 dto)?

2)现在我有一个领域项目,它具有领域服务、规范和逻辑,由应用层和单独的领域模型项目(由表示层和应用层使用)编排。我这里还有通用存储库和工作单元模式的框架接口。我是否应该将框架内容分解为一个单独的项目并将其余部分合并为一个项目?

3)我想将我的领域层重组为聚合,现在所有的领域模型都是由模块组织的,基本上每个模块的所有类型都在一个命名空间中。通过聚合来组织实体、价值对象、服务和其他东西会更好吗?

4) 对于基本上是 .net 框架助手库类型的基础设施服务,我应该使用分离接口模式吗?例如配置对象或验证运行器?这样做有什么好处?

5) 最后,我所见过的使用域实体接口的例子并不多。由于依赖的原因,我几乎所有的对象都喜欢传递接口,它使测试变得更加容易。使用接口而不是混凝土是否有效?我应该提到我们使用 EF 4.3.1(即将升级到最新版本),我似乎记得 EF 在使用接口或其他东西时遇到了问题。我应该公开接口而不是域实体吗?

非常感谢您提前。

项目结构:

Presentation.Web
     | |
     | 应用
     | | |
Domain.Model - 域

(基础设施.数据、基础设施.核心、基础设施.安全)

说明:Presentation.Web(MVC3 Web 项目)

应用程序——编排领域层并响应来自表示层的请求的服务层(获取此更新)。这是按模块组织的,例如,如果我有一个客户模块,我将拥有 Application.Customer,其中包含所有应用程序服务

域——包含域服务、规范、计算和其他不作为域实体行为公开的域逻辑。例如,涉及多个域实体的计算,这些实体公开为应用层调用的域服务。-- 还包含规范框架的框架代码和通用存储库和工作单元模式的主要接口。

Domain.Model -- 包含域实体和枚举。按模块组织。例如,如果我可能有一个客户模块,它有一个客户实体、客户订单实体等。这是从域项目中分离出来的,以便应用程序和表示层可以使用这些对象。

Infrastructure.Security -- 用于身份验证和授权的安全基础设施

Infrastructure.Core - 由多个层(验证器、日志记录、配置、扩展、IoC、电子邮件等)使用的横切内容。大多数项目依赖于该项目中的接口(除了domain.model)来提供基础设施服务。

Infrastructure.Data——通过 LINQ 和 EF 4.3.1 的存储库实现、映射层、工作单元实现。接口在域项目中(分离接口模式)

4

1 回答 1

1

1)首先,确定你的主网站是否真的需要用到应用层。恕我直言,如果您的应用程序服务和您的主网站位于同一 Web 服务器上,那么您应该评估潜在的性能损失是否值得让您的主网站在可以直接调用域对象时调用应用服务器方法。但是,如果您的应用程序服务器肯定在另一台服务器上,那么是的,您应该让应用程序服务器调用您的域对象,并且只在它与您可能拥有的任何表示层(包括您的主网站)之间来回传递 DTO。

2)这确实是一个关于组织偏好的问题。两者都是有效的。你选。

3)关于组织偏好的另一个问题。我个人首先通过限界上下文组织我的代码。然后,我在它们的正下方有实体和聚合根。然后,我有枚举、存储库(接口)、服务(接口)、规范和值的文件夹。命名空间不反映最后一个有界上下文文件夹之后的这种组织结构。但是,同样,您应该以最适合您查看代码的方式来执行此操作。

4)这是一个实施问题。如果我认为将来很有可能需要更换实现,我个人只会将实现问题分解为接口。话虽如此,我通常将我的帮助程序库组织到特定的基础设施上下文中(例如 MainContext.Web.MVC.Helpers 或 MainContext.Web.WebForms.Helpers。)这些很少改变,我还没有遇到我需要的实例完全换掉实现。

5)据我了解,为您的域实体使用接口而不是具体是完全有效的。话虽如此,我还没有遇到过我的域实体需要不同实现的情况。我什至能想到的唯一原因是,如果您需要更改一个应用程序的业务逻辑,但保留使用原始业务逻辑的旧应用程序。如果您的业务对象是该领域的良好模型,我无法理解您实际上会遇到这个问题,但我已经看到人们只是为了抽象而这样做的示例。恕我直言,这不值得额外的编码工作,但如果它让你内心感觉良好或者你获得了一些实际好处(例如,使测试更容易),那么你没有任何理由不能抽象出你的域实体。话虽如此,

答案 5 源于应用程序是选择实现的人的想法。如果您正在尝试实现洋葱架构,那么您的应用程序将为所有内容(存储库、域服务和其他抽象的实现问题)选择具体的实现。我看不出它为什么不能直接使用域聚合,因为它们是域模型的具体表示。(注意:所有实体都应该封装到聚合中。应用程序永远不能持有对在上下文中不是聚合的实体的引用)

于 2012-12-14T21:23:39.487 回答