2

我知道在实体中注入服务(通过构造函数或设置器)并让实体保留对它的引用通常被认为是一种不好的做法。

但是在调用方法时可以暂时将服务交给实体吗?

例如,假设我想对name实体的字段进行版本化,并且VersionService每次setName()调用时都创建一个新版本,我可以这样做:

public class Entity
{
    public void setName(String name, VersionService service)
    {
        this.name = name;
        service.addVersion(this, name);
    }
}

我在这段代码中喜欢的是,如果setName()不提供 a 就无法调用该方法VersionService,从而强制执行所需的行为。通过模拟VersionService.

我在Jimmy Bogard关于双重调度模式的帖子中找到了这种方法的一个示例。

但是从关于 Stack 的一些讨论中,我认为普遍的共识是避免对域模型中的服务有任何依赖。

对这个问题有什么想法吗?

4

3 回答 3

2

但是从关于 Stack 的一些讨论中,我认为普遍的共识是避免对域模型中的服务有任何依赖。

服务而言,我很想知道反对在实体中使用它们的论点。领域服务是包含在通用语言中的第一类领域对象。在很多情况下,位于实体中的逻辑调用位于域服务中的逻辑是合理的,就像它调用另一个实体一样。

本文中的第3段就是一个很好的例子。

于 2012-11-16T13:40:13.550 回答
1

您通常使用域事件来生成新版本:

public class Entity
{
    public void setName(String name)
    {
        this.name = name;
        DomainEvent.Publish(new MyEntityGotRenamed(Id));
    }
}

public class YourService : ISubscribeOn<MyEntityGotRenamed>
{
     public void Handle(MyEntityGotRenamed domainEvent)
     {
         var entity = repos.Get(domainEvent.Id);
         AddVersion(entity);
     }
}

您订阅事件的方式是特定于平台的。

请注意,这setName并不代表域操作。应该是Rename或您的客户已定义的其他内容。

于 2012-11-16T10:09:32.070 回答
1

领域事件方法很好,但它依赖于使用消息驱动的架构。

无论如何,特别是对于您给出的示例,我不会将服务作为参数传递,因为 IMO 使用该服务更新其他模型不是实体关注的问题。实体(可能是聚合根)只关心它自己的模型。调用实体的代码也可以调用服务。

但是,我认为可以将服务作为参数传递以检索其他一些必要的数据(遗憾的是我现在想不出一个例子)。但是大多数情况下,您会将服务作为构造函数依赖项传递,也就是说,您需要该服务的不仅仅是操作,而且您不能将数据作为方法参数提供。

于 2012-11-17T16:05:20.243 回答