【问题标题】:Why interfaces for message contracts are strongly recommended in MassTransit?为什么 MassTransit 强烈建议使用消息合约接口?
【发布时间】:2017-06-05 12:04:28
【问题描述】:

MassTransit 声明我们应该为消息合约使用接口:

强烈建议对消息合约使用接口, 根据多年不同水平的经验 开发者经验。 MassTransit 将创建动态界面 消息的实现,确保完全分离 来自消费者的消息合约。

资料来源 : Docs » 使用 MassTransit » Creating a message contract

使用 POCO DTO 代替接口有什么缺点,在使用 MassTransit 进行消息传递的上下文中,接口相对于类的明显优势是什么?

另一方面,NServiceBus 可以使用 POCO,确保不使用域对象等内部类是有意义的,见下文。

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

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

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

【问题讨论】:

  • 优点很简单:确保消息合约与消费者完全分离
  • POCO 不会是第二好的吗?我的意思是措辞 - “强烈建议”意味着不使用接口的某种风险或负面后果,我目前看不到。
  • 接口只是一个分离层,允许对 POCO 方法的更改只需迁移到一个代码块。整个代码中可能有几十个不同的 save 命令,需要在简单的表格更改上进行编辑,但如果这些命令只是汇集到 Save 界面,你只会需要编辑 1 个实例
  • 这是指导,以确保行为不会蔓延到消息合同中。 POCO 的使用当然是允许的,大多数从 NSB 移植的团队不会更改他们的消息程序集并且它们工作得很好。
  • @ChrisPatterson 不再是下一个 C# 接口可以包含功能的情况:-)

标签: c# masstransit event-bus


【解决方案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;
    }

    ...
}

【讨论】:

  • 我明白了,但这不是全貌 - 因为您需要在客户端实现 User aka RemoteUser : IUser {},然后反序列化它,现在使用接口仍然是您的责任您的客户端代码,而不是改变您自己的实现。
  • 通过 POCO 方法,您可以使用带有构造函数参数的不可变类并获得相同的保证。 JSON.NET 通过构造函数参数支持反序列化,非常简单。并且您可以减轻客户端的实施负担。
【解决方案2】:

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

长话短说更简洁的代码和更高的可维护性

【讨论】:

  • 虽然消息类型通常不会在 DI 容器中注册
【解决方案3】:

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

有明确的合同定义,同时保持与旧版本合同的兼容性。

在输出上使用新接口 - 代码清楚地定义了合约。

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

【讨论】:

    猜你喜欢
    • 2017-11-18
    • 2019-09-26
    • 1970-01-01
    • 2014-01-11
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    • 2017-05-06
    • 2014-10-13
    相关资源
    最近更新 更多