BDD/DDD 在哪里放置基本实体验证的规范?

发布于 2024-08-06 16:58:18 字数 167 浏览 1 评论 0原文

或者,基本实体验证是否被视为规范?

一般来说,将基本实体验证(名称不能为 null 或空,日期必须大于 xxx)保留在实际实体中还是在规范中保留在实体之外更好?

如果在规范中,那会是什么样子?您是否会对每个字段都有一个规范,或者将其全部包装在一个 EntityIsValid 类型规范中?

Alternatively, is basic entity validation considered a specification(s)?

In general, is it better to keep basic entity validation (name cannot be null or empty, date must be greater than xxx) in the actual entity, or outside of it in a specification?

If in a specification, what would that look like? Would you have a spec for each field, or wrap it all up in one EntityIsValid type spec?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜嗑 2024-08-13 16:58:18

在我看来,一旦人们了解了一些 DDD,他们就会选择规范模式并希望将其应用到任何地方。这确实是金锤反模式。

我看待规范模式的方式,以及我理解领域驱动设计的方式 的一个优点是,当您需要独立于实体改变业务规则时,您可以选择应用它的设计模式。

请记住,DDD 是一种迭代方法,因此您不必在第一次就将其“正确”。我首先将基本验证放入实体中。这非常符合 OOD 的基本思想,因为它让表示概念的对象了解数据的有效范围。

在大多数情况下,您甚至不需要显式验证,因为实体的设计应使约束表示为不变量,从而不可能创建违反约束的实例。

如果您有一条规则规定 Name 不能为 null 或为空,您可以直接在实体中主动强制执行该规则:

public class MyEntity
{
    private string name;

    public MyEntity(string name)
    {
        if(string.IsNullOrEmpty(name))
        {
            throw new ArgumentException();
        }
        this.name = name;
    }

    public string Name
    {
        get { return this.name; }
        set
        {
            if(string.IsNullOrEmpty(value))
            {
                throw new ArgumentException();
            }
            this.name = value;
        }
    }
}

name 不能为 null 的规则现在是该类的不变量:MyEntity 类现在不可能获取进入一种规则被打破的状态。

如果稍后您发现规则更复杂,或者在许多不同的概念之间共享,您始终可以将其提取到规范中。

It seems to me that once people have learned a little about DDD, they pick up the Specification pattern and look to apply it everywhere. That is really the Golden Hammer anti-pattern.

The way I see a place for the Specification pattern, and the way I understood Domain-Driven Design, is that it is a design pattern you can choose to apply when you need to vary a business rule independently of an Entity.

Remember that DDD is an iterative approach, so you don't have to get it 'right' in the first take. I would start out with putting basic validation inside Entities. This fits well with the basic idea about OOD because it lets the object that represents a concept know about the valid ranges of data.

In most cases, you shouldn't even need explicit validation because Entities should be designed so that constraints are represented as invariants, making it impossible to create an instance that violates a constraint.

If you have a rule that says that Name cannot be null or empty, you can actively enforce it directly in your Entity:

public class MyEntity
{
    private string name;

    public MyEntity(string name)
    {
        if(string.IsNullOrEmpty(name))
        {
            throw new ArgumentException();
        }
        this.name = name;
    }

    public string Name
    {
        get { return this.name; }
        set
        {
            if(string.IsNullOrEmpty(value))
            {
                throw new ArgumentException();
            }
            this.name = value;
        }
    }
}

The rule that name cannot be null is now an invariant for the class: it is now impossible for the MyEntity class to get into a state where that rule is broken.

If later on you discover that the rule is more complex, or shared between many different concepts, you can always extract it into a Specification.

尸血腥色 2024-08-13 16:58:18

实体既有数据又有行为,因此让您的实体确保其不变量是恕我直言的方法。否则,您最终可能会得到一个贫血域模型 [Fowler]。

如果您的上下文允许您按照 Mark Seemann 的建议在设置器中强制执行规则,那就太好了,因为您的模型中没有所有“IsValid”和/或“BrokenRules”逻辑。

我遇到过两种情况,我们发现自己需要上述解决方案:

  1. 经典的响应/请求 Web 解决方案,其中网页在保存失败时显示实体的所有损坏规则。

  2. 该模型是从外部更新的数据库中读取的(因此,尽管存在 setter 逻辑,实体也并非不可能无效,除非您让 ORM 使用 setter,但我们的重点是找出有关有效性)。

Entities have both data and behavior, so letting your entities ensure their invariants is the way to go IMHO. Else, you might end up with an anemic domain model [Fowler].

If your context allows you to enforce the rules in the setters as Mark Seemann suggests, it would be great since you don't have all the "IsValid" and/or "BrokenRules" logic in your model.

I've been in two contexts where we found ourselves needing the aforementioned solution though:

  1. A classic response/request web solution where the web page displays all the broken rules of an entity upon failing save.

  2. The model is read from a database which is updated externally (hence it's not impossible for the entity to be invalid despite the setter logic, unless you let your ORM use the setters, but the whole point for us was to find out about the validity).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文