Search Results for

    Show / Hide Table of Contents

    向后兼容准则

    编写向后兼容的代码可能很难测试。

    永远不要更改现有方法的签名

    由于Orleans序列化程序的工作方式,您永远不应该更改现有方法的签名。

    以下示例是正确的:

    [Version(1)]
    public interface IMyGrain : IGrainWithIntegerKey
    {
      // First method
      Task MyMethod(int arg);
    }
    
    [Version(2)]
    public interface IMyGrain : IGrainWithIntegerKey
    {
      // Method inherited from V1
      Task MyMethod(int arg);
    
      // New method added in V2
      Task MyNewMethod(int arg, obj o);
    }
    

    这是不正确的:

    [Version(1)]
    public interface IMyGrain : IGrainWithIntegerKey
    {
      // First method
      Task MyMethod(int arg);
    }
    
    [Version(2)]
    public interface IMyGrain : IGrainWithIntegerKey
    {
      // Method inherited from V1
      Task MyMethod(int arg, obj o);
    }
    

    注意:您不应在代码中进行此更改,因为这是导致非常糟糕的副作用的不良实践的示例。这是一个如果您只重命名参数名会发生什么的示例:假设我们在集群中部署了以下两个接口版本:

    [Version(1)]
    public interface IMyGrain : IGrainWithIntegerKey
    {
      // return a - b
      Task<int> Substract(int a, int b);
    }
    
    [Version(2)]
    public interface IMyGrain : IGrainWithIntegerKey
    {
      // return y - x
      Task<int> Substract(int y, int x);
    }
    

    这种方法似乎是相同的。但是,如果使用V1调用客户端,并且请求由V2激活处理:

    var grain = client.GetGrain<IMyGrain>(0);
    var result = await grain.Substract(5, 4); // Will return "-1" instead of expected "1"
    

    这是由于内部Orleans序列化程序是如何工作的。

    避免改变现有的方法逻辑

    这看起来很明显,但是在更改现有方法的主体时应该非常小心。除非您正在修复一个bug,否则如果您需要修改代码,最好只添加一个新方法。

    例子:

    // V1
    public interface MyGrain : IMyGrain
    {
      // First method
      Task MyMethod(int arg)
      {
        SomeSubRoutine(arg);
      }
    }
    
    // V2
    public interface MyGrain : IMyGrain
    {
      // Method inherited from V1
      // Do not change the body
      Task MyMethod(int arg)
      {
        SomeSubRoutine(arg);
      }
    
      // New method added in V2
      Task MyNewMethod(int arg)
      {
        SomeSubRoutine(arg);
        NewRoutineAdded(arg);
      }
    }
    

    不要从grain接口删除方法

    除非确定不再使用这些方法,否则不应从grain接口中删除方法。如果要删除方法,应该分两步完成:1。部署V2grains,V1方法标记为过时的

    [Version(1)]
    public interface IMyGrain : IGrainWithIntegerKey
    {
      // First method
      Task MyMethod(int arg);
    }
    
    [Version(2)]
    public interface IMyGrain : IGrainWithIntegerKey
    {
      // Method inherited from V1
      [Obsolete]
      Task MyMethod(int arg);
    
      // New method added in V2
      Task MyNewMethod(int arg, obj o);
    }
    
    1. 当您确定没有进行V1调用时(实际上V1不再部署在正在运行的集群中),则在部署V3时删除V1方法 cs [Version(3)] public interface IMyGrain : IGrainWithIntegerKey { // New method added in V2 Task MyNewMethod(int arg, obj o); }
    • Improve this Doc
    In This Article
    Back to top Generated by DocFX