SciJava组件使用Semantic Versioning(SemVer)系统。该方案在每个软件组件的版本之间传输涉及backwards compatibility(或缺乏§§17§§§)的信息。
总结
因此,语义版本控制的工作原理如下:
给定版本号MAJOR.MINOR.PATCH,递增:
-当您进行不兼容的 API 更改时,主要 (M) 版本, -您当以坚固兼容的方式添加功能时,次要 (n) 版本,以及 -当您进行完整兼容的错误修复时,修复程序 (p) 版本。
每个 SciJava 组件都属于以下类别之一:
- 0.M.n - 以 0 开头的版本号表示该组件仍处于初始孵化阶段。API 将在开发中,可能会发生变化。我们确实尝试保持完整性,在删除旧类之前至少在一个版本中废弃旧类,但并不总是可能的。因此,依赖于这些组件的代码可能会崩溃。
- M.n.p-beta-a - 与 0.M.n 类似,API 尚在开发中。在某些圈子中,术语“beta”可能意味着“功能完整”,但我们不这样使用该术语。这些“测试版”版本被认为比 0.M.n 更不稳定,但仍会根据需要进行未来的更改和添加。
- M.n.p-rc-a - 构成 beta 的“版本候选”,尽管被认为非常接近成熟版本。
- M.n.p - 其中 M 至少为 1。这表示一个成熟的版本,致力于长期地保持完整性兼容性。即使该组件后来升级了主要版本,我们仍会尝试进行必要的最小破坏性更改以引入任何新的所需功能。
语义版本对于指示软件如何将编程方式从一个版本更改为另一个版本非常有用,但它对于人类来说可能不理解,尤其是对于非开发人员而言。重要的是要理解,“主要”版本的增加并不一定意味着大量新功能的闪亮新版本的软件,而更多可能删除已废弃的类和方法,和/或以刚性不兼容的方式将功能从一个地方移动到另一个地方。相反,“次要”版本的增加可能表明在某个处添加了单个新方法,或者许多重要的新功能,并且SemVer 没有指定一种解决方案来解决极端情况下的场景。
SemVer 的范围
SemVer 提供了一种推理公共 API 变化的方法。然而,开发人员需要准确定义其软件中的“公共 API”所主题的内容。对于 SciJava,该定义如下:
- API (classes) 由 Application Programming Interface、methods 和 Service Provider Interface 调度下游消费者使用的集合定义。这意味着,例如,如果您的代码依赖scijava-common提供ModuleService#getModules()并调用ModuleService方法,则您可以升级到较新的
scijava-common版本,并保证只要主版本号不增加,该方法将继续并存在兼容的返回类型。
鼓励以下内容成为公共 API 的一部分,但它们是优点的或不能严格执行,因此不能仅通过版本号来保证:
- 方法的预期行为。例如,假设修改了ModuleService的实现,使得构成“严格”§§7§§§的定义发生了变化。在这种情况下,应增加
scijava-common的主要版本:即使方法签名未更改,Context的预期合同已更改。相反,假设ModuleService尚未并引发实现UnsupportedOperationException。首次实现此方法时增加,次要版本就足够了,因为代码正在朝着“预期”行为发展。
以下是不属于 SciJava“公共 API”的实际示例,可以因此在不相应增加主要版本的情况下进行更改:
- 方法的意外行为。例如,假设 FormatTools.calibrate 方法中存在错误,它总是从
imageIndex值中减少1。了解此错误后,您始终将1添加到calibrate方法调用中使用的索引中。但是,当此错误修复后,您的代码会突然尝试在无效索引处调整图像。审视上,这可能感觉像是一个重大更改,但上述公共 API 的定义并不能保证该方法的行为。 - 外部依赖项。 请参阅下面的Is SemVer transitive?。
- SPI (interfaces) compatibility——由下游实现者**扩展和实现的类和接口集。例如,如果您的代码提供了自己的 Context#isStrict() 接口实现,则更新到
scijava-common的新版本可能会由于添加了您的类未实现的新方法签名而破坏您的代码。 请注意,在实践中可以减少许多限制。例如,开发人员可以尽最大努力限制 SPI 损坏,安装上游零件而不是解决软件问题,并使用 BOM 以确保跨库兼容性。
另外,SciJava 项目通常伴随着具有相应抽象类和/或默认实现的接口,为“实现者”提供了面向未来的扩展点。所以例如在Context#isStrict()的情况下,让你的类扩展RichPlugin而不是普通的实现接口将是一种有效的方法,可以在很大程度上保护你自己在 SPI 损坏的影响期间进行未来依赖版本升级。其他一些例子:
|
感兴趣的界面 |
要扩展基类 |
熔炉
由于 SemVer 可用于推理的内容限制的存在,因此应用程序可能还希望提供一个“熔炉”来进行高级兼容性评估。
SciJava component collection使用melting pot script来从其最低级库(例如,SciJava Common和ImgLib2)到其最普通的应用程序(例如,ImageJ2和Fiji)的组件进行测试。
SemVer 是否具有提交性?
SemVer 的规则在单个项目范围内很容易遵循,但是当依赖项升级、添加或删除时如何处理版本号并没有明确的定义。因此,SciJava 开发人员已根据项目类型就标准规定达成一致。
标准项目。对于标准软件项目(例如库和应用程序),答案是否;SemVer 的范围仅限于项目公共及其 API。
如果项目添加、删除或升级对具有不同主要或次要版本的版本的依赖项,则仅当项目自身的公共 API 也发生更改时,项目的版本才会被修改。
在不影响库的主要或次要版本的情况下添加新的依赖项可能会感觉很奇怪。毕竟,现在库不能被放入例如ImageJ安装不会遇到依赖偏差。但从使用您的库的下游Maven项目的角度来看,新版本是兼容以前的版本。
本质上,依赖收敛是版本控制的一个单独问题,并且不能使用 SemVer 进行跟踪。
库存清单项目。 对于 Bill of Materials 项目,“公共 API”是所有托管依赖项的联合。因此,如果 BOM 中管理的一个或多个组件更新到增加的主要或次要版本,则 BOM 本身必须在其下一个版本中进行最重大的更改。
例如,如果 BOM 版本为 5.4.3,托管其托管依赖项 X 从 1.0.3 > 1.1.0 更新,Y 从 2.4.1 > 3.0.0 更新,则 BOM 的下一个版本约为 6.0.0。