语义版本控制:小改动还是大改动?
Posted
技术标签:
【中文标题】语义版本控制:小改动还是大改动?【英文标题】:Semantic versioning: minor or major change? 【发布时间】:2019-07-31 22:52:14 【问题描述】:在semantic versioning 中,一般规则是仅在引入向后兼容的功能时才增加次要编号,否则必须增加主要编号。 libtool 使用same approach,但算法不同。
我有一个问题,关于什么被认为是向后兼容的变化,什么不是。
假设我编写了一个库,该库的公共头文件包含一个名为foo
的数据类型的typedef
。在 1.0.0 版中,typedef
看起来像这样:
typedef struct foo_t
int x;
int y;
foo;
然后我决定改变数据类型,下个版本会是这样的:
typedef struct foo_t
int x;
int y;
int z;
foo;
我只向结构foo_t
添加了一个字段。这似乎是一个向后兼容的变化,但是上面的结构现在是 de facto 另一个结构。我所做的不是引入一个新功能,其余的都保持不变,而是我改变了一些已经存在的东西。
上述数据类型通常用于与库函数交换数据,但用户可能将其用于其他目的。如果用户使用 1.0.0 版本编写了程序,并且最后一次更改构成向后兼容的更改,则用户的程序也必须使用这个新版本进行编译。
这个新版本怎么叫,1.1.0还是2.0.0?
编辑
您可以阅读此讨论的进一步发展here。
【问题讨论】:
【参考方案1】:这将是一个主要的版本更改。结构布局被烘焙到最终用户程序中。添加 或 删除成员是一项重大更改;无论哪种方式,布局都发生了变化。
引用Linux Program Library HOWTO — §3.6。不兼容的库:
当新版本的库与旧版本二进制不兼容时,soname 需要更改。在 C 语言中,库不再兼容二进制有四个基本原因:
函数的行为发生变化,使其不再符合其原始规范,
导出的数据项发生变化(例外:将可选项添加到结构的末尾是可以的,只要这些结构仅在库中分配)。
李>导出的函数被移除。
导出函数的接口发生变化。
您说,“上面的数据类型通常用于与库的函数交换数据,但是用户可能已将其用于其他目的。”如果该结构仅在内部使用并且未在公共 API 中公开,则可以。但听起来用户可以自己分配一个结构变量,这意味着这是一个突破性的变化。
您可以使用opaque structs 保护您的图书馆免受此类流失的影响。隐藏结构的内容,让用户只传递指针。这正是 FILE *
的工作原理:C 标准没有定义 FILE
的布局,我们作为最终用户不知道其中的内容。
【讨论】:
感谢您提供非常好的答案。我不能向用户隐藏我的struct
,所以不透明的结构不是一种选择。主要版本改变吧!
请注意,您可以通过使大小动态化(因此用户需要查询库以获取要分配的大小)或包含大小甚至动态来避免需要主要版本更改对象本身的版本 ID。对于后者,库将需要检查该大小/版本以了解它正在处理的对象版本(更多工作),但如果您预计将来想要更改结构,这可能是值得的。以上是关于语义版本控制:小改动还是大改动?的主要内容,如果未能解决你的问题,请参考以下文章