RESTful API 版本控制最佳实践:为什么 v1 是第一
克里斯·麦克法登
2017年5月24日
电子邮件
1 min read

关键要点
API 版本控制防止重大更改,并维护 API 提供商和开发者之间的信任。
清晰的版本控制规范有助于避免端点之间版本混乱的局面。
RESTful API 与简单、明确的版本 URI 配合使用,让开发人员的集成直观易用。
治理小组确保团队之间的一致性,防止意外的重大更改。
并非所有更改都需要新版本 — 只有那些破坏现有集成的更改才需要。
良好的文档对于避免混淆和防止不经意的重大更改至关重要。
将部署与发布分开可以让团队在公布之前安全地测试和完善端点。
当重大更改不可避免时,必须仔细评估并进行沟通。
Q&A 精华
为什么API版本控制很重要?
这可以防止开发人员在与您的API集成时遇到意外的重大变化,保护信任,并确保依赖稳定行为的应用程序的长期稳定性。
什么是API中的重大变更?
任何更改现有集成行为的修改,例如移除端点、更改默认值、添加必填字段或修改响应格式。
为何SparkPost选择REST作为他们API的基础?
REST 使用 HTTP 和 JSON 使得不同语言 (PHP, Ruby, Java 等) 的开发人员无需专门了解底层系统也能轻松集成。
SparkPost是如何确定其版本方法的?
他们评估了 Accept-header 版本控制与 URI 版本控制,并选择了 URI 版本控制,因为它明确、简单且对开发者更友好。
API治理组的作用是什么?
这确立了标准,执行了一致性,防止团队引入与规范冲突或破坏兼容性的更改。
哪些类型的更改不被视为破坏性更改?
添加新的可选参数、引入新的端点、在JSON有效负载中添加新键或更改非公共端点——任何不干扰现有行为的操作。
哪些更改被视为重大更改?
添加必需的参数,删除终端,改变默认行为,修改响应结构,或引入必需的 JSON 字段。
为什么准确的文档很重要?
它防止了意外的破坏性更改,帮助开发人员理解行为,并确保团队可靠地更新API。SparkPost使用了Markdown(API Blueprint)和GitHub来保持清晰和开放。
将部署与发布分开的好处是什么?
团队可以在内部持续部署新的端点或增强功能,在实际工作流程中测试它们,优化行为,并仅在稳定后公开发布——避免过早和潜在破坏性的暴露。
如果需要进行重大变更,会发生什么情况?
这必须是罕见的,由明确的好处来证明,谨慎评估对用户的影响,并彻底沟通。示例:仅在确认影响最小时调整 Suppression API,并提供通知。
所以,将一个API版本化能有多难呢?事实是,它并不难,但困难的是保持理智,不要在数十个API端点上不必要地演变成令人眼花缭乱的多个版本和子版本,而这些端点的兼容性尚不明确。
所以,将一个API版本化能有多难呢?事实是,它并不难,但困难的是保持理智,不要在数十个API端点上不必要地演变成令人眼花缭乱的多个版本和子版本,而这些端点的兼容性尚不明确。
所以,将一个API版本化能有多难呢?事实是,它并不难,但困难的是保持理智,不要在数十个API端点上不必要地演变成令人眼花缭乱的多个版本和子版本,而这些端点的兼容性尚不明确。
哎呀!
必须承认,有时候我们没有完全遵循我们的“无破坏性更改”理想,这些情况值得我们学习。在一次情况下,我们认为如果一个特性默认设置为true而不是false,对用户来说会更好。我们部署更改后,收到了用户的多次投诉,因为行为意外发生了变化。 我们撤销了更改,并添加了一个账户级别的设置——这无疑是一种更加用户友好的方法。
有时我们希望通过修复错误来引入破坏性更改。然而,我们决定保留这些特性独特性,而不是为了一致性而冒着破坏客户集成的风险。
极少情况下,我们会做出关键决定,做出破坏性更改——比如弃用一个API资源或方法——这是为了更广大用户社区的利益,并且只有在确认对用户几乎没有影响后才会进行。例如,我们有意识地选择改变了Suppression API的响应行为,但这是在仔细权衡对社区的好处和影响并且认真与用户沟通过更改后才实施的。然而,我们 绝不会 引入任何可能直接影响用户生产邮件发送的更改。
必须承认,有时候我们没有完全遵循我们的“无破坏性更改”理想,这些情况值得我们学习。在一次情况下,我们认为如果一个特性默认设置为true而不是false,对用户来说会更好。我们部署更改后,收到了用户的多次投诉,因为行为意外发生了变化。 我们撤销了更改,并添加了一个账户级别的设置——这无疑是一种更加用户友好的方法。
有时我们希望通过修复错误来引入破坏性更改。然而,我们决定保留这些特性独特性,而不是为了一致性而冒着破坏客户集成的风险。
极少情况下,我们会做出关键决定,做出破坏性更改——比如弃用一个API资源或方法——这是为了更广大用户社区的利益,并且只有在确认对用户几乎没有影响后才会进行。例如,我们有意识地选择改变了Suppression API的响应行为,但这是在仔细权衡对社区的好处和影响并且认真与用户沟通过更改后才实施的。然而,我们 绝不会 引入任何可能直接影响用户生产邮件发送的更改。
必须承认,有时候我们没有完全遵循我们的“无破坏性更改”理想,这些情况值得我们学习。在一次情况下,我们认为如果一个特性默认设置为true而不是false,对用户来说会更好。我们部署更改后,收到了用户的多次投诉,因为行为意外发生了变化。 我们撤销了更改,并添加了一个账户级别的设置——这无疑是一种更加用户友好的方法。
有时我们希望通过修复错误来引入破坏性更改。然而,我们决定保留这些特性独特性,而不是为了一致性而冒着破坏客户集成的风险。
极少情况下,我们会做出关键决定,做出破坏性更改——比如弃用一个API资源或方法——这是为了更广大用户社区的利益,并且只有在确认对用户几乎没有影响后才会进行。例如,我们有意识地选择改变了Suppression API的响应行为,但这是在仔细权衡对社区的好处和影响并且认真与用户沟通过更改后才实施的。然而,我们 绝不会 引入任何可能直接影响用户生产邮件发送的更改。
重大变化不好!API版本控制好!
正如任何构建或经常使用API的人迟早会意识到的,重大更改是非常糟糕的,并且会成为一个原本有用的API上的严重瑕疵。重大更改是指API行为的更改,这种更改会破坏用户的集成,并导致API提供者和用户之间的巨大挫折和信任缺失。重大更改需要提前通知用户(并附上道歉),而不是像令人愉悦的新功能那样直接显示出来。避免这种挫折的方法是对API进行版本控制,并通过API所有者的保证,确保在任何单个版本中不会引入令人意外的更改。
那么,给API设定版本有多难呢?事实是,这并不难,但困难的是在不必要地陷入眼花缭乱的版本和子版本之中、遍布几十个API端点且兼容性不明确的情况下,保持一些理智。
我们在三年前推出了API的v1版本,并未意识到它会一直走到今天。那么,我们是如何在两年多的时间里继续提供最佳的邮件传递API,但仍然保持同一API版本呢?这种稳定性对于在云基础设施中构建应用程序的开发者至关重要,在这里,可靠性和一致性是首要的。虽然对于如何给REST API设定版本有很多不同的意见,但我希望,我们谦逊而强大的v1的故事能在你走向API版本化启蒙的道路上提供指导。
正如任何构建或经常使用API的人迟早会意识到的,重大更改是非常糟糕的,并且会成为一个原本有用的API上的严重瑕疵。重大更改是指API行为的更改,这种更改会破坏用户的集成,并导致API提供者和用户之间的巨大挫折和信任缺失。重大更改需要提前通知用户(并附上道歉),而不是像令人愉悦的新功能那样直接显示出来。避免这种挫折的方法是对API进行版本控制,并通过API所有者的保证,确保在任何单个版本中不会引入令人意外的更改。
那么,给API设定版本有多难呢?事实是,这并不难,但困难的是在不必要地陷入眼花缭乱的版本和子版本之中、遍布几十个API端点且兼容性不明确的情况下,保持一些理智。
我们在三年前推出了API的v1版本,并未意识到它会一直走到今天。那么,我们是如何在两年多的时间里继续提供最佳的邮件传递API,但仍然保持同一API版本呢?这种稳定性对于在云基础设施中构建应用程序的开发者至关重要,在这里,可靠性和一致性是首要的。虽然对于如何给REST API设定版本有很多不同的意见,但我希望,我们谦逊而强大的v1的故事能在你走向API版本化启蒙的道路上提供指导。
正如任何构建或经常使用API的人迟早会意识到的,重大更改是非常糟糕的,并且会成为一个原本有用的API上的严重瑕疵。重大更改是指API行为的更改,这种更改会破坏用户的集成,并导致API提供者和用户之间的巨大挫折和信任缺失。重大更改需要提前通知用户(并附上道歉),而不是像令人愉悦的新功能那样直接显示出来。避免这种挫折的方法是对API进行版本控制,并通过API所有者的保证,确保在任何单个版本中不会引入令人意外的更改。
那么,给API设定版本有多难呢?事实是,这并不难,但困难的是在不必要地陷入眼花缭乱的版本和子版本之中、遍布几十个API端点且兼容性不明确的情况下,保持一些理智。
我们在三年前推出了API的v1版本,并未意识到它会一直走到今天。那么,我们是如何在两年多的时间里继续提供最佳的邮件传递API,但仍然保持同一API版本呢?这种稳定性对于在云基础设施中构建应用程序的开发者至关重要,在这里,可靠性和一致性是首要的。虽然对于如何给REST API设定版本有很多不同的意见,但我希望,我们谦逊而强大的v1的故事能在你走向API版本化启蒙的道路上提供指导。
REST Is Best
The SparkPost API 源自我们还是 Message Systems 的时候,那时我们的云冒险还未开始。当时我们正忙于为 Momentum 4 的测试版发布做最后的准备。这是对我们市场领先的本地 MTA 版本 3.x 的重大升级。Momentum 4 包含全新的 UI、实时分析,最重要的是一个新的网页 API,用于消息注入和生成、管理模板以及获取邮箱指标。我们的愿景是一个 API 优先的架构——甚至连 UI 也会与 API 终端互动。
我们做出的最早也是最好的决定之一是采用 RESTful 风格。自 2000 年代后期以来,基于表现状态转换 (REST) 的网页 API 成为云 API 的事实标准。使用 HTTP 和 JSON 让开发人员无论使用哪种编程语言——PHP、Ruby 和 Java——都可以轻松地与我们的 API 集成,而无需了解或关心我们的底层技术。然而,大规模构建云原生 API 会带来意想不到的基础设施挑战,例如我们在处理大规模 API 流量时在 AWS 中遇到的DNS 扩展限制。
选择使用 RESTful 架构很容易。选择版本控制方式就不那么容易了。最初我们通过完全不对测试版进行版本控制来搁置这个问题。然而,在几个月内,测试版已交到少数客户手中,我们开始构建我们的云服务。是时候定义版本了。我们评估了两种版本控制方式。
版本控制方式 | 工作原理 | 权衡利弊 |
|---|---|---|
URI 版本控制 | 版本包含在终端路径中 | 明确且易于理解 |
Accept header 版本控制 | 版本通过 HTTP header 传递 | 不太明显,对开发者来说更复杂 |
第一个方案是将版本控制直接放入 URI,第二个方案是使用 Accept header。第一个方案更明确并且更简单,这对开发者来说更容易。由于我们热爱开发者,这是个合乎逻辑的选择。
The SparkPost API 源自我们还是 Message Systems 的时候,那时我们的云冒险还未开始。当时我们正忙于为 Momentum 4 的测试版发布做最后的准备。这是对我们市场领先的本地 MTA 版本 3.x 的重大升级。Momentum 4 包含全新的 UI、实时分析,最重要的是一个新的网页 API,用于消息注入和生成、管理模板以及获取邮箱指标。我们的愿景是一个 API 优先的架构——甚至连 UI 也会与 API 终端互动。
我们做出的最早也是最好的决定之一是采用 RESTful 风格。自 2000 年代后期以来,基于表现状态转换 (REST) 的网页 API 成为云 API 的事实标准。使用 HTTP 和 JSON 让开发人员无论使用哪种编程语言——PHP、Ruby 和 Java——都可以轻松地与我们的 API 集成,而无需了解或关心我们的底层技术。然而,大规模构建云原生 API 会带来意想不到的基础设施挑战,例如我们在处理大规模 API 流量时在 AWS 中遇到的DNS 扩展限制。
选择使用 RESTful 架构很容易。选择版本控制方式就不那么容易了。最初我们通过完全不对测试版进行版本控制来搁置这个问题。然而,在几个月内,测试版已交到少数客户手中,我们开始构建我们的云服务。是时候定义版本了。我们评估了两种版本控制方式。
版本控制方式 | 工作原理 | 权衡利弊 |
|---|---|---|
URI 版本控制 | 版本包含在终端路径中 | 明确且易于理解 |
Accept header 版本控制 | 版本通过 HTTP header 传递 | 不太明显,对开发者来说更复杂 |
第一个方案是将版本控制直接放入 URI,第二个方案是使用 Accept header。第一个方案更明确并且更简单,这对开发者来说更容易。由于我们热爱开发者,这是个合乎逻辑的选择。
The SparkPost API 源自我们还是 Message Systems 的时候,那时我们的云冒险还未开始。当时我们正忙于为 Momentum 4 的测试版发布做最后的准备。这是对我们市场领先的本地 MTA 版本 3.x 的重大升级。Momentum 4 包含全新的 UI、实时分析,最重要的是一个新的网页 API,用于消息注入和生成、管理模板以及获取邮箱指标。我们的愿景是一个 API 优先的架构——甚至连 UI 也会与 API 终端互动。
我们做出的最早也是最好的决定之一是采用 RESTful 风格。自 2000 年代后期以来,基于表现状态转换 (REST) 的网页 API 成为云 API 的事实标准。使用 HTTP 和 JSON 让开发人员无论使用哪种编程语言——PHP、Ruby 和 Java——都可以轻松地与我们的 API 集成,而无需了解或关心我们的底层技术。然而,大规模构建云原生 API 会带来意想不到的基础设施挑战,例如我们在处理大规模 API 流量时在 AWS 中遇到的DNS 扩展限制。
选择使用 RESTful 架构很容易。选择版本控制方式就不那么容易了。最初我们通过完全不对测试版进行版本控制来搁置这个问题。然而,在几个月内,测试版已交到少数客户手中,我们开始构建我们的云服务。是时候定义版本了。我们评估了两种版本控制方式。
版本控制方式 | 工作原理 | 权衡利弊 |
|---|---|---|
URI 版本控制 | 版本包含在终端路径中 | 明确且易于理解 |
Accept header 版本控制 | 版本通过 HTTP header 传递 | 不太明显,对开发者来说更复杂 |
第一个方案是将版本控制直接放入 URI,第二个方案是使用 Accept header。第一个方案更明确并且更简单,这对开发者来说更容易。由于我们热爱开发者,这是个合乎逻辑的选择。
API 管理
选择了版本控制约定后,我们有了更多问题。我们什么时候调高版本?什么是重大更改?我们会重新定版本整个API还是仅重新定版本某些端点?在SparkPost,我们有多个团队在API的不同部分工作。在这些团队中,人们在不同时间工作于不同的端点。因此,我们的API在使用约定方面的一致性非常重要。这比版本控制更重要。
我们成立了一个治理小组,包括每个团队的代表工程师、产品管理团队的一位成员以及我们的CTO。这个小组负责建立、记录和执行我们在所有团队中的API约定。一个API治理 Slack频道也为关于这个话题的激烈讨论提供了便利。
治理小组识别出多种可以引入API的方式,它们对用户有益且不构成重大更改。
更改类型 | 被视为破坏性? | 原因 |
|---|---|---|
新资源或端点 | 否 | 不影响现有集成 |
新的可选参数 | 否 | 现有请求仍然有效 |
新的可选JSON键 | 否 | 客户端可以安全忽略 |
新响应字段 | 否 | 对消费方保持向后兼容 |
新必需参数 | 是 | 破坏现有请求 |
新的必需POST键 | 是 | 使现有有效负载无效 |
移除端点 | 是 | 现有集成失败 |
更改默认行为 | 是 | 改变预期结果 |
这些包括:
新的资源或API端点
新的可选参数
对非公共API端点的更改
在JSON POST主体中新的可选键
在JSON响应体中返回的新键
相反,重大更改包括任何可能中断用户集成的内容,例如:
新的必需参数
POST主体中新的必需键
移除现有的端点
移除现有的端点请求方法
API调用内部行为的重大不同,例如默认行为的更改。
选择了版本控制约定后,我们有了更多问题。我们什么时候调高版本?什么是重大更改?我们会重新定版本整个API还是仅重新定版本某些端点?在SparkPost,我们有多个团队在API的不同部分工作。在这些团队中,人们在不同时间工作于不同的端点。因此,我们的API在使用约定方面的一致性非常重要。这比版本控制更重要。
我们成立了一个治理小组,包括每个团队的代表工程师、产品管理团队的一位成员以及我们的CTO。这个小组负责建立、记录和执行我们在所有团队中的API约定。一个API治理 Slack频道也为关于这个话题的激烈讨论提供了便利。
治理小组识别出多种可以引入API的方式,它们对用户有益且不构成重大更改。
更改类型 | 被视为破坏性? | 原因 |
|---|---|---|
新资源或端点 | 否 | 不影响现有集成 |
新的可选参数 | 否 | 现有请求仍然有效 |
新的可选JSON键 | 否 | 客户端可以安全忽略 |
新响应字段 | 否 | 对消费方保持向后兼容 |
新必需参数 | 是 | 破坏现有请求 |
新的必需POST键 | 是 | 使现有有效负载无效 |
移除端点 | 是 | 现有集成失败 |
更改默认行为 | 是 | 改变预期结果 |
这些包括:
新的资源或API端点
新的可选参数
对非公共API端点的更改
在JSON POST主体中新的可选键
在JSON响应体中返回的新键
相反,重大更改包括任何可能中断用户集成的内容,例如:
新的必需参数
POST主体中新的必需键
移除现有的端点
移除现有的端点请求方法
API调用内部行为的重大不同,例如默认行为的更改。
选择了版本控制约定后,我们有了更多问题。我们什么时候调高版本?什么是重大更改?我们会重新定版本整个API还是仅重新定版本某些端点?在SparkPost,我们有多个团队在API的不同部分工作。在这些团队中,人们在不同时间工作于不同的端点。因此,我们的API在使用约定方面的一致性非常重要。这比版本控制更重要。
我们成立了一个治理小组,包括每个团队的代表工程师、产品管理团队的一位成员以及我们的CTO。这个小组负责建立、记录和执行我们在所有团队中的API约定。一个API治理 Slack频道也为关于这个话题的激烈讨论提供了便利。
治理小组识别出多种可以引入API的方式,它们对用户有益且不构成重大更改。
更改类型 | 被视为破坏性? | 原因 |
|---|---|---|
新资源或端点 | 否 | 不影响现有集成 |
新的可选参数 | 否 | 现有请求仍然有效 |
新的可选JSON键 | 否 | 客户端可以安全忽略 |
新响应字段 | 否 | 对消费方保持向后兼容 |
新必需参数 | 是 | 破坏现有请求 |
新的必需POST键 | 是 | 使现有有效负载无效 |
移除端点 | 是 | 现有集成失败 |
更改默认行为 | 是 | 改变预期结果 |
这些包括:
新的资源或API端点
新的可选参数
对非公共API端点的更改
在JSON POST主体中新的可选键
在JSON响应体中返回的新键
相反,重大更改包括任何可能中断用户集成的内容,例如:
新的必需参数
POST主体中新的必需键
移除现有的端点
移除现有的端点请求方法
API调用内部行为的重大不同,例如默认行为的更改。
The Big 1.0
在我们记录和讨论这些约定时,我们也得出结论,要避免对 API 进行破坏性更改,因为管理多个版本会产生相当多的开销,这符合每个人(包括我们自己的)最大利益。我们决定在确定“v1”之前,有一些事情需要修正我们的 API。
发送一个简单的电子邮件需要太多努力。为了“保持简单的事情简单”,我们更新了 POST 主体,以确保简单和复杂的使用案例都能得到满足。新的格式也更加适合未来。其次,我们解决了 Metrics 端点的问题。这个端点使用了一个“group_by”参数,该参数会改变 GET 响应主体的格式,使第一个键成为按参数分组的值。这看起来不太符合 RESTful 原则,所以我们将每个分组拆分为单独的端点。最后,我们审核了每个端点,并在这里和那里做了细微的更改,以确保它们符合标准。
在我们记录和讨论这些约定时,我们也得出结论,要避免对 API 进行破坏性更改,因为管理多个版本会产生相当多的开销,这符合每个人(包括我们自己的)最大利益。我们决定在确定“v1”之前,有一些事情需要修正我们的 API。
发送一个简单的电子邮件需要太多努力。为了“保持简单的事情简单”,我们更新了 POST 主体,以确保简单和复杂的使用案例都能得到满足。新的格式也更加适合未来。其次,我们解决了 Metrics 端点的问题。这个端点使用了一个“group_by”参数,该参数会改变 GET 响应主体的格式,使第一个键成为按参数分组的值。这看起来不太符合 RESTful 原则,所以我们将每个分组拆分为单独的端点。最后,我们审核了每个端点,并在这里和那里做了细微的更改,以确保它们符合标准。
在我们记录和讨论这些约定时,我们也得出结论,要避免对 API 进行破坏性更改,因为管理多个版本会产生相当多的开销,这符合每个人(包括我们自己的)最大利益。我们决定在确定“v1”之前,有一些事情需要修正我们的 API。
发送一个简单的电子邮件需要太多努力。为了“保持简单的事情简单”,我们更新了 POST 主体,以确保简单和复杂的使用案例都能得到满足。新的格式也更加适合未来。其次,我们解决了 Metrics 端点的问题。这个端点使用了一个“group_by”参数,该参数会改变 GET 响应主体的格式,使第一个键成为按参数分组的值。这看起来不太符合 RESTful 原则,所以我们将每个分组拆分为单独的端点。最后,我们审核了每个端点,并在这里和那里做了细微的更改,以确保它们符合标准。
准确的Documentation
拥有准确且可用的API文档至关重要,以避免有意或无意的重大更改。我们决定使用一个简单的API文档方法,采用一种名为API Blueprint的Markdown语言,并在Github中管理我们的文档。我们的社区为这些开源文档做出贡献并加以改进。我们还在Github中维护了一套非公开文档,用于内部API和端点。
最初,我们将文档发布到Apiary,这是一个用于原型设计和发布API文档的优秀工具。然而,将Apiary嵌入我们的网站在移动设备上不起作用,因此我们现在使用Jekyll来生成静态文档。我们最新的SparkPost API docs现在加载快速,并在移动设备上效果良好,这对不总是在电脑前坐着的开发者来说非常重要。
拥有准确且可用的API文档至关重要,以避免有意或无意的重大更改。我们决定使用一个简单的API文档方法,采用一种名为API Blueprint的Markdown语言,并在Github中管理我们的文档。我们的社区为这些开源文档做出贡献并加以改进。我们还在Github中维护了一套非公开文档,用于内部API和端点。
最初,我们将文档发布到Apiary,这是一个用于原型设计和发布API文档的优秀工具。然而,将Apiary嵌入我们的网站在移动设备上不起作用,因此我们现在使用Jekyll来生成静态文档。我们最新的SparkPost API docs现在加载快速,并在移动设备上效果良好,这对不总是在电脑前坐着的开发者来说非常重要。
拥有准确且可用的API文档至关重要,以避免有意或无意的重大更改。我们决定使用一个简单的API文档方法,采用一种名为API Blueprint的Markdown语言,并在Github中管理我们的文档。我们的社区为这些开源文档做出贡献并加以改进。我们还在Github中维护了一套非公开文档,用于内部API和端点。
最初,我们将文档发布到Apiary,这是一个用于原型设计和发布API文档的优秀工具。然而,将Apiary嵌入我们的网站在移动设备上不起作用,因此我们现在使用Jekyll来生成静态文档。我们最新的SparkPost API docs现在加载快速,并在移动设备上效果良好,这对不总是在电脑前坐着的开发者来说非常重要。
分离 Deployment 和 Release
我们很早就学到了一个宝贵的技巧,即将部署与发布分开。这样一来,当变更准备好后,可以通过持续交付和部署频繁地进行部署,但我们不总是同时公开宣布或记录这些变更。对于我们来说,在UI中或使用内部工具时,先部署一个新的API端点或对现有API端点的增强,而在公开记录和支持之前使用它,这并不罕见。这样,我们可以对其进行一些调整以提高可用性或符合标准,而不必担心造成令人害怕的重大变更。一旦我们对更改感到满意,我们就会将其添加到我们的公共文档中。
我们很早就学到了一个宝贵的技巧,即将部署与发布分开。这样一来,当变更准备好后,可以通过持续交付和部署频繁地进行部署,但我们不总是同时公开宣布或记录这些变更。对于我们来说,在UI中或使用内部工具时,先部署一个新的API端点或对现有API端点的增强,而在公开记录和支持之前使用它,这并不罕见。这样,我们可以对其进行一些调整以提高可用性或符合标准,而不必担心造成令人害怕的重大变更。一旦我们对更改感到满意,我们就会将其添加到我们的公共文档中。
我们很早就学到了一个宝贵的技巧,即将部署与发布分开。这样一来,当变更准备好后,可以通过持续交付和部署频繁地进行部署,但我们不总是同时公开宣布或记录这些变更。对于我们来说,在UI中或使用内部工具时,先部署一个新的API端点或对现有API端点的增强,而在公开记录和支持之前使用它,这并不罕见。这样,我们可以对其进行一些调整以提高可用性或符合标准,而不必担心造成令人害怕的重大变更。一旦我们对更改感到满意,我们就会将其添加到我们的公共文档中。



