在前几期的InfoQ专栏中刊登了一篇名为“使用功能开关更好地实现持续部署”的文章,文中讲解了 特性开关与Spring的集成应用。但如果项目没有依赖Spring,又该如何更好地使用特性开关呢?同时, 又该如何透明地引入,使得项目不至于完全依赖特性开关呢?
接下来我将结合我们在项目中实 际运用特性开关的经验,从另一个角度为大家介绍如何使用特性开关透明地实现功能屏蔽。
问 题
我们的团队正在开发一款在线保险产品,该产品下包括若干品牌,每个品牌有不同的目标用 户群,但提供的服务基本相同。当第一个品牌正式上线后,我们就面临一个很大挑战——既要修正上线 后发现的Bug,又要继续为其它品牌添加新特性,且这些特性暂时不能反映到已上线的品牌中。我们并 不愿意为这种多品牌开发的业务创建分支版本,因为它对于版本维护而言,无疑是一场灾难。因而,我 们决定选择特性开关来解决这个问题。
若要快速地解决这一问题,我们当然可以选择 if… else… 这种简单的特性开关模型;然而,随之却会引入其它问题:
条件式特型开关会对现有的业务结构产生影响
清晰的业务逻辑,简单的代码结构是保证项目可维护性的基础。如果特性开关的添加使业务逻辑变 得复杂而不易理解,那么特性开关就在一定程度上破坏了项目的可维护性。
添加特性开关前的代码如下:
inputVehicleDetails(); createQuote(); inputPersonalDetails(); buyInsurance();
添加特性开关后:
inputVehicleDetails(); if (brandA.isActive()) { // 条件式特性开关 createQuote(); } inputPersonalDetails(); buyInsurance();
可以看到,简单的条件分支虽然实现了特性开关——部分代码只有在满足条件时才会执行,但却破 坏了原有清晰的业务结构??
当前程序中如果已存在了某些类似特性开关的判断,条件式特性开关会造成逻辑混淆
添加特性开关前:
inputVehicleDetails(); createQuote(); if (currentBrand == brandB) { // 原有依赖于品牌的条件判断 inputPersonalDetails(); } buyInsurance();
添加特性开关后:
inputVehicleDetails(); if (brandA.isActive()) { // 特性开关 createQuote(); } if (currentBrand == brandB) { // 原有依赖于品牌的条件判断 inputPersonalDetails(); } buyInsurance();
可以看到,新加入的条件式特性开关 brandA.isActive() 与原有业务判定逻辑 currentBrand == brashA 十分相似,很难区分,在使用过程中更是特别容易混淆。更糟的是,随着项目的不断深入,越 来越多的条件式特性开关会被放置在代码中,代码中会充满“坏味道 “,使得混淆的情况进一步恶化 !
条件式特性开关并不具有可扩展性
条件式特性开关通常只是简单的条件判断,并不具有可扩展性。添加第一个条件判断与添加第十个 需要写同样多的代码,并且随着判断逻辑的增多,会令添加代码所用的时间和维护成本持续增加。
例如:
if (brandA.isActive()) { // 特性开关 inputVehicleDetails(); } if (brandB.isActive()) { // 特性开关 createQuote(); } if (brandC.isActive()) { // 特性开关 inputPersonalDetails(); } if (brandD.isActive()) { // 特性开关 buyInsurance(); }
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索代码混淆
, 上线项目
, 逻辑题
, 代码
, 项目
, 开关
, 特性
, 品牌
多条件判断
高压开关特性测试仪、高压开关动特性测试仪、开关特性测试仪、三极管的开关特性、开关特性,以便于您获取更多的相关知识。