Flags 使用建议
我真正想要的是我的代码的行为由无法静态预测的全局变量控制,其使用情况未完全记录,并且只能非常困难地从我的代码中删除。” – 从来没有人
在生产代码中(尤其是在库中)常见的Flags使用是一个错误。除非确实必要,否则不要使用Flags。在那里,我们说了。
Flags是全局变量,更糟糕的是:您无法通过阅读代码知道该变量的值。Flags不仅可以在启动时设置,而且可以在以后通过任意方式进行更改。
如果您在二进制文件中运行服务器,通常无法保证Flags的值在每个周期中保持不变,也不能保证Flags值发生变化时发出任何通知,也不能保证任何方式来查找此类变化。
如果您的生产环境直接记录每个二进制文件的调用并存储这些日志,那就太好了。大多数环境并不是这样工作的。 对于库代码来说,这种不确定性尤其危险:如何判断某个特定功能的使用何时实际上已失效?简单的答案是:你不能。
Flags也使得将最后的赌注放在死代码中变得具有挑战性。在迁移到新后端的过程中,您可能会认为删除遗留代码只是删除不必要的构建依赖项并发布历史上最令人满意的 git rm 。
你错了。如果您的遗留二进制文件有数百个由生产代码定义和引用的Flags,那么简单地删除死代码会给您的发布工程师带来巨大的问题:在这样的更改之后几乎不会启动任何作业。
这一切中最糟糕的部分是什么? 我在 2023 年初对过去用过的项目,进行的一项分析发现,据我们所知,在上述数据保留限制内,大多数 C++ Flags实际上从未发生过变化。
然而,Flags在某些用例中是合适的:在没有启用Flags的回溯的情况下进行调试是不一样的。如果处理得当(并随后清理),功能Flags是完全合理的。
真正需要由英雄 SRE 调整的旋钮是一个方便的安全网。更广泛地说,用于将名称/值输入传递给二进制文件且仅在 main() 中使用的Flags比位置参数更易于维护。
即使考虑到这些警告,我们现在也应该认真审视一下Flags的使用。下次当您想向库中添加Flags时,请花一些时间寻找更好的方法。显式传递配置:这几乎总是更容易正确推理,
并且当然更容易维护。考虑将数字Flags放入编译时常量中。如果您在代码审查中遇到新Flags,请推迟。每一个Flags的引入都应该是合理的。