降低代码复杂度的一种方法

代码之所以复杂,有以下两种原因:

一是耦合度高。如果一个代码单元是由多个小的代码单元耦合而成,那么它的复杂度就是其中各个小代码单元的复杂度的总和;二是使用了非常长的链式(连续的)if-then-elase语句或者switch语句,代码单元包含很多个分支。

降低代码的复杂度,要根据代码复杂的原因采取相应的方法。对于第一种情况,由于代码单元中含有了许多几乎互不相关的代码块,这时候就适合采用“提取方法”的技巧来进行重构,以降低复杂度。

对于第二种情况,代码单元有太多的分支,而一般能够接受的分支数量是不多于4个。下面以一个会返回正确的国旗颜色的GetFlagColors方法重构为例来演示下降低其复杂度的方法。

public IList<Color> GetFlagColors(Nationality nationality)
{
List<Color> result;
switch (nationality)
{
case Nationality,DUTCH:
result = new List<Color> { Color.Red, Color.White, Color.Blue}; break;
case Nationality.GERMAN:
result = new List<Color> { Color.Black, Color.Red, Color.Yellow};
break;
case Nationality.BELGIAN:
result = new List<Color> {Color.Black, Color.Yellow, Color.Red };
break;
case Nationality.FRENCH:
result = new List<Color> {Color. Blue, Color.White, Color.Red};
break;
case Nationality.ITALIAN:
result = new List<Color> { Color.Green, Color.White, Color.Red };
break;
case Nationality,UNCLASSIFIED:
default:
result = new List<Color> { Color,Gray };
break;
}
return result;
}

方法体中的switch语句需要处理所有的国家枚举类型,并返回每个国家对应的正确国旗颜色。这个方法中需要测试的分支为6。

要减少这个方法的分支数量,可以使用“使用多态来代替条件判断”的重构技巧,让每个国旗都拥有一个自己的类型,并实现同一个接口。

为此,我们首先定义一个公用的Flag接口:

public interface IFlag
{
IList<Color> Colors
{
get;
}
}

然后再为不同的国家定义不同的国旗类型,例如荷兰:

public class DutchFlag: IFlag
{
public IList<Color> Colors
{
get
{
return new List<Color { Color.Red, Color.White, Color.Blue };
}
}
}

最终重构后代码如下:

private static readonly Dictionary<Nationality, IFlag>FLAGS = new Dictionary<Nationality, IFlag>();

static FlagFactory()
{
FLAGS[Nationality.DUTCH]= new DutchFlag();
FLAGS[Nationality.GERMAN] = new GermanFlag();
FLAGS[Nationality.BELGIAN] = new BelgianFlag();
FLAGS [Nationality.FRENCH]= new FrenchFlag();
FLAGS[Nationality.ITALIAN] = new ItalianFlag();
}

public IList<Color> GetFlagColors(Nationality nationality)
{
IFlag flag = FLAGS[nationality];
flag = flag ?? new DefaultFlag();
return flag.Colors;
}

这种重构技巧去掉了switch语句,极大地降低了代码的复杂度,而且可以根据需要不断增加所支持的国旗种类。不过,这种方式的不好之处是引入了更多的类和代码。

这正是:

若要降低复杂度,复杂原因搞清楚

提取方法去耦合,减少分支用类库

参考书目:代码不朽:编写可维护软件的十大要则,作者:(荷兰)约斯特·维瑟,译者:张若飞,出版社:电子工业出版社

(0)

相关推荐

  • 复杂度分析和大O表示法

    学习数据结构和算法要从复杂度分析说起.表示时间的大O符号,是用来描述算法效率的语言和度量单位.算法复杂度包括时间复杂度和空间复杂度,两者中又以时间复杂度相对重要,因为就 Web 应用而言,我们常见的性 ...

  • Go 数据结构和算法篇(四):冒泡排序

    Go语言中文网 今天 以下文章来源于xueyuanjun ,作者xueyuanjun 今天给大家介绍的是基于选择的排序算法,常见基于选择的排序算法有冒泡排序.插入排序.选择排序.归并排序和快速排序,我 ...

  • 如何优化【if else】的面条代码,我们一起来解决代码复杂度问题!

    相信不少同学在维护老项目时,都遇到过在深深的 if else 之间纠缠的业务逻辑.面对这样的一团乱麻,简单粗暴地继续增量修改常常只会让复杂度越来越高,可读性越来越差,有没有固定的套路来梳理它呢?这里分 ...

  • 表驱动法在串行通讯协议解析中的应用

      在<单片机高级裸编程思想>和<代码大全2>中,均提到了数据驱动程序的编程思想,认为数据是宇宙的语言.虽然我们可以通过代码逻辑实现任务需求,但容易出现代码分支众多,程序难以理 ...

  • 提高员工敬业度的11种方法

    组织必须对自己的业务计划以及在疫情爆发期间的工作方式进行大量调整.他们比以往任何时候都更加需要敬业的员工来度过这个充满挑战的时期,他们需要为马拉松而不是短跑做准备,这种全球性流行病不可能在一夜之间消失 ...

  • 降低员工流失率的21种方法

    尽管进行了数百年的创新,但对于当今的组织而言,不必要的员工流动仍然是一个大问题,我们写出21种简单的方法来帮助你降低员工流失率. 01 不要让员工无聊 即使你的员工疯狂地爱上了他们的工作,但在职业生涯 ...

  • L&D提高员工敬业度的5种方法?

    员工敬业度从未像现在这样至关重要,缺乏员工敬业度会导致人员流失,生产力低下和组织发展停滞等灾难性后果.尽管解决方案的一部分位于L&D之内,但吸引员工是一个复杂且通常是战略性的过程,需要随着技术 ...

  • 提高筋度的五种方法

        要想提高面粉的筋度,除了用高筋面粉外,还可采用以下5种方法:     充分饧面和面之后,让面团充分静置,这样可以给面团内的面筋蛋白充足的时间形成面筋网络.     加鸡蛋鸡蛋中含有大量含有巯基 ...

  • 施工中降低钢筋损耗率的12种方法

    钢筋是建筑业用量较大.价值较高的一种原材料,能否合理利用以降低损耗率,已经成为项目是否盈利的关键点,量化管理是成本控制的关键. 一.钢筋选择进料法 采购钢筋时,针对下料单组合排列及工地实际情况,必须对 ...

  • 提高肉类嫩度的4种方法

    多聚磷酸盐嫩化法 多聚磷酸盐包括焦磷酸.偏磷酸和三聚磷酸盐.1950年开始应用于肉食品 加工中,嫩化方法是将多聚磷酸盐配成腌制液用于腌制或注入肉中,然后进行滚揉.一般添加量为0.125%-0.375% ...

  • 修改 cmd 控制台默认代码页编码的几种方法【GBK、UTF

    在程序开发中我们统一的编码是 UTF-8,这一点很重要,但是总还是会遇到许多乱码问题,乱码的原因是多方面的,但归根结底就是编码与解密标准不一致,这里暂不过多总结.这里只说明在 window 下使用控制 ...

  • 降低企业内部成本的五种方法

    成本是衡量企业管理水平的关键元素,成本的能力也是实现企业经营绩效的基础.但是,企业不应追求最低成本,成本只能是合理. 为什么不能有最低成本?有三个原因: 1.成本决定品质.对品质产生直接影响的是成本, ...

  • Notepad 去除代码行号的几种方法

    问:在网页中复制代码时,常常遇到高亮程序自动给代码加上行号或字符"#",如何格式化?如下: # 1 //去除首字符或行号 # 2 <?php # 100 echo '再长点' ...