语义版本控制是不是适用于源或二进制兼容性?

Posted

技术标签:

【中文标题】语义版本控制是不是适用于源或二进制兼容性?【英文标题】:Does semantic versioning apply to source or binary compatibility?语义版本控制是否适用于源或二进制兼容性? 【发布时间】:2015-08-13 11:05:36 【问题描述】:

此问题适用于以一种语言(“来源”)编写的任何语言,例如C 或 Java,并以另一个(“二进制”)分发,例如机器码或 Java 字节码,使用动态链接。


假设用户已经在使用我的库的 A 版。我发布了一个更新的版本 B。

如果他可以编译他的代码而无需针对 B 进行更改并正确地与 B 一起运行,则从 A 到 B 的更改被称为 源代码兼容

如果他可以针对 A 编译他的代码并正确地与 B 一起运行,则从 A 到 B 的更改被称为 二进制兼容。这种情况在使用没有隔离模块加载的传递依赖图(例如 OSGI)时很常见。 X 是针对特定版本的 Y 和 Z 编译的,而 Y 是针对不同的特定版本 Z 编译的。在运行时,Y 对 Z 的调用可能不正确并且可能会崩溃。

更改可能是源兼容的,但二进制不兼容。更改也可能是源不兼容和二进制兼容。

我使用哪种兼容性来进行语义版本控制?我是使用源兼容性来区分主要和次要/补丁更新,还是使用二进制兼容性来区分主要和次要/补丁更新?


我目前的动机是 Scala 库。 Scala 二进制兼容性很难分析,需要对编译器细节有很好的理解。源代码兼容和二进制不兼容很常见。

这不是什么奇怪的边缘情况;此问题可能出现在大多数已编译的、动态链接的语言中。

【问题讨论】:

【参考方案1】:

要回答这个问题,请假设您是一个用户而不是程序员。在他们看来,源代码一文不值;他们不理解它,这对他们来说毫无意义。另一方面,他们有一个包含目标代码的文件,他们知道它需要去某个地方。只有二​​进制文件的版本对他们很重要。

然而,这并不是故事的结局。您的问题隐含地包含更好答案的核心。兼容性有两种,所以应该有两种版本序列。问题本身包含一个功能失调的假设,即应该只有一个版本序列。

现在,如果您有两个版本序列,另外,在用户端创建一种自动方式将源兼容版本转换为对象兼容版本,那么您的问题就得到了缓解。能够做到这一点需要明确指定如何进行转换,例如编译器版本、解释器版本、命令行参数等。

简而言之,对上述问题的最佳答案是它适用于他们两个。

【讨论】:

源代码兼容性意味着用户的代码无需更改即可编译,因此在这里谈论非程序员或不了解源代码的用户似乎很荒谬。此外,拥有单独的版本控制方案只会将问题转移给用户——我应该使用带有源代码还是二进制兼容语义的版本方案? 请注意我的回答中的“假装”一词。有时甚至程序员也不关心源代码。不过,我怀疑,鉴于您的评论,您有这个问题中没有说明的担忧。也许在对原始问题的评论中详细说明您的具体问题是合适的。【参考方案2】:

几个月后,我想我有一个很好的结论。

语义版本控制应该考虑两者,并遵循“变化最大”的一个。

中断源代码编译是对库用户的不兼容更改。 中断运行时执行是对库用户的不兼容更改。

如果源兼容性或二进制兼容性发生变化,则根据语义版本控制,它应该是新的主要版本。

就我的 Scala 而言,有时很难确定二进制兼容性。有几个 JAR API 差异工具,例如JDiff.

【讨论】:

以上是关于语义版本控制是不是适用于源或二进制兼容性?的主要内容,如果未能解决你的问题,请参考以下文章

语义版本控制:小改动还是大改动?

语义版本控制 - 向后兼容性和版本 0.x.y

HTTP Restful 语义版本控制

语义化版本控制的规范(转载)

语义化版本控制规范(SemVer)

语义版本控制 (Semver) - 如何对向后兼容的大型功能更新进行 semver