惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
博客园 - Franky
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
L
LangChain Blog
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hacker News: Front Page
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
AI
AI
T
Troy Hunt's Blog
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
Attack and Defense Labs
Attack and Defense Labs

博客园 - 小陆

版本的故事(五)闯关旅程 从技术谈到管理,把系统优化的技术用到企业管理 版本的故事(四)版本号有多重要 版本的故事(二)版本的诞生 版本的故事(一)为什么要写版本的故事 程序配置的原则和实践以及 Spring Boot 支持方式 全文检索基本概念 Elasticsearch升级1.5版本暴露jdk的bug 以后还是要多写点博客 DateTime类型的一个Bug 完全命令行.NET开发 .NET初学者架构设计指南(四)Model-View-Controller .NET初学者架构设计指南(三)设计模式 .NET初学者架构设计指南(二)OO设计初次见面 .NET初学者架构设计指南(一)Hello world的时代 软件的逻辑层次 无痛苦的软件维护——被遗忘的需求 无痛苦的软件维护——文档和代码 NGOSS的一点简单概念
版本的故事(三)取个好名字
小陆 · 2020-09-02 · via 博客园 - 小陆

当我们发布一个版本的时候,需要为这个版本取一个名字,也称作版本号。本文说明编制版本号的方法。

版本编号有很多不同的方法,其中最常见的是“三段式”版本号,我们使用的操作系统、开发工具、编译器、库函数、中间件,很多都使用这种版本编号方式。比如:Zookeeper 3.4.13、Maven 3.6.2、Tomcat 9.0.2、MacOS 10.15.6、CentOS 7.3.1611。

以上软件涵盖了产品、组件两大类别,这两类对象都有“版本”,但是概念是有差别的,编号方式也不一样。本文只介绍组件版本,产品版本以后细说。

三段版本号是由三个数字组成的,分别称为 MAJOR、MINOR、PATCH。对于这个三个值有没有具体的编号标准呢?一个普遍的说法是:大修改升级 MAJOR,中等修改升级 MINOR,小修改升级 PATCH。但是多大的修改算大,多小的修改算小呢?以下是多年前看到的一本书上的描述,以下摘自《未雨绸缪——理解软件配置管理》(董越,2008):

按照书中的描述总结一下:

  • MAJOR:大量的修改,“完全不同”的新版本
  • MINOR:增加少量新功能
  • PATCH:Bug 修复

关于 PATCH 的描述已经很清楚了,但是 MAJOR 和 MINOR 还是有一些模糊。比如“完全不同”是界面完全不同,还是架构完全不同?再找一本书翻翻,以下摘自《微服务设计》(Sam Newman,2015):

 总结如下:

  • MAJOR:包含向后不兼容的修改
  • MINOR:有新功能的增加,但应该是向后兼容的
  • PATCH:对已有功能的缺陷修复

这种编号方式是以不同的数字段表示 API 的修改状态:MAJOR 升级表示发生了 API 不兼容的修改,通常称之为 Breaking change;MINOR 升级表示 API 有更改,但是仍然兼容上一个版本;PATCH 升级表示 API 没有变动,只有软件内部的变化。这样一来,版本号就不再是一个主观随意的标准了,而是非常明确客观的标准。这个规范就是著名的“语义化版本”。按照语义化版本,版本号体现的是 API 的变化状态,能够表达相邻版本之间的底层代码和修改内容的信息。遵守语义化版本,对于依赖管理有实质的意义。

举个例子说明语义化版本可以怎样改善我们的依赖管理:我们有个服务名叫 order-service,它需要依赖 product-service。开发时的依赖关系是这样的:

部署的时候,我们可以使用高版本的 product-service(大于 3.1.0 并且小于 4.0.0)代替 3.1.0 版本,比如下面这个依赖关系也是可以成立的:

这样我们就做到了:“一个客户端能够仅仅通过查看服务的版本号,就知道它是否能够与之进行集成”。这个信息给部署架构就带来了“弹性”,这种弹性对于部署工作是非常重要的。如果依赖关系是一个僵硬的整体,产品可能会陷入“版本锁死”的状态,给维护工作带来巨大的烦恼。我们为了完成一次升级,就要对每一个依赖包都做一次改版。

大型软件系统是由数量众多的组件和外部库组成的,每个组件都有多个版本。在这些组件中选择好用的版本,组成一个完整的系统是一个极具难度的事。一个令人十分痛苦的场景是:一个组件依赖两个组件,这两个组件都依赖另外一个组件,但它们所依赖的版本各不相同,在运行的时候可能就会出问题。这个问题我们称之为“菱形依赖问题”。很多项目组在菱形依赖中挣扎,一遍遍的部署调试,只是为了找到一个能在现场部署的版本。

语义化版本就是帮助我们脱离苦海的好办法,我们来举个例子,下面是一个菱形依赖的典型场景:

可以看到 B 和 C 都依赖 D,但是依赖的版本各有不同,这样就没有办法安装了。能不能找到 C 的某个版本,既能满足 A 的依赖关系,又可以满足 D 的依赖关系呢?我们翻阅 C 的发布历史(是的,一定要编写发布文档,并且永远保留它们),然后发现了这么一个版本:“C-1.8.0,2020年8月1日发布,依赖 D-2.5.2”,太好了,找到了!

现在集成 C-1.8.0,新的依赖关系是这样的:

分析一下:C-1.8.0 是 C-1.5.7 的兼容升级版,因此能够满足 A 的依赖要求;D-2.7.11 是 D-2.5.2 的兼容升级版,因此我们只要部署一个 D-2.7.11,就能同时满足 B 和 D 的依赖条件。

是的,我们运气很好,恰好有一个合适的 C 版本。但是如果没有语义化版本,我们根本不可能有这个机会。

使用与语义化版本,组件就有了一个简单、准确的 API 规格。版本现在有了一个好名字。