一次支持同一系统的多个版本的问题是这个问题的根源,也是我正在积极思考的一个问题。让我们一次一件!
什么是功能切换?
对不起其他答案!功能切换只需要做一件事:将功能发布与部署分离。正如这个问题所指出的,切换如何针对任何任意更改执行此操作是一个棘手的问题。
通常,为切换器供电的系统必须满足两个条件才能被认为是完整的:
- 向后兼容性。无论此切换的状态如何,旧功能都必须仍然有效。这包括此功能的旧行为!
- 前向兼容性。无论此切换的状态如何,新功能都必须正常运行。
对于任何重要的更改,这都是……具有挑战性的。无论如何,这是一个词
示例 1:UI 样式
假设您有一个无法访问其输入样式的表单。您的工作是修复样式以使其易于访问,但您使用基于主干的开发master
,并且您的团队希望在每天结束时将所有工作与您项目的唯一分支集成。
这种变化是极其孤立的。它影响:
- 单一表格
- 无功能(即无需更改业务逻辑)
- 没有非功能性需求(例如,这不会引入扩展问题)
因此,根据切换的状态切换加载哪个 CSS 样式表就足够了:
- 向后兼容性:没有功能受到影响,所以旧的东西应该默认工作。关闭标志不需要特殊行为,因此只需要简单的条件逻辑即可。
- 前向兼容性:这比较棘手,但假设表单已正确DRYed,任何新输入都将自动继承标志指示的样式。假设关注点分离良好,对这些样式的更改不会影响任何其他组件,反之亦然。
示例 2:一个新的表单域
我希望你喜欢这种美丽的简单,因为我们现在遇到了麻烦。这正是 OP 所描述的那种情况。
这种变化跨越多个系统。它影响(至少):
- 用户体验表单
- 后端的数据 API,因为有一个新字段
- 数据库层,因为有一个新字段
如此小的差异使事情变得更具挑战性。我们将在这里逐个系统地进行。
用户体验表格:
- 向后兼容性:与前面的示例相同。如果这确实是一个新领域,那么旧代码应该不在乎。此功能切换必须涵盖任何代码路径。
- 前向兼容性:这里的主要问题是某个字段可能在某一天存在,然后在下一次切换时消失。新逻辑可能需要在前端状态管理中设置一个默认值,或者由后端提供。
数据接口:
- 向后兼容性:此字段表示 API 合同的更改。为了支持某些用例(想到验证),如果切换关闭,可能需要提供默认值。否则,旧的东西应该没问题,虽然YMMV
- 前向兼容性:再一次,棘手的部分归结为确保在此切换关闭时有新代码可以使用。在最坏的情况下,可能需要将特殊的条件逻辑编码到新功能中来处理标志被关闭的情况
数据库层:
- 向后兼容性:在数据库级别,向后兼容性要求我们只添加可选字段。必要性可以在我们的应用程序的其他地方强制执行,但是如果模式添加了新的必填字段,则不能将其视为向后兼容。旧的插入和更新将立即中断。因此,您的数据迁移添加了一个新的可选字段。简单的?
- 前向兼容性:好的,新代码进来了。它应该期待这个领域吗?如果必须,这就是默认值发挥作用的地方。注意我没有指定什么应该声明默认值,因为这取决于应用程序,但必须有一些东西。在最坏的情况下,特殊的条件逻辑将不得不涵盖该字段是默认值的可能性。
这听起来很疯狂!我如何使其易于管理?
这里要遵循三个主要原则来保持理智:
- 让您的更改尽可能小,并重构阻止小更改的痛点。这意味着更多的标志,但更少的复杂性。增量改进是游戏的名称。
- 将长寿命标志视为关键的技术债务。您的标志不应该在生产中持续很长时间。对更改何时“稳定”有明确的规则,以及清理相关标志的清晰窗口。作为维护的常规部分清理标志对于控制需要支持多少代码路径至关重要。
- 不要教条主义!抛弃极端,必要时使用长期存在的特性分支。有些更改已经太复杂了,标记的额外开销是不值得的。如果您遵循第 1 点和第 2 点,这种情况应该会越来越少。
祝你好运!