3

我正在创建一个应用程序,其架构基于鲍勃叔叔的清洁架构概念和DDD。请注意,它基于DDD,所以我给了自己与严格 DDD 不同的自由。

为了创建这个应用程序,我使用 C# 和 .Net Standard 2.0

DDD 的原则之一与值对象有关。根据Wikipedia ,值对象的定义如下:

值对象

包含属性但没有概念标识的对象。它们应该被视为不可变的。

示例:人们在交换名片时,一般不会区分每张唯一的名片;他们只关心印在卡片上的信息。在这种情况下,名片是价值对象

现在,如果某些验证不成功,我希望我的值对象不允许创建它们。当它发生时,实例化过程中会抛出异常。我真的打算在那里抛出一个异常,因为架构的核心确实不希望任何无效数据到达那个点。

在进一步讨论这个问题之前,为了给你们更多的背景知识,是我的架构(注意:仍然不完整):

我的清洁架构提案

我在这个架构中遵循的规则是:

  1. 一个层只能知道其最内层邻居层的接口
  2. 一个层不能知道任何最外层的任何信息
  3. 层之间的所有通信都必须通过接口完成
  4. 每一层都必须是可独立部署的
  5. 每一层都必须是可独立开发的

为了更好地理解此图中的箭头,我建议阅读 Stack Exchanges 的问题:

UML 箭头的解释

https://softwareengineering.stackexchange.com/questions/61376/aggregation-vs-composition

现在,我现在面临的挑战是找到一种使用验证器的好方法。在这一点上,我对我的架构并不满意。问题如下:

由于我可以在给定时间实例化数千个值对象,因此我不希望值对象的每个实例都有一个实例方法来执行验证。我希望验证方法是静态的,因为每个实例的逻辑都是相同的。此外,我希望架构的上层可以使用验证逻辑来​​执行验证,而无需尝试实例化值对象,从而导致抛出昂贵的异常。

问题是:C# DOES NOT ALLOW polymorphism with static methods,所以我不能做类似的事情:

internal interface IValueObject<T>
{
    T Value { get; }
    static bool IsValid(T value);
}

如何在不依赖静态方法多态性的情况下实现此功能,同时又不浪费内存?

4

3 回答 3

1

您可以抽象地思考是一件好事,但您应该在编写一些工作代码后进行概括。

一个通用的、大小合适的架构 DDD 是一个秘诀。事实上,DDD 仅适用于 Domain 层。这就是它的美妙之处,它与技术无关。

在我的项目中,我什至没有值对象、实体或聚合根的基类或接口。我不需要它们。所有这些构建块都是 POPO (PHP)。

在我看来,Clean 架构是保持领域层技术不可知的架构,不依赖于任何外部框架。其他层几乎可以是任何东西。

于 2018-03-16T05:09:00.450 回答
0

在干净的架构中,所有业务逻辑都进入用例交互器。验证规则是业务逻辑的一部分,因此也应该进入用例交互器。

在您的情况下,我建议将您的验证放在采用“请求模型”的交互器中,验证“参数”,然后将相应的值对象作为(部分)响应模型返回。

这样,验证逻辑位于正确的层中,并且仅在验证成功时才创建值对象 - 因此不会创建无效值对象并且不会浪费性能。

于 2019-02-03T16:18:48.317 回答
0

我建议您摆脱IsValid()并让您的值对象自我检查,始终有效的对象。建议使它们不可变,并且在这方面显然会有很大帮助。您只需在创建期间检查一次不变量。

[编辑]

您可能需要将其视为输入验证的第一遍,而不是值对象不变的强制执行。如果有大量的不安全数据进入你想转换成值对象,首先在外层的验证过程中处理它——你可以进行你需要的所有性能优化,实现错误逻辑并在那里协调 VO 创建。

于 2018-03-19T14:37:50.340 回答