系统存在过多开关的思考

一个系统通过配置文件或者数据库设置几个到几十个开关通常是没有问题,但是如果这个系统拥有上千个开关并且他们之间可能相互依赖,那对于开发、测试人员来说绝对是一个灾难。这样的灾难恰好出现在我之前维护的系统里面,代码大约有700万行代码,代码里面配置了几千个开关!系统很小的时候,能够应付得过去,这样做没有问题。当客户变多的时候,她们向需求人员提出了越来越多定制化要求,通常这些变化是无法拒绝的。况且这对公司也是有好处的,毕竟每一个变化是要算算钱的;另外通过不同需求可以攒出一个产品系统功能更加丰富,销售可以向客户表达我们的系统可以顶你们10个子系统。

实际上我们的系统在面向不同客户是想了一些办法的,比如不同的客户通过oracle数据库里面配置不同schema,不同的schema里面表结构相同,库表里面有一个开关配置表,用户在里面定义不同的开关,一套程序读取不同的开关。为了便于升级维护,代码是一套代码,可怜的程序员加上一个又一个if...else...代码。这样做会造成如下问题:

  • 假定客户A需要开关1打开,客户B开关1默认关闭,开发、测试人员需要考虑两种情况。系统升级后,客户B则被强制升级。万一没有详尽的测试出现bug,客户B无辜受到影响。
  • 不同开关之间有相互叠加,测试数量呈现指数级增加。对开发人员也是一场噩梦,代码复杂程度大大增加。
  • 增大了测试成本,因为不同开关组合的情况在实际使用中并不存在,但是为了保证完备性,测试人员需要测试实际上并不使用场景,万一哪天要使用某个条件组合呢。
  • 增加新客户的时候,运维人员需要大量配置不同开关。谁知道这么多开关代表什么含义?这么多开关组合在一起谁能保证他们能够完全正常工作?所以上线前,测试又需要再测试一遍。
  • 代码耦合度高

所以加一个看似简单的需求,实际开发测试量非常巨大,系统到后来越来越难以维护。

从技术层面思考如下:

  1. 代码层面的相互隔离,这样即便客户A出现了问题,问题也将局限在客户A这个层面。
  2. 去掉if...else...代码,将开关抽象出来用策略模式代替。

代码层面如何相互隔离比较有意思,实际要求不同客户绑定不同的服务实例。

一个简单想法是不同的客户部署不同版本的代码,但这样势必增加不同版本的代码维护量,并且数据库库表结构不同。如果某个开关只有客户A使用,我们完全可以给他单独部署一个。

不同的开关加载对应的实现类,把创建开关的权利交给容器,这其实与spring的思想不谋而合。当实际也是很复杂的事情,在某些情况下甚至不可能。但不管怎样,在系统变得越来越复杂的情况下,我们应该抛弃if...else...的写法。

原文地址:https://www.cnblogs.com/pmh905001/p/12325720.html

时间: 2024-11-05 16:27:03

系统存在过多开关的思考的相关文章

关于后台系统自动生成的一点思考

大量实践发现后台管理程序,其实90%的代码都是相同的,当然是在抛弃复杂逻辑业务的情况下,那么如何能高效的节约这些时间呢,那就是接下来我要说的,对于后台系统自动生成的一些思考. 适用情景: 1.表编号id为自增(基于现在大部分表编号都是自增的情况): 2.没有太复杂业务关联关系,比如表的某一个字段,存储了一个json对象,为了平衡后台用户使用,需要友好的分段展示给用户的定制ui界面:还比如表中存储了外键的多个id,但为了方便用户使用,只能已标签name的方式,给用户展示,等等这些超强业务黏合逻辑的

小米3系统计算器自定义开关控件-MySwitchView

1.前言 在android4.0以后,有switch控件,类似于iPhone上面滑块的效果,但是只能用在4.0以后的系统中,之前的平台,就无法使用这种控件.近段时间,看到了小米3手机上自带的计算器app,有这样的效果,上面的一个控件,觉得很漂亮,并且与iPhone上的效果略有不同,于是自己动手编写了一下这个功能,在编写的过程中,参考过网上的一些demo,运行后,在控件滑动的时候,感觉动画不平滑,有卡顿的现象,反复修改,最后还是有一些问题,感觉是在滑动中的状态,没有合理的控制好.无奈只能参考Goo

关于Linux系统basename函数缺陷的思考

某模块作为前台进程独立运行时,运行命令携带命令行参数:作为某平台下守护进程子进程运行时,需要将命令行参数固化在代码里.类似如下写法: char *argv[] = {"./DslDriver", "-t", "/bin/VdslModemSco.bin"}; int argc = sizeof(argv) / sizeof(argv[0]); 随后,调用basename函数(头文件为libgen.h)解析argv[0],即"./DslD

地铁事件对系统稳定性、可用性的思考

昨天晚高峰发生在北京地铁上的一件事情让我心里一直很难受,一个年轻的生命在地铁的两个自动门之间被夹身亡.姑且不论受害者的家属是什么样的一个心情,作为一个普通人,都会觉得非常的惋惜和愤恨.为什么地铁门不止一次的夺走了一条又一条的生命?不要以为这是一个"低概率事件"而默认事情的合理性.如果我们尊重人的生命,那么即使再低的概率也是付出了极高的代价,这种事情就不应该发生. 地铁夹人夺走生命的事情已经发生多次,此次在北京发生的事情早在2007年在上海就发生过,同样是被夹在屏蔽门和列车之间.在上海发

系统问题解决的后的思考,处理问题的思路(oracle关不掉,起不来)

前言 应用支持A,接到业务部门反映公司的老总生产看板数据显示不了,联系开发组B,说是程序最近没有改动过,问题肯定在数据库让我检查数据库 查看报错ora-12541,检查数据库的监听,1521端口,均正常,线上的生产系统(与生产看板用的是同一个数据库),plsql都是正常.反应给开发组B,B说是程序没有改动,问题肯定在数据库. 因为不了解的生产看板的的数据架构,向B要应用连接数据库的配置参数,一直没给我 因为是公司总经理的事情,领导比较关注,应用支持A就一直说是数据库的问题,让重启数据库先 我一直

系统过载及保护的思考

家用电器为了防止电流过大,都会有保险装置,当电流过大时,自动切断电流,防止电器损坏, 防洪大坝的水位超过了警戒线,会开闸泄洪,防止大坝崩溃. 而我们的服务系统如果一旦流量过大(用户或请求超过其处理能力),很多情况下,都把自己搞挂了,很显然,我们设计系统时没有像我们的工业及建筑领域那样成熟的引入自我保护机制.稍不注意就把自己搞挂了. 一个系统的处理能力是有限的,就如一个车站在车次一定的情况下(车辆一定,运力一定),每天可以输送2万名乘客, 如果逢年过节,赶上春运,一天来了25000名乘客,怎么办,

日志系统:字段类型的思考——String(字符串)、datetime(日期时间)、ip、int(整数)、float(小数)

日志本身用来记录事件,因此日志的内容应该包含: 事件发生的日期和时间: 精确度:毫秒(Java中最常用的时间单位).微秒数(PHP等其它语言中常用的时间单位).纳秒: 类型:datetime.double.long... 事件主体 类型:String 事件客体 类型:String 事件描述 类型:String 事件类型 类型:int.String... 事件级别: 类型:int.String 日志数据源的IP地址或名称: 类型:ip.String 汇总一下:int.long.double.Str

这里给大家整理了一些Linux系统运维相关的面试题,有些问题没有标准答案,希望要去参加Linux运维面试的朋友,可以先思考下这些问题

这里给大家整理了一些Linux系统运维相关的面试题,有些问题没有标准答案,希望要去参加Linux运维面试的朋友,可以先思考下这些问题. 一.Linux操作系统知识 1.常见的Linux发行版本都有什么?你最擅长哪一个?它的官网网站是什么?说明你擅长哪一块? 2.Linux开机启动流程详细步骤是什么?系统安装完,忘记密码如何破解? 3.企业中Linux服务器系统分区标准是什么?(以硬盘为300G,内存16G为例) 4.某一天突然发现Linux系统文件只读,该怎么办呢?完整操作步骤. 5.安装一台系

【游戏设计模式】之二 实现撤消重做、回放系统的神器:命令模式

本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://blog.csdn.net/poem_qianmo/article/details/52663057 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 这篇文章将与大家一起探索游戏开发中命令模式的用法. 命令模式的成名应用是实现诸如撤消,重做,回放,时间倒流之类的功能.如果你想知道<Dota2>中的观战系统.<魔兽争霸3>中的录像系统.<守望先锋>