如何设计我的 Java / C# 库,使其在未来发生变化时保持二进制兼容?

发布于 2024-11-02 04:24:39 字数 1061 浏览 6 评论 0原文

任务:我正在设计一个供开发人员使用的库。

目标:我需要确保未来版本中的更改不会影响现有开发人员。

示例:

第一次发布时的情况:

只有一个类

public class ClassSample

{

String methodSample(String para1,String Para2, int Para3, String Para4);

}

第二次发布时的情况:

要求:

methodSample 的响应可以返回多个值。

methodSample方法中需要更多参数。

解决方案:一种方法是添加另一个重载方法,该方法将具有新参数并返回对象而不是内置数据类型。

但上述解决方案的问题是,将来会有太多的重载方法,太多的参数会显得大材小用。

修改解决方案1:

void methodSample(Request request, Response response)

在每个版本中(显然如果需要的话),我都会修改Request &响应类具有新的附加方法来获取/设置值。在这种情况下会有一个问题,因为在方法内部,我将无法区分调用者是 Version10 还是 Version20。

修改后的解决方案2:

void methodSample(AbsractRequest request, AbstractResponse response)

在每个版本中,我们都可以扩展派生类,例如Request200扩展Request100扩展AbstractRequest,对于响应类类似。在这种情况下,我可以通过检查实例类型来检查内部方法调用者是 Version10 还是 Version20。

总而言之,修改后的解决方案 2 对我来说看起来不错,您的想法如何?

Task: I am designing a library which will be used by developers.

Objective: I need to make sure that changes in future versions will not impact existing developers.

Example:

Situation during first release:

There is one class

public class ClassSample

{

String methodSample(String para1,String Para2, int Para3, String Para4);

}

Situation during second release:

Requirements:

Response of methodSample can return multiple values.

More parameters are needed in methodSample method.

Solution: One way could be just add another overloaded method which will have new parameters and return object rather than built-in data type.

But problem with above solution is, it will have too many overloaded methods in future, too many parameters will be overkill.

Modified Solution 1:

void methodSample(Request request, Response response)

In each release(obviously if required), I will modify Request & Response classes to have new additional methods to get/set values. There will be a problem in this case as inside the method, I won't be able to differentiate whether caller is of Version10 or Version20.

Modified Solution 2:

void methodSample(AbsractRequest request, AbstractResponse response)

In each release we can extend derived class like Request200 extends Request100 extends AbstractRequest, similarly for response classes. In this case I can check inside method whether caller is of Version10 or Version20 by checking instance typing.

In summary Modified Solution 2 looks good to me, what about your thoughts ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦言归人 2024-11-09 04:24:39

我会选择修改后的解决方案 1,但在类中添加了 get/set Version 方法。

您的库可以使用 getVersion 找出用户程序期望的行为

I would go for Modified Solution 1, but with the addition of a get/set Version method in the class.

Your library can the use getVersion find out which behaviour the user program is expecting

南笙 2024-11-09 04:24:39

我意识到这可能有点晚了,但想法可能对您或其他人有用。

我过去创建了一个需要版本控制的 SDK,并且做了一些与我在下面发布的非常相似的事情,并且效果很好。

这个想法是,所有消息都派生自您所建议的抽象类,但是在调用应用程序的一开始就设置了一个静态。然后,所有请求只需将 Version 属性设置为等于静态属性。这样在整个应用程序中只指定一次。

当您添加新版本时,只需添加到枚举中即可。我实际上使用了一个整数并递增它,但我认为枚举总是更易于维护。

享受!

namespace SilverlightClassLibrary1
{
    public enum SDKVersions
    {
        NonSpecific = 0,
        Version100,
        Version200,
    }

    public abstract class RequestBase
    {
        public static SDKVersions SystemSDKVersion { get; set; }

        public SDKVersions RequestSDKVersion { get; set; }

        protected RequestBase()
        {
            this.RequestSDKVersion = RequestBase.SystemSDKVersion;
        }
    }

    public class SimpleDataRequest : RequestBase
    {
        public String Data { get; set; }
    }

    public class SimpleDataResponse
    {
        public String Response { get; set; }
    }

    public class SomeSDKFunctionality
    {
        public static void RandomSDKFunction(SimpleDataRequest request, out SimpleDataResponse response)
        {
            switch (request.RequestSDKVersion)
            {
                case SDKVersions.Version100:
                    //Legacy response
                    response = new SimpleDataResponse()
                               {
                                   Response = "Helo " + request.Data,
                               };
                    break;

                default:
                    //Fixed / Updated Response
                    response = new SimpleDataResponse()
                               {
                                   Response = "Hello " + request.Data + "!",
                               };
                    break;
            }
        }
    }
}

namespace MyExternalApplication
{
    public class Main
    {
        public void ApplicationEntryPoint()
        {
            //Specify a specific version you intend to use
            RequestBase.SystemSDKVersion = SDKVersions.Version100;

        }

        public void ButtonClickExample()
        {
            SimpleDataResponse response;
            SomeSDKFunctionality.RandomSDKFunction(new SimpleDataRequest()
                                                   {
                                                       Data = "James",
                                                   }, out response);
        }
    }
}

I realise this might be a bit late but thought might be useful to you or someone else.

I've created an SDK in the past that required versioning and did something very similar to what I posted below and it worked a treat.

The idea being that all messages derive from an abstracted class as you suggested, but there is a static that is set in the calling application right at the start. All requests then simply set a Version property equal to that of the static. This way its only specified once in the whole application.

When you add new versions, just add to the enum. I actually used an integer in mine and incremented it but I think an Enum is always more maintainable.

Enjoy!

namespace SilverlightClassLibrary1
{
    public enum SDKVersions
    {
        NonSpecific = 0,
        Version100,
        Version200,
    }

    public abstract class RequestBase
    {
        public static SDKVersions SystemSDKVersion { get; set; }

        public SDKVersions RequestSDKVersion { get; set; }

        protected RequestBase()
        {
            this.RequestSDKVersion = RequestBase.SystemSDKVersion;
        }
    }

    public class SimpleDataRequest : RequestBase
    {
        public String Data { get; set; }
    }

    public class SimpleDataResponse
    {
        public String Response { get; set; }
    }

    public class SomeSDKFunctionality
    {
        public static void RandomSDKFunction(SimpleDataRequest request, out SimpleDataResponse response)
        {
            switch (request.RequestSDKVersion)
            {
                case SDKVersions.Version100:
                    //Legacy response
                    response = new SimpleDataResponse()
                               {
                                   Response = "Helo " + request.Data,
                               };
                    break;

                default:
                    //Fixed / Updated Response
                    response = new SimpleDataResponse()
                               {
                                   Response = "Hello " + request.Data + "!",
                               };
                    break;
            }
        }
    }
}

namespace MyExternalApplication
{
    public class Main
    {
        public void ApplicationEntryPoint()
        {
            //Specify a specific version you intend to use
            RequestBase.SystemSDKVersion = SDKVersions.Version100;

        }

        public void ButtonClickExample()
        {
            SimpleDataResponse response;
            SomeSDKFunctionality.RandomSDKFunction(new SimpleDataRequest()
                                                   {
                                                       Data = "James",
                                                   }, out response);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文