首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >领域模型设计中的困境

领域模型设计中的困境
EN

Software Engineering用户
提问于 2018-08-20 11:39:32
回答 4查看 200关注 0票数 2

我有一个类Document,文档具有一个状态:

代码语言:javascript
复制
public enum DocumentStatus : byte
{
    Incompleted,
    Completed,
    Cancelled
}

现在我遇到了一个我无法独自解决的难题。

Document应该有像CancelComplete这样的方法,以及像DocumentCancelledDocumentCompleted这样的域事件吗?

代码语言:javascript
复制
public class Document : Entity, IAggregateRoot
{
    ...

    public DocumentStatus Status { get; private set; }

    public void Cancel()
    {
        Status = DocumentStatus.Cancelled;
        this.AddDomainEvent(new DocumentCancelled(this));
    }

    public void Complete()
    {
        Status = DocumentStatus.Completed;
        this.AddDomainEvent(new DocumentCompleted(this));
    }
}

或者让Status设置器公开并有像DocumentStatusChanged这样的域事件也很好吗?

代码语言:javascript
复制
public class Document : Entity, IAggregateRoot
{
    ...

    private DocumentStatus _status;

    public DocumentStatus Status
    {
        get => _status;
        set {

            this.AddDomainEvent(new DocumentStatusChanged(this, _status, value)); // oldValue, newValue

             _status = value;
        }
    }
}

在本例中,这比使用以下方法更好:

代码语言:javascript
复制
public class Document : Entity, IAggregateRoot
{
    ...

    public DocumentStatus Status { get; private set; }

    public void SetDocumentStatus(DocumentStatus status)
    {
        this.AddDomainEvent(new DocumentStatusChanged(this, Status, status)); // oldValue, newValue
        Status = status;
    }
}

对不起,如果这听起来微不足道或愚蠢,但我是新手DDD,并试图遵循最佳实践。

EN

回答 4

Software Engineering用户

回答已采纳

发布于 2018-08-20 19:18:04

文档是否应该有像CancelComplete这样的方法,以及像DocumentCancelledDocumentCompleted这样的域事件?

如果应用程序不会侦听事件,就不要创建事件。除非您正在处理传统应用程序(即桌面或电话),否则这些事件不会有多大帮助。这些方法是个好主意。它们使文档状态成为一个只读属性,取消或完成文档的行为可以自由地进行其他操作,而不仅仅是设置状态。这是一件好事。

或者让Status设置器公开并有像DocumentStatusChanged这样的域事件也很好吗?

同样,关于事件的同样的评论。如果您必须添加任何附加逻辑(如验证等)然后,一个简单的setter将使您的代码难以理解。

我要回答的最大问题是,您的领域模型在哪里使用?Web应用程序和标准UI有不同的通信方式。如果您的模型不需要通知任何其他代码,则不需要通知。

还有另一种选择:

代码语言:javascript
复制
class Document : Entity, IAggregateRoot
{
    public DocumentStatus Status { get; private set; }

    public void Cancel()
    {
        this.AddDomainEvent(new DocumentStatusChanged(this, Status, DocumentStatus.Cancelled));
        Status = DocumentStatus.Cancelled;
    }

    public void Complete()
    {
        this.AddDomainEvent(new DocumentStatusChanged(this, Status, DocumentStatus.Completed));
        Status = DocumentStatus.Completed;
    }        
}
票数 1
EN

Software Engineering用户

发布于 2018-08-20 11:59:33

在这种情况下,您可能应该使用您的领域专家的语言作为指南--思考领域建模的一种方法是,我们正在尝试创建一种特定于领域的语言,该语言与我们试图解决的问题相匹配。

很少有域使用"set“作为语言中的头等关注点。

例如,我们“放置”、“完成”和“取消”订单。因此,我们更愿意对这种语言进行建模,而不是使用像"set status“这样的拼写。

票数 3
EN

Software Engineering用户

发布于 2018-08-20 11:59:46

如果状态之间的所有转换都是有效的,那么我可能只需要使用公共getter + setter创建一个属性,这是最简单的事情,它可以工作,而且几乎不需要代码。

如果某些转换是被禁止的,那么您肯定会想要使用imho方法,例如不能从被取消的->完成

票数 2
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/377145

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档