改进rust代码的35种具体方法-类型(二十一)-熟悉Cargo.toml版本使用

上一篇文章-改进rust代码的35种具体方法-类型(二十)-避免过度优化的诱惑


“如果我们承认SemVer是一个有损的估计,只代表可能变化范围的子集,我们可以开始将其视为一个钝器。”——Titus Winters,“谷歌软件工程(O'Reilly)”

 Rust的软件包管理器Cargo允许根据语义版本控制(semver)自动选择Rust代码的依赖项。Cargo.toml节喜欢:

[dependencies]
serde = "1.4"

cargo表明这种依赖性可以接受的semver版本范围。官方文档提供了有关指定可接受版本的精确范围的详细信息,但以下是最常用的变体:

  • "1.2.3":指定任何与1.2.3兼容的版本都是可以接受的
  • "^1.2.3":是另一种更明确地指定相同事物的方法
  • "=1.2.3":针脚到一个特定版本,不接受替代品
  • "~1.2.3":允许与1.2.3兼容的版本,但仅在最后指定的组件更改的情况下(因此1.2.4是可以接受的,但1.3.0不是)
  • "1.2.*":接受与通配符匹配的任何版本

这些规范允许的示例如下表所示。

依赖版本规范
技术规格1.2.21.2.31.2.41.3.02.0.0
"1.2.3"
"^1.2.3"
"=1.2.3"
"~1.2.3"
"1.2.*"
"1.*"
"*"

在选择依赖版本时,Cargo通常会选择所有这些semver范围组合的最大版本。

由于语义版本化是cargo依赖性解决过程的核心,因此本项目探讨了有关semver含义的更多详细信息。

Semver必需

语义版本控制的要点列在semver文档的摘要中,转载如下:

给定一个版本号MAJOR.MINOR.PATCH,增加:

  • 当您进行不兼容的API更改时的主要版本
  • 当您以向后兼容的方式添加功能时,次要版本
  • 当您进行向后兼容的错误修复时,补丁版本

一个重要点潜伏在细节中:

一旦版本化软件包发布,该版本的内容不得修改。任何修改都必须作为新版本发布。

用不同的词来表达:

  • 更改任何内容都需要一个新的补丁版本。
  • 以一种方式东西添加到API中,这意味着板条箱的现有用户仍然需要编译和工作,需要小版本升级。
  • 删除更改API中的东西需要主要版本升级。

semver规则还有一个重要的codicil:

主要版本零(0.y.z)用于初始开发。任何事情都可能随时改变。公共API不应被视为稳定。

货物略微调整了最后一条规则,“左移”了早期的规则,以便最左侧非零组件的变化表明不兼容的变化。这意味着0.2.3到0.3.0可以包含不兼容的API更改,就像0.0.4到0.0.5一样。

Crate 作者的语义化版本控制

在理论上,理论等同于实践。但在实践中,情况并非如此。

作为一名板条箱作者,从理论上讲,这些规则中的第一条很容易遵守:如果你触摸任何东西,你需要一个新的版本。使用Git标签匹配发布版本可以对此有所帮助——默认情况下,标签固定为特定提交,只能使用手动--force选项移动。发布tocrates crates.io版本也会对此进行自动监管,因为注册表将拒绝发布同一板条箱版本的第二次尝试。不合规的主要危险是,当你在发布后不久就注意到一个错误,你必须抵制只是扼杀修复的诱惑。

semver规范涵盖了API的兼容性,因此,如果您对行为进行了不改变API的细微更改,那么就应该只需要更新补丁版本。(然而,如果您的板条箱被广泛依赖,那么在实践中,您可能需要了解Hyrum定律:无论您对代码所做的更改有多小,即使API没有变化,也可能会依赖旧行为。)

对于板条箱作者来说,困难的部分是后一种规则,这需要准确确定更改是否与后兼容。一些更改显然不兼容——删除公共入口点或类型,更改方法签名——一些更改显然是向后兼容的(例如,向struct添加新方法,或添加新常量),但中间还剩下很多灰色区域。

为了帮助解决这个问题, 在Cargo 书中相当详细地阐述了什么是兼容的,什么是不兼容的。这些细节大多不足为奇,但有几个方面值得强调:

规则的一个明显推论是:一个 crate 拥有的公共项越少,就越少会导致不兼容改变的事物。

然而,不可否认的是,从一个版本到下一个版本比较所有公共 API 项的兼容性是一个耗时的过程,最好只能得出对变更级别(主要/次要/修订)的粗略评估。考虑到这种比较是一个有些机械化的过程,希望能够出现工具来简化这个过程。

如果你确实需要进行不兼容的主版本更改,最好通过确保改变后仍提供相同的整体功能来为用户简化生活,即使 API 已经发生了根本性的改变。如果可能的话,对于 crate 用户来说,最有帮助的顺序如下:

  1. 发布一个包含新版本 API 的次要版本更新,并将旧版本标记为废弃,包括迁移的指示。
  2. 发布一个主要版本更新,移除 API 中已经废弃的部分。

一个更微妙的观点是要让破坏性改变真正成为破坏性。如果你的 crate 正在以一种对现有用户实际上不兼容的方式改变其行为,但可以重用相同的 API:不要这样做。强制更改类型(并进行主要版本升级),以确保用户不会无意中错误地使用新版本。

对于 API 的不太具体的部分,比如最低支持的 Rust 版本(MSRV)或许可证,请考虑建立一个 CI 检查,以便根据需要使用工具(例如 cargo-deny;)来检测变化。

最后,不要因为版本号达到 1.0.0 而感到害怕,因为这意味着你的 API 现在是固定的。许多 crate 陷入了永远停留在版本号为 0.x 的陷阱,但这将把 semver 的三个类别(主要/次要/修订)的表达能力减少到两个(有效主要/有效次要)。

Crate 用户的语义化版本(Semver)

对于一个 crate 的用户,对于一个依赖项的新版本的理论期望如下:

  • 一个依赖 crate 的新修订版本应该“立即可用”。
  • 一个依赖 crate 的新次要版本应该“立即可用”,但新的 API 部分可能值得探索,看看是否有更清晰或更好的使用方式。然而,如果你使用了新的部分,就无法将依赖关系回滚到旧版本。
  • 对于一个依赖的新主要版本,一切皆有可能;很可能你的代码将不再能够编译,并且你需要重写部分代码以符合新的 API。即使你的代码仍然能够编译,你也应该检查在主要版本变更后你对 API 的使用是否仍然有效,因为库的约束和前置条件可能已经发生了变化。

实际上,即使前两种类型的更改可能会导致意外行为变化,即使代码仍然能够正常编译,也可能受到海伦姆法则的影响。

由于这些期望,你的依赖规范通常会采用类似"1.4.3"或"0.7"的形式,其中包括后续兼容的版本;避免指定完全通配符依赖,如""或"0."。完全通配符依赖表示你的 crate 可以使用任何版本的依赖,具有任何 API,这不太可能是你真正想要的。避免使用通配符也是发布到 crates.io 的要求;带有"*"通配符的提交将被拒绝。

然而,从长远来看,忽略依赖关系中的主要版本更改是不安全的。一旦一个库经历了主要版本更改,进一步的 bug 修复——更重要的是安全更新——可能不会应用到之前的主要版本。像"1.4"这样的版本规范将会随着新的 2.x 发布的到来而逐渐落后,其中的安全问题也会被忽视。

因此,你需要接受被困在旧版本上的风险,或者最终跟随依赖关系的主要版本升级。诸如 cargo update 或 Dependabot(第 31 条)等工具可以在更新可用时通知你;然后你可以安排升级的时间,以便适合你的方便。

讨论

语义化版本控制也是有成本的:每次对 crate 的更改都必须根据其标准进行评估,以决定适当的版本升级类型。语义化版本控制也是一个粗糙的工具:充其量只能反映 crate 所有者对当前发布属于三个类别中的哪一种的猜测。并非每个人都能做到完全正确,关于“正确”究竟意味着什么也并非一切都清楚明了,即使你做对了,也总有可能会违反海伦姆法则。

然而,对于那些没有幸运地在像谷歌这样经过高度测试的巨大内部单库环境中工作的人来说,语义化版本控制是唯一的选择。因此,理解其概念和局限性对于管理依赖关系是必要的。


例如,cargo-semver-checks 是一种试图在这些方面做一些事情的工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/20235.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32_FSMC_HAL(介绍)

FSMC(Flexible Static Memory Controller)是STM32微控制器中的一种内存控制器,它允许微控制器与外部存储器接口,如SRAM、NOR Flash、NAND Flash和PSRAM等。FSMC特别适用于需要高速数据交换和大量数据存储的应用场景。 典型应用&a…

参数的读取

argparse函数的读取 这个是以函数的形式嵌入到脚本中的 def common_args():parser argparse.ArgumentParser(descriptioncommon config)parser.add_argument(--test, actionstore_true, help"test mode (load model and test dataset)")parser.add_argument(--ite…

AndroidStudio设置允许APP获取定位权限

1. 在AndroidManifest.xml中声明权限 常用的定位权限有以下两种&#xff1a; <uses-permission android:name"android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name"android.permission.ACCESS_COARSE_LOCATION"/>2. …

react跨组件通信Context

案例&#xff1a;现在有个父-子-孙组件 需要进行组件通信 import { useState } from "react"; // 创建上下文 const CountContext React.createContext();//子组件 const SonComponent (props) > {return (<div><h2>子组件</h2><Grandson…

【机器学习】让大模型变得更聪明

文章目录 前言1. 理解大模型的局限性1.1 理解力的挑战1.2 泛化能力的挑战1.3 适应性的挑战 2. 算法创新&#xff1a;提高模型学习和推理能力2.1 自监督学习2.2 强化学习2.3 联邦学习 3. 数据质量与多样性&#xff1a;增强模型的泛化能力3.1 高质量数据的获取3.2 数据多样性的重…

#1 深度优先搜索

深搜思想 DFS其实是针对图论的一种搜索算法&#xff0c;由一个节点出发&#xff0c;不撞南墙不回头式的遍历所有的节点。 如先遍历1&#xff0c;沿&#xff08;1,2&#xff09;遍历2&#xff0c;再沿&#xff08;2,4&#xff09;遍历4&#xff0c;撞南墙&#xff08;边界条件…

XSS另类攻击(四)kali系统beef-xss安装和使用

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、环境说明 kali系统&#xff0c;ip&#xff1a;192.1…

k8s的ci/cd实践之旅

书接上回k8s集群搭建完毕&#xff0c;来使用它强大的扩缩容能力帮我们进行应用的持续集成和持续部署&#xff0c;整体的机器规划如下&#xff1a; 1.192.168.8.156 搭建gitlab私服 docker pull gitlab/gitlab-ce:latest docker run --detach --hostname 192.168.8.156 --publ…

SAP 生产订单批量报工(代码分享)

最近公司一直在对成本这块的业务进行梳理,影响比较大的就是生产这块的报工,经常会要求要批量的冲销报工,然后在继续报工,来调整生产订单的实际工时,前面的博客中已经给大家分享了批量冲销生产订单的代码, 下面给大家分享一下生产订单批量报工的代码 首先流程制造和离散制…

推荐几首听无数遍也听不腻的好歌(1)

1.Wannabe (Spice Girls Cover) 这首歌是Why Mona创作的首红眼特效的歌&#xff0c;唱的像牙痛的唱不清楚&#xff0c;但配上超级劲爆的旋律及节奏&#xff0c;简直好听到爆 2.Down For Life (Reset) 这首HSHK创作的纯音乐&#xff0c;虽然旋律一直重复一个调&#xff0c;但…

【算法】过桥

✨题目链接&#xff1a; 过桥 ✨题目描述 ✨输入描述: 第一行一个数n(2≤n≤2000) 接下来一行n个数a[i](1≤|a[i]|≤2000)表示浮块上的数字 ✨输出描述: 输出一行&#xff0c;表示对应的答案 ✨示例1 &#x1f4cd;输入 4 2 2 -1 2 &#x1f4cd;输出 2 &#x1f4cd;说明 1…

前端经典手写面试题---节流防抖

防抖 定义: n 秒后在执行该事件&#xff0c;若在 n 秒内被重复触发&#xff0c;则重新计时。 场景: 搜索框搜索输入。只需用户最后一次输入完&#xff0c;再发送请求手机号、邮箱验证输入检测窗口大小resize。只需窗口调整完成后&#xff0c;计算窗口大小。防止重复渲染。 实…

HNCTF 2024 ez_pecp 冰蝎+CS流量分析

考点:冰蝎webshell流量分析CS4.x流量解密 给了两个 流量包 第一个 ctf1.pcapng 查看其HTTP请求 而在CS中流量特征是基于tls协议 http-beacon 通信中&#xff0c;默认使用 GET 方法向 /dpixel 、/__utm.gif 、/pixel.gif 等地址发起请求&#xff0c;而且下发指令的时候会请求 …

如何使用浔川AI翻译机?——浔川AI社

1 前言 对于“如何使用浔川AI翻译机&#xff1f;”这个问题&#xff0c;我们官方 总结出以下结论&#xff1a; 首先&#xff1a; 复制以下代码&#xff1a; # -*- coding: utf-8 -*- import tkinter as tk import tkinter.messagebox import pickle import random# 窗口 wi…

Springboot校验集合是否为空,校验集合内对象参数

一、示例1 public AjaxResult saveQuoted(RequestBody NotEmpty List< Valid HisParam> list) {}二、示例2 public class Comment {NotNull(message "orderId 不能为空")private Long orderId;ValidNotEmpty(message "itemList不能为空")private…

Jmeter压测中遇到的问题汇总

Jmeter使用过程问题总结 一、某个请求的请求体中有中文字段&#xff0c;执行后该请求无法成功 解决方法&#xff1a;在取样器的内容编码处加上UTF-8 二、遇到接口请求后报401&#xff0c;请求未授权&#xff08;或者信息头管理器只写了cookie请求不成功&#xff09; 解决方…

记录深度学习GPU配置,下载CUDA与cuDnn,安装tensorflow

目标下载: cuda 11.0.1_451.22 win10.exe cudnn-11.0-windows-x64-v8.0.2.39.zip Anaconda的安装请看别的博主的,这里不再赘述 看看自己电脑的cuda 方法一:打开英伟达面板查看 方法二:使用命令行 随便找个文件夹,在顶部路径输入"cmd" 输入下面命令 nvidia-smi 我…

【TensorFlow深度学习】深度学习中的梯度传播机制解析

深度学习中的梯度传播机制解析 反向传播基础理论概览梯例&#xff1a;Sigmoid激活函数的梯度传播实战例代码结构反向传播机制的精髓结语 深度学习中的梯度传播机制&#xff1a;揭秘神经网络的核心算法 深度学习的兴起&#xff0c;离不开一个至关重要的算法——反向传播&#xf…

2406C++,ADL加隐式转换

原文 最近在搞iguana.struct_pb动态反射功能时,遇见一个奇怪的问题. struct person {std::string name;int64_t age; }; REFLECTION(person, name, age); struct persons {std::vector<person> list; }; REFLECTION(persons, list); //#1 static_assert(iguana::is_publ…

小程序配置自定义tabBar及异形tabBar配置操作

什么是tabBar&#xff1f; 小程序的tabbar是指小程序底部的一组固定导航按钮&#xff0c;通常包含2-5个按钮&#xff0c;用于快速切换小程序的不同页面。每个按钮都有一个图标和文本标签&#xff0c;点击按钮可以切换到对应的页面。tabbar通常放置在小程序的底部&#xff0c;以…