为什么在MassTransit中强烈推荐使用消息契约接口?

24

MassTransit认为我们应该使用接口来定义消息协议:

建议使用接口定义消息协议,基于多年开发经验,考虑到各种不同程度的开发者经验。MassTransit将为消息创建动态接口实现,确保消息协议与消费者之间的清晰分离。

来源:文档 » 使用 MassTransit » 创建消息协议

相较于使用接口,使用 POCO DTOs 的缺点是什么?在使用 MassTransit 进行消息传递时,使用接口的优势明显有哪些?

另一方面,NServiceBus 推荐使用 POCO 对象,而且不使用内部类如领域对象,见下文。

来源:NServiceBus » Messaging » Messages, Events and Commands

创建消息时应遵循以下准则:

  • 消息应该是简单的 POCO 对象。
  • 消息应该尽可能小。
  • 消息应该满足单一职责原则。
  • 不应将用于其他目的的类(例如领域对象、数据访问对象和 UI 绑定对象)用作消息。

非常简单,优点在于:确保消息契约与消费者之间的清晰分离。 - Jamie Rees
1
POCO 不是第二好的吗?我的意思是,“强烈建议”这个措辞暗示了不使用接口会有某种风险或负面后果,但我目前还没有看到。 - Edgars Pivovarenoks
2
接口(Interface)只是一个隔离层,允许将对POCO方法的更改迁移到一个代码块中。在表格简单更改时,可能会有数十个不同的保存命令需要进行编辑,但是如果这些命令只是汇集到一个“保存”接口,则您只需要编辑一个实例。 - Mad Myche
8
这是一种指导,旨在确保行为不会潜入消息契约中。POCO的使用是允许的,大多数从NSB移植的团队不会改变他们的消息程序集,它们仍然可以正常工作。 - Chris Patterson
5
@ChrisPatterson,下一个版本的C#中接口可以包含功能了,这已经不再是以前的情况了 :-) - Carlo V. Dango
3个回答

1
虽然与MassTransit没有直接关系,但我认为原因是封装。创建一个带有setter的简单POCO,但通过只承诺getter的接口传递它将数据封装在DTO中。
public class Program
{
    static void Main(string[] args)
    {
        User user = new User()
        {
            Username = "user99"
        };

        Account account = new Account(user);
    }
}

public interface IUser
{
    string Username { get; }
}

public class User : IUser
{
    public string Username { get; set; }
}

public class Account
{
    private IUser user;

    //Currently used in main
    public Account(User user)
    {
        user.Username = ""; //This is allowed            
        this.user = user;
    }

    //But consider this ctor
    public Account(IUser user)
    {
        //user.Username = ""; //Not allowed
        this.user = user;
    }

    ...
}

我明白,但这并不是全部情况 - 因为你需要在客户端实现用户,即RemoteUser:IUser {},然后对其进行反序列化,现在你仍然有责任在客户端代码中使用接口而不是改变自己的实现。 - Edgars Pivovarenoks
3
使用POCO方法,您可以使用带有构造函数参数的不可变类,并获得相同的保证。JSON.NET支持通过构造函数参数进行反序列化,因此非常容易。这样可以减轻客户端的实现负担。 - Edgars Pivovarenoks

0

使用接口可以更轻松地处理多个消息版本。您可以拥有两个单独的接口,每个版本一个,并且POCO对象实现两个接口。

在保留与旧合同版本兼容性的同时,有一个明确的合同定义。

在输出时使用新接口 - 代码清晰地定义了合同。

在输入时使用POCO - 保持与两个版本的兼容性。


-1

我认为更容易的依赖注入和根据需要提供多个实现,可以在整个项目中提供统一的消息格式,但尽可能提供不同的处理逻辑。

长话短说,代码更清晰,可维护性更高。


1
消息类型通常不会在 DI 容器中注册。 - gbro3n

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接