Title: 最佳实践 Locale: zh URL: https://sensorswave.com/docs/feature-gates/best-practices/ Description: 掌握功能开关的最佳使用方法和实施建议 本文总结了功能开关使用的最佳实践,帮助您更有效地使用功能开关,避免常见问题。 ## 功能开关的业务分类 > **说明**:以下开关类型分类是一种建议性的管理方法,并非产品内置功能。您可以根据团队需要自行定义分类标准。 根据业务需要和使用场景,建议将功能开关划分为以下三种类型: ### 临时开关(Temporary Gates) **定义**:用于新功能的发布和验证,功能稳定后应该删除。 **使用场景**: - 新功能灰度发布 - 功能稳定性验证 - 短期 A/B 测试前置 **生命周期**: 1. 创建开关,默认关闭 2. 逐步灰度,验证稳定性 3. 全量发布后,移除代码中的开关判断 4. 归档或删除功能开关 **示例**: ```javascript // 临时开关:新推荐算法 const useNewAlgorithm = await SensorsWave.checkFeatureGate('new_recommendation_algorithm'); ``` **最佳实践**:临时开关应该在功能全量发布后的 1-2 个月内清理,避免累积过多无用的开关。 ### 永久开关(Permanent Gates) **定义**:用于长期存在的功能分级,不同用户群体看到不同功能。 **使用场景**: - 付费功能控制 - 用户等级权限 - 地区定制功能 - 企业版 vs 基础版功能 **生命周期**: - 长期存在,与产品功能绑定 - 随着产品演进可能调整规则 - 通常不会删除 **示例**: ```javascript // 永久开关:高级分析功能(仅付费用户) const hasAdvancedAnalytics = await SensorsWave.checkFeatureGate('advanced_analytics_access'); ``` **管理建议**:永久开关通常与用户属性(如 `subscription_level`)关联,建议在开关命名中体现其业务用途。 ### 运维开关(Ops Gates) **定义**:用于系统运维和故障应急,快速降级非核心功能。 **使用场景**: - 功能降级保障 - 限流熔断 - 依赖服务隔离 - 紧急故障恢复 **生命周期**: - 长期存在,平时保持开启 - 故障时快速关闭 - 恢复后重新开启 **示例**: ```javascript // 运维开关:推荐系统开关(系统负载高时关闭) const recommendationEnabled = await SensorsWave.checkFeatureGate('recommendation_system_enabled'); if (recommendationEnabled) { // 调用推荐算法 recommendations = await getRecommendations(userId); } else { // 降级:使用默认推荐 recommendations = getDefaultRecommendations(); } ``` **管理建议**:核心业务流程应该配置运维开关,确保在依赖服务故障时仍能正常运行。 ### 类型对比 | 对比维度 | 临时开关 | 永久开关 | 运维开关 | |---------|---------|---------|---------| | **生命周期** | 短期(几周到几个月) | 长期(随产品存在) | 长期(随系统存在) | | **默认状态** | 通常关闭 | 根据用户属性决定 | 通常开启 | | **使用频率** | 灰度期间频繁调整 | 较少调整 | 故障时操作 | | **清理策略** | 全量后应删除 | 不删除 | 不删除 | | **典型场景** | 新功能发布 | 付费功能、权限控制 | 功能降级、限流 | ### 如何在团队中应用分类 1. **建立命名约定**:在开关名称中体现类型,如 `temp_*`、`perm_*`、`ops_*` 2. **文档记录**:在开关描述中注明类型和预期生命周期 3. **定期审查**:每月审查临时开关,及时清理已完成的功能 4. **定期检查**:定期检查运维开关的状态和覆盖范围 ## 命名规范 ### 开关命名原则 **使用清晰描述性的名称**: ``` ✅ 推荐 recommendation_algorithm_v2 payment_wechat_pay_enabled user_profile_redesign_2024 ❌ 不推荐 flag1 test new_feature temp_switch ``` ### 命名格式 **使用 snake_case 格式**: - 全部小写字母 - 单词之间用下划线连接 - 避免使用驼峰命名(camelCase) **添加模块前缀**: ``` recommendation_new_algorithm payment_alipay_enabled user_email_verification checkout_express_mode ``` **包含版本信息(如适用)**: ``` recommendation_algorithm_v2 checkout_flow_2024 ui_redesign_phase2 ``` ### 命名检查清单 在创建功能开关前,检查命名是否符合以下标准: - [ ] 使用 snake_case 格式 - [ ] 名称清晰描述功能 - [ ] 长度适中(15-40 个字符) - [ ] 包含模块前缀 - [ ] 不使用过于通用的名称(如 test, flag) - [ ] 团队成员能理解其含义 ## 生命周期管理 ### 临时开关的生命周期 **创建阶段**: 1. 明确功能开关的使用周期 2. 在描述中说明预计删除时间 3. 设置提醒,避免遗忘 **使用阶段**: 1. 按计划进行灰度发布 2. 监控关键指标 3. 记录重要的决策和变更 **清理阶段**: 1. 功能全量后,稳定运行 1-2 个月 2. 移除代码中的开关判断 3. 归档功能开关 4. 确认不再需要后删除 ### 永久开关的管理 **定期审查**: - 每季度审查一次永久开关 - 确认是否仍然需要 - 评估是否可以简化规则 **文档维护**: - 保持描述信息最新 - 记录使用场景和注意事项 - 更新相关的 Wiki 文档 ### 运维开关的管理 **平时保持开启**: - 默认值设置为开启 - 只在故障时关闭 **演练和测试**: - 定期演练降级流程 - 验证降级方案是否有效 - 确保团队熟悉操作流程 **文档记录**: - 记录每次使用的原因 - 总结经验教训 - 完善降级方案 ## 代码组织 ### 代码位置 **集中管理功能开关**: ```javascript // ✅ 推荐:集中定义功能开关 // src/config/featureGates.js NEW_RECOMMENDATION: 'recommendation_algorithm_v2', WECHAT_PAY: 'payment_wechat_pay_enabled', USER_PROFILE_REDESIGN: 'user_profile_redesign', }; // 使用时引用 const isEnabled = await SensorsWave.checkFeatureGate(FeatureGates.NEW_RECOMMENDATION); ``` ```javascript // ❌ 不推荐:硬编码字符串 const isEnabled = await SensorsWave.checkFeatureGate('recommendation_algorithm_v2'); ``` **优势**: - 集中管理,便于查看所有开关 - 避免拼写错误 - 便于重构和删除 ### 代码结构 **保持代码简洁**: ```javascript // ✅ 推荐:简洁的条件判断 const useNewAlgorithm = await SensorsWave.checkFeatureGate('new_algorithm'); const recommendations = useNewAlgorithm ? await getRecommendationsV2(userId) : await getRecommendationsV1(userId); ``` ```javascript // ❌ 不推荐:过于复杂的嵌套 const isEnabled = await SensorsWave.checkFeatureGate('new_algorithm'); if (isEnabled) { if (someOtherCondition) { // 多层嵌套 } } else { // ... } ``` **提取函数**: ```javascript // ✅ 推荐:提取函数,保持主流程清晰 async function getRecommendations(userId) { const useNewAlgorithm = await SensorsWave.checkFeatureGate('new_algorithm'); return useNewAlgorithm ? await getRecommendationsV2(userId) : await getRecommendationsV1(userId); } // 主流程 const recommendations = await getRecommendations(userId); displayRecommendations(recommendations); ``` ### 避免过度使用 **不要为每个小改动都创建开关**: ```javascript // ❌ 不推荐:过度使用 const buttonColor = await SensorsWave.checkFeatureGate('button_color_blue'); const fontSize = await SensorsWave.checkFeatureGate('font_size_14'); const padding = await SensorsWave.checkFeatureGate('padding_10'); ``` ```javascript // ✅ 推荐:为有意义的功能创建开关 const useNewTheme = await SensorsWave.checkFeatureGate('new_theme_2024'); if (useNewTheme) { applyNewTheme(); } else { applyLegacyTheme(); } ``` ## 测试策略 ### 单元测试 **测试两种情况**: ```javascript // 测试功能开启时的行为 test('should use new algorithm when gate is enabled', async () => { // Mock 功能开关返回 true jest.spyOn(SensorsWave, 'checkFeatureGate').mockResolvedValue(true); const recommendations = await getRecommendations('user_123'); expect(recommendations).toEqual(expectedV2Results); }); // 测试功能关闭时的行为 test('should use legacy algorithm when gate is disabled', async () => { // Mock 功能开关返回 false jest.spyOn(SensorsWave, 'checkFeatureGate').mockResolvedValue(false); const recommendations = await getRecommendations('user_123'); expect(recommendations).toEqual(expectedV1Results); }); ``` ### 集成测试 **测试完整流程**: ```javascript test('should complete checkout with new flow', async () => { // 启用新结账流程 await enableFeatureGate('new_checkout_flow'); // 执行结账流程 await goToCheckoutPage(); await fillShippingInfo(); await selectPaymentMethod(); await confirmOrder(); // 验证结果 expect(orderCreated).toBe(true); }); ``` ### 测试覆盖 确保功能开关相关的代码有足够的测试覆盖率: - 功能开启的场景 - 功能关闭的场景 - 降级场景(SDK 失败) - 边界情况 ## 性能优化 ### 缓存策略 **使用本地缓存**: ```javascript // SDK 默认会缓存配置,避免频繁请求 const isEnabled = await SensorsWave.checkFeatureGate('new_feature'); ``` ### 减少重复查询 **在调用方缓存查询结果**: ```javascript // ✅ 推荐:查询一次,多处使用 const isEnabled = await SensorsWave.checkFeatureGate('feature_1'); // 在后续逻辑中复用 isEnabled 变量 ``` ### 避免过多开关 **控制开关数量**: - 建议单个项目的功能开关数量 < 100 个 - 定期清理不再使用的开关 - 避免为每个小改动都创建开关 **合并相关开关**: ```javascript // ❌ 不推荐:过多细粒度的开关 const showButton = await SensorsWave.checkFeatureGate('show_button'); const showIcon = await SensorsWave.checkFeatureGate('show_icon'); const showText = await SensorsWave.checkFeatureGate('show_text'); // ✅ 推荐:合并为一个开关 const useNewUI = await SensorsWave.checkFeatureGate('new_ui_redesign'); if (useNewUI) { // 新 UI 包含所有变更 renderNewUI(); } ``` ## 团队协作 ### 文档规范 **为每个功能开关维护文档**: 1. **控制台描述**: ``` 新推荐算法(基于深度学习),预期提升点击率 15%。 用于灰度发布,验证稳定性和效果。 预计 2 周完成灰度,全量后删除此开关。 相关需求:PROJ-1234 负责人:张三 ``` 2. **代码注释**: ```javascript // 功能开关:新推荐算法 // 创建时间:2024-01-15 // 预计删除:2024-03-15 // 相关文档:https://wiki.example.com/recommendation-v2 const useNewAlgorithm = await SensorsWave.checkFeatureGate('recommendation_algorithm_v2'); ``` 3. **Wiki 文档**: - 功能说明 - 使用场景 - 配置说明 - 注意事项 ### 沟通机制 **发布前沟通**: - 在团队会议中同步灰度计划 - 通知相关团队(客服、运维、QA) - 准备应急预案 **发布中沟通**: - 每天同步灰度进展 - 及时通报发现的问题 - 调整计划时告知相关人员 **发布后总结**: - 记录关键数据和决策 - 总结经验教训 - 分享给团队成员 ### 权限管理 **明确责任分工**: - 开发者:创建和编辑功能开关 - QA:验证功能开关配置 - 运维:紧急情况下操作运维开关 - 管理员:审批和归档 **生产环境谨慎操作**: - 生产环境配置变更需要审批 - 关键功能开关需要双人确认 - 所有操作记录审计日志 ## Do's and Don'ts ### 推荐做法 **✅ 为所有新功能创建功能开关**: - 降低发布风险 - 实现渐进式灰度 **✅ 使用清晰描述性的命名**: - 便于理解和维护 - 避免混淆和错误 **✅ 在代码中指定默认值**: - 作为降级方案 - 确保 SDK 失败时仍能运行 **✅ 定期清理不再使用的开关**: - 保持代码整洁 - 降低维护成本 **✅ 监控关键指标**: - 及时发现问题 - 数据驱动决策 **✅ 记录文档**: - 便于团队协作 - 知识传承 ### 避免的做法 **❌ 不要跳过灰度直接全量**: - 问题影响范围不可控 - 失去快速验证的机会 **❌ 不要使用过于简单的命名**: - `flag1`, `test`, `temp` 等 - 难以理解和维护 **❌ 不要在循环中频繁调用**: ```javascript // ❌ 不推荐 for (const item of items) { const isEnabled = await SensorsWave.checkFeatureGate('feature'); // ... } // ✅ 推荐:在循环外查询一次 const isEnabled = await SensorsWave.checkFeatureGate('feature'); for (const item of items) { // 使用 isEnabled } ``` **❌ 不要累积过多无用的开关**: - 影响性能 - 增加维护成本 - 代码难以理解 **❌ 不要在生产环境直接测试**: - 先在开发/测试环境验证 - 确认配置正确再发布到生产 **❌ 不要忽视降级处理**: ```javascript // ❌ 不推荐:没有降级处理 const isEnabled = await SensorsWave.checkFeatureGate('new_feature'); // ✅ 推荐:checkFeatureGate 在无法获取配置时自动返回 false const isEnabled = await SensorsWave.checkFeatureGate('new_feature'); // 可直接使用返回值,SDK 已内置降级逻辑 ``` ## 实施建议 ### 第一次使用功能开关 **从简单场景开始**: 1. 选择一个低风险的功能 2. 创建功能开关并配置 3. 实施灰度发布 4. 总结经验 **逐步推广**: 1. 在团队内分享经验 2. 建立团队规范 3. 扩展到更多功能 4. 持续优化流程 ### 建立团队规范 **制定规范文档**: - 命名规范 - 使用流程 - 审批流程 - 清理策略 **工具和模板**: - 功能开关创建模板 - 灰度发布检查清单 - 监控看板模板 **培训和分享**: - 新成员培训 - 定期分享最佳实践 - 案例复盘 ### 持续改进 **收集反馈**: - 团队成员的使用体验 - 遇到的问题和困难 - 改进建议 **优化流程**: - 简化操作流程 - 改进工具和文档 - 自动化常见操作 **指标评估**: - 发布成功率 - 问题发现时间 - 回滚次数 - 团队满意度 ## 检查清单 ### 创建功能开关时 - [ ] 命名符合规范 - [ ] 描述清晰完整 - [ ] 设置合理的默认值 - [ ] 添加相关文档链接 ### 发布前 - [ ] 在测试环境验证 - [ ] 制定灰度计划 - [ ] 准备回滚方案 - [ ] 通知相关团队 ### 灰度过程中 - [ ] 每天检查监控指标 - [ ] 收集用户反馈 - [ ] 记录重要决策 - [ ] 按计划推进或回滚 ### 全量后 - [ ] 持续监控 1-2 周 - [ ] 确认各项指标稳定 - [ ] 计划清理功能开关 - [ ] 总结经验教训 ### 清理时 - [ ] 移除代码中的开关判断 - [ ] 删除旧代码 - [ ] 归档功能开关 - [ ] 更新相关文档 ## 下一步 现在您已经了解了功能开关的最佳实践,接下来可以: 1. **[常见问题](faq.mdx)**:查看常见问题的解答 2. **[快速开始](quick-start.mdx)**:创建您的第一个功能开关 --- **最后更新时间**:2026 年 1 月 28 日