语义化版本

导言:

无论是手机上的应用,还是MacOS这样的操作系统,我们在使用软件的时候,常会跳出提醒我们升级到xxx版本的小窗口,建议我们使用更新的版本。这时候,你一般是怎么判断,这次要不要升级的呢? 当我们自己开发一个小游戏,上线之后,我们希望更新一个新版本,这时候,我们的版本号应该怎么变化呢? 本期,我们就来聊聊,软件的版本号一般是怎样的结构,包含了怎样的意义。

关于版本的问题

如导言中所说,软件/库的版本号,包含了很多意义,如果对版本号的定义不清楚,不规范,可能会导致以下几个大问题:

问题1 版本号的意义不明确

某某软件新发布了一个版本2.2.2,这个版本号代表着什么意思?必然不会是想说这是一个很2的版本吧… 某某开发者想写个软件,版本号是从0.0.1开始呢还是从1.0.0开始? 某某产品经理想发布一个软件的升级版本,是从1.0.4升级到1.0.5呢还是升级到1.1.0?

问题2 缺乏统一的标准

每个软件都可以定义自己版本号的规则,无可厚非,但是如果每个软件都定义自己的版本号规则,而这些规则又不一样,甚至互相冲突,即使每个规则在自己的范围内都是有意义的,但是对用户来说,版本号背后代表的含义就没有任何意义了。所以,一个统一的定义版本号的规则是必须的。

问题3 缺乏版本兼容信息

无论对操作系统还是具体的类库,版本兼容都是一个大问题。用户升级版本时经常要看一堆升级文档,其中描述了例如:

如果没有其他信息,用户只能通过阅读大量的升级文档,在其中找到以上的关键字,然后判断是否需要升级,如何处理兼容问题等等麻烦事儿,然后确认自己是否能升级,试想一下你需要同时升级10个依赖的库,工作量该有多大~ 而如果版本号本身就能包含上述大部分信息,是不是会很方便?

问题4

软件不同版本天然需要兼容的需求,但是如果兼容的版本太多又会导致代码难以维护,老功能无法去除影响新功能的开发,因此软件也有不兼容的需求,如何协调兼容不兼容的需求。

语义化版本

语义化版本控制规范,就是为了来解决上面这些问题的,它是由Gravatars创办者兼GitHub共同创办者Tom Preston-Werner 所建立的,主页https://semver.org/。 这个规范到底规定了些什么呢,我们来看看它的摘要:

摘要

版本格式:主版本号.次版本号.修订号,版本号递增规则如下:

1. 主版本号:当你做了不兼容的 API 修改,
2. 次版本号:当你做了向下兼容的功能性新增,
3. 修订号:当你做了向下兼容的问题修正。
先行版本号及版本编译元数据可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

网站的主页还有非常完整的,关于版本号格式及内容的定义,在此就不赘述了。仅从上文的摘要就可以看出,规范的版本号不仅可以体现当前新版本的更新目的,还包含了与老版本是否兼容等信息,免去了用户查阅其他升级文档的时间,解决了我们上面提出的所有问题。

老样子,我们用一个小栗子来演示一下,一个软件的版本号到底应该怎么演变。

一个软件的版本号演变

0.1

某年某月某一天,又一个小软件库诞生了!第一个版本可以从0.0.1或者0.1.0开始,0.1.x及以下版本号的软件处于开发初始阶段,一切都可能随时被改变,这时候的公共API不应该被视为稳定版。

1.0.0

开发了一段时间,当软件比较稳定后,就可以发布第一个正式版本1.0.0了。注意,和之前的版本不同,这时发布的公共API后续就不能随意修改,需要兼容几个版本。

修订号

发布了一段时间,我们发现1.0.0有bug,没关系,直接在1.0.0基础上打patch,然后发布1.0.1版本就好了。如果后续还有bug,就发布1.0.2,1.0.3,以此类推~

次版本号

改完bug之后,又过了一段时间,我们觉得1.0.x的功能比较有限,想再提供一些新的酷炫的功能,这时需要发布1.1.0,次版本号更新说明有新功能,但是老功能兼容1.0.0。

这时,如果发现1.0.2和1.1.0上都有一个相同的bug,需要同时发布1.0.3和1.1.1,分别修改两个版本。在工程上,也许就是在项目的两个branch需要分别打一个patch,并且上线两个新版本的软件或者库。

主版本号

软件发布一段时间,有了一些用户反馈,我们发现1.0的某些功能设计的不好,想弃用,忘掉这段黑历史。于是,我们首先需要将这个公开API标记为弃用(java里面使用@Deprecated注解),保持一段时间后(可能会保持几个次版本),在升级到2.0.0版本的时候,我们就可以把这些API删除了。

又过了段时间,我们的版本越发越多后,需要维护的版本也会越来越多,甚至多到无法维护的地步,是时候放弃一些版本了!因此,我们需要定义目前正在维护哪几个版本(太老的就不维护了),这主要取决于我们的用户目前大部分升级到了哪个版本。

以上,就是一个小软件库的升级演化过程。其实我们所使用的很多软件/库,都是遵循着这个规范在更新版本的。比如,Android的版本升级就一直是一个很欢乐的事情,在版本号上,安卓严格按照以上规则一步步升级新的版本号,但同时,Google的工程师们还饶有兴趣地给每个版本起了一个名字,画了一个新的logo,让版本升级这件事情变得更有趣味。

参考

Written on July 12, 2019