发布于 2026-01-06 0 阅读
0

Fun with Feature Flags Why use feature flags? Implementing a Feature Flag Ways to Configure Feature Flags Objections to Feature Flags Next Steps

趣味特色标志

为什么要使用功能标志?

实现功能标志

配置功能标志的方法

对功能标志的反对意见

后续步骤

功能开关是一种简单的技术,可以让你切换软件中是否启用新的功能或其某些行为方式。

在本文中,我将讨论为什么这个想法并不像听起来那么疯狂,如何实现一个简单的功能开关,不同类型的功能开关以及触发每种功能开关的不同方法。

注意:如果您对“标志”一词感到困惑,可以把它想象成一个拨动开关或拨杆。它指的是一个布尔(真/假)变量,而不是一块随风飘动的布料。

为什么要使用功能标志?

乍一看,设置标志的想法似乎有点奇怪——毕竟,如果你不想让某个功能可用,为什么一开始就要把它放在代码里呢?

首先,对单个用户来说运行良好的功能,在生产环境中处理更广泛的数据集或交互时,可能无法正常工作。您可能需要定义一个仅限测试用户使用的功能标志,即仅对部分用户启用该功能,直到验证其运行无误后再正式发布。

Beta 用户可比其他用户更早获得新代码。

其次,许多产品都有精心安排的“上线”日期。您可能希望提前将新代码部署到生产环境,以降低任何额外的风险,然后在某个特定的日期到来时激活该功能。

最后,如果您频繁地将代码发布到生产环境,而大型功能(也称为史诗级功能)的开发周期又很长,那么分支管理就会变得非常困难。您会花费更多时间管理不同的分支,从而降低生产力,并错失在开发周期早期发现 bug 的机会。功能标志允许您在生产环境中以离线状态发布部分功能,但在完整功能准备就绪之前,先在 QA 或 Beta 环境中进行测试。

实现功能标志

那么,功能标志究竟长什么样呢?

private static IResumeAnalyzer GetResumeAnalyzer()
{
    // Check whatever configuration management this application uses
    if (ConfigHelper.GetBoolean("UseNewAnalyzer"))
    {
        return new RewrittenAnalyzer();
    }
    else
    {
        return new ResumeAnalyzer();
    }
}
Enter fullscreen mode Exit fullscreen mode

在上面的示例中,我们从应用程序框架所依赖的配置文件中提取一个设置。如果该设置的值UseNewAnalyzer设置为 true,则RewrittenAnalyzer使用新版本;否则,使用旧版本。

代码极其简单,但最终效果却截然不同:我们只需修改一个文件,应用程序的运行方式就会完全改变。根据您使用的编程语言和部署环境,甚至可能无需重启应用程序。

配置功能标志的方法

功能标志不一定需要通过配置文件来控制。在不同的场景下,还有许多其他选项可能更合适。

功能开关的常见触发条件包括:

  • 基于配置文件中的值(参见以上示例)
  • 基于数据库表中的值
  • 在特定日期(或日期范围内)激活或停用
  • 仅对测试版用户有效
  • 仅在一定比例的时间内或针对随机用户子集激活(通常用于 A/B 测试)
  • 基于外部 Web 服务调用返回的值
  • 由Launch Darkly等外部服务管理

对功能标志的反对意见

好的,功能开关使得离线部署代码或仅向特定用户群体部署代码变得更加容易。这听起来有利于提高代码质量,但缺点是什么呢?

天下没有免费的午餐,使用功能开关也需要在几个关键方面付出代价:

测试

由于现在需要测试激活和停用功能,测试变得更加困难和耗时。我见过一些团队尝试采用功能开关,只测试功能处于激活状态的情况,结果当功能部署到离线状态时,预览环境就崩溃了。

此外,如果各项功能相互关联且每项功能都有一个开关,则应测试所有不同功能状态的组合。这正是我强烈建议移除已全面上线或永久停用的功能的旧功能标志的关键原因。

数据库架构

如果你的新功能依赖于影响现有表的数据库迁移脚本,那么你需要考虑如果该功能离线,旧数据将如何处理;如果该功能需要从在线切换到离线(或反之亦然),会发生什么情况;以及其他各种问题。

通常最好的做法是在部署新功能开关的同时迁移数据——即使该开关处于离线状态,但这并非在所有情况下都可行。

或者,您可以将功能版本存储在正在修改的表的某一列中,以便区分哪些行与新功能关联,哪些行与旧版功能关联。这有助于您控制向新功能状态的迁移以及从旧版状态的迁移,但这样做会增加复杂性。

配置管理

配置越多,管理每个环境和跟踪每个环境中每个功能的状态就越困难,这可能会导致混乱或其他问题。

后续步骤

最终,对于需要提前推出的长期主要测试版功能,或者对于可能需要快速回滚而无需更改代码/部署的、风险较高的更改,功能标志是一个值得考虑的好东西。

如果您想了解更多关于 C# 中的功能标志的信息,请参阅我关于 FeatureToggle 的文章

虽然我在某些情况下会使用功能标志,但我更喜欢使用 Scientist 系列库来测试新代码在生产环境中的效果,而不会冒着影响用户的风险。

使用 Scientist 运行一个实验,该实验将使用一个旧版本和一个新版本的例程。

有关该过程的更多详细信息,请参阅我关于使用 Scientist .NET 进行无受害者金丝雀测试的文章。


封面照片由 Paul 拍摄,来自 Unsplash

文章来源:https://dev.to/integerman/fun-with-feature-flags-31jf