DDD(领域驱动设计),是一组模式、原则和实践,帮助我们解决和理解面向对象系统设计中的业务问题(领域)。DDD 是一个非常广泛的话题。
我一直在使用 Windows 窗体中的 N-Layers 架构,但在 ASP.NET MVC 中我有疑问,因为我是一个在 Web 系统上工作的初学者。
让我们关注 DDD 架构。
让我们直接解决我遇到的问题。从域实体开始是具有身份的对象,并且在我们的应用程序的业务逻辑中很重要,但它们不必被应用程序的其他层直接知道。
这是我项目的结构。
我正在使用DTO或数据传输对象是主要目标是简化将在进程之间交换的对象的类。
在Application Layer,我有两个项目:Application Services和Adapters。
- 适配器:这是我实现 DTO 的地方。
- 应用程序服务:我在这一层实现应用程序方法,因为我的表示层不知道域层,反之亦然。回到主题,正是在这一层中,我通过 AutoMapper 将域实体变成了 DTO。
域实体。
public class Proveedor
{
public int ProveedorId { get; set; }
public string RazonSocial { get; set; }
public string Direccion { get; set; }
}
DTO
public class ProveedorDto
{
[Key]
public int ProveedorId { get; set; }
[Display(Name = "Razón Social")]
public string RazonSocial { get; set; }
[Display(Name = "Dirección")]
public string Direccion { get; set; }
}
在应用程序服务中应用 AutoMapper。
public IEnumerable<ProveedorDto> GetAll()
{
IEnumerable<Proveedor> _proveedor = _sdProveedor.GetAll();
config = new MapperConfiguration(cfg => cfg.CreateMap<Proveedor, ProveedorDto>());
IEnumerable<ProveedorDto> listDto = config.CreateMapper().Map<IEnumerable<ProveedorDto>>(_proveedor);
return listDto;
}
这样,我的域实体不会到达表示层,并且适配器层中的 DTO 被用作 MVC 设计模式的模型。
- 我应该在表示层中创建模型,我是否必须坚持模型在该层中实现的字母,正如 MVC 所说的那样?
- 我应该如何使用良好的实践来实现我已经解释过的那部分,以便我的架构整洁?
我认为重要的是要清楚理论与实践之间的区别。在整个应用程序中,您会发现自己在许多情况下会迫使您打破该理论以追求生产力和效率。作为应用程序的架构师,您可以做出决定。
根据我的个人经验,模型不会在表示层上绘制任何内容。我首先将它们放在持久层中,这是它们的理想位置,最后放在称为“基础架构”的横向层中,因为无论哪种方式,很容易最终需要它们在其他层中的引用。理论上,与持久性相关的所有内容,包括模型,都应该位于该层中。域不应该与模型有任何关系或知道它们的存在。
如果你是一个架构纯粹主义者,并且能够将层之间的耦合减少到零,那么你就已经达到了理想的架构,但我坚持很多时候必须打破那些规则,用头脑做事。随着时间的流逝,您已经使用该应用程序工作了很长时间,您会意识到自己做得好的事情和做错的事情。
老兄
事实上,反之亦然,整个应用程序都必须知道域。DDD 背后的想法是创建一个业务模型,它是一个可以工作并解决业务问题的黑盒。
因此,重点是创建一个实体交互和协作的生态系统。
说得更清楚一点,这个概念大概是这样的:太阳本身的存在是有影响的,它的光、它的引力影响着行星、气候,所以在这个领域发生的每一个事件都应该是这样的。
在您的模型中,如果我有一个会计系统并且在将消息发送到它必须验证、影响其他实体并在必要时注册或可能修改某些内容的模型时必须输入发票,则必须发生这种情况。
所有这些逻辑都封装在域中,使得操作不典型:
_repisitorio.invoices.add(发票)
但
model.Invoices.RegistrarFactura(发票)
在生成所有逻辑时,您将其封装在能够处理其自身操作的域中,这使其非常有价值。
同样重要的是要提到域与持久性无关,因为即使没有持久性的域几乎没有用,它也应该能够在没有持久性的情况下工作。
现在使用域到用户对象转换的原因是因为在 mvc 中,结果是通过视图模型完成的,而在域中,概念可能涉及业务实体之间的一种协作,这不会使其成为向用户表示的候选对象。
例如,您可以有一个采购订单及其商品,并且来自 ui 的用户会显示采购订单和商品数量,显然这必须进行处理,结果将填充一个准备显示的视图模型
另一个重要的概念是,通过专注于一个领域,我们不再谈论孤立的概念,例如在某些事物具有典型的实体之前
Emp 现在是 Employee。很简单,对吧?
实体必须在团队中所有人都通用,这就是所谓的泛在语言,可以说口语不应该像以前那样有抽象,但你应该可以和业务专家交谈关于相同的概念。
同样重要的是,要对领域进行建模,它不是在您的脑海中诞生的,业务的领域总是已经存在的,要做的就是与了解业务的人交谈,然后将其传递给代码,这就是为什么重要的是要很好地理解它,因为如果您不可能留空因此无法解决所有问题,它会起作用。
查看 Eric Evans 的书,域驱动设计
错误,它们在所有级别都可以看到,但用户不一定必须知道它们。
我应该在表示层中创建模型,我是否必须坚持模型在该层中实现的字母,正如 MVC 所说的那样?
由于它是在 mvc 中实现的,它与 ddd 无关,但很重要的一点,动作与视图模型密切相关,正如它的名字所说,它是视图的模型,即页面的模型,它具有与您的域无关,因为它存在的原因是视图或页面,这是在 mvc 中处理的概念。
我应该如何使用良好的实践来实现我已经解释过的那部分,以便我的架构整洁?
没有食谱,你必须自己记录。
对于 mvc 页面,使用自定义视图模型,这是为该网页设计的模型,并填充了作为 DTO 的域实体的数据。您向业务层发出请求,该业务层返回一个域对象 (dto) 并将其映射到您的自定义视图模型。通过这种方式,您可以根据自己的喜好为您的网页创建本地模型,这些模型可以由一个或多个域对象提供支持。