敏捷开发

软件修养 - 版本号管理

2021-04-29  本文已影响0人  CatchZeng

原文:https://makeoptim.com/training/semver

在软件管理的领域里存在着被称作“依赖地狱”的死亡之谷,系统规模越大,加入的套件越多,你就越有可能在未来的某一天发现自己已深陷绝望之中。 —— GitHub 共同创办者 Tom Preston-Werner

依赖地狱

在现代软件开发过程中,相较于“重复造轮子”,开发者往往会利用一些已有的组件(如库、程序、多媒体文件)进行开发。程序开发者根据特定版本的组件来设计自己的软件。这种方式使得代码重复利用,减少了开发的工作量,降低了开发门槛。但是该软件要正确运行,必须安装了指定版本的某些组件。

打个比方:你组装一台游戏电脑,想要配置高配的显卡。由于主板和 cpu 都需要和显卡适配,因此,你不得不先定好显卡型号,然后以该显卡作为标准,来选择主板和 cpu。你组装的电脑,必须依赖于显卡的型号

training

这便是”相依性“的产生过程。

而随着产品的迭代,软件的集成度越来越高,随之依赖组件也越来越多。若只有简单的相依性,则比较容易解决。如 A 软件依赖 B、C 软件包,而 B、C 软件包没有依赖,只需要安装 B、C 软件包,再安装 A 软件即可。而当依赖性过多,且具有多级结构,形成错综复杂的网络,依赖性的解析就会变得异常困难,甚至出现无法解析的致命错误。

我们将在操作系统中由于软件之间的依赖性不能被满足而引发的问题称为依赖地狱

training

依赖地狱主要有以下表现:

依赖过多

一个软件包可能依赖于众多的库,因此安装一个软件包的同时要安装几个甚至几十个库包。

多重依赖

指从所需软件包到最底层软件包之间的层级数过多。这会导致依赖性解析过于复杂,并且容易产生依赖冲突和环形依赖。

依赖冲突

即两个软件包无法共存的情况。除两个软件包包含内容直接冲突外,也可能因为其依赖的低层软件包互相冲突。因此,两个看似毫无关联的软件包也可能因为依赖性冲突而无法安装。

依赖循环

即依赖性关系形成一个闭合环路,最终导致:在安装 A 软件包之前,必须要安装 A、B、C、D 软件包,然而这是不可能的。

语义化版本

为了解决依赖地狱,Tom Preston-Werner 提议用一组简单的规则及条件来约束版本号的配置和增长。这些规则是根据(但不局限于)已经被各种封闭、开放源码软件所广泛使用的惯例所设计。为了让这套理论运作,你必须先有定义好的公共 API 。这可以透过文件定义或代码强制要求来实现。无论如何,这套 API 的清楚明了是十分重要的。一旦你定义了公共 API,你就可以透过修改相应的版本号来向大家说明你的修改。考虑使用这样的版本号格式:X.Y.Z (主版本号.次版本号.修订号)修复问题但不影响 API 时,递增修订号;API 保持向下兼容的新增及修改时,递增次版本号;进行不向下兼容的修改时,递增主版本号。Tom Preston-Werner 称这套系统为语义化版本控制

版本格式

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

先行版本号及版本编译元数据可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

training

规范

以下关键词 MUST、MUST NOT、REQUIRED、SHALL、SHALL NOT、SHOULD、SHOULD NOT、 RECOMMENDED、MAY、OPTIONAL 依照 RFC 2119 的叙述解读。

FAQ

小结

在软件管理中,一定要重视版本控制。否则,一不留神依赖地狱就向你招手。 语义化版本提供了一套简单有效的方案帮助我们尽量避免依赖地狱的出现。但是,语义化版本只是一个规范,规范都是需要人去执行才能有效。作为一位负责任的开发者,你理当确保每次包升级的运作与版本号的表述一致。现实世界是复杂的,我们除了提高警觉外能做的不多。你所能做的就是让语义化的版本控制为你提供一个健全的方式来发行以及升级包,而无需推出新的依赖包,节省你的时间及烦恼。

在实践中,大家可以参考 react 项目。下面是遵从了语义化版本规范的 react 依赖图:

training

注:npm 的依赖关系图,可以通过http://npm.broofa.com/?q=react@16.3.1 查看

另外,推荐大家使用 git 的 tag&release,将版本“持久化”,这有助于避免一些规范的问题,如下图所示:

training training

参考

上一篇 下一篇

猜你喜欢

热点阅读