一个软件总是为解决某种特定的需求而产生,时代在发展,客户的业务也在发生变化。有的需求相对稳定一些,有的需求变化的比较剧烈,还有的需求已经消失了,或者转化成了别的需求。在这种情况下,软件必须相应的改变。

考虑到成本和时间等因素,当然不是所有的需求变化都要在软件系统中实现。但是总的说来,软件要适应需求的变化,以保持自己的生命力。

这就产生了一种糟糕的现象:软件产品最初制造出来,是经过精心的设计,具有良好架构的。但是随着时间的发展、需求的变化,必须不断的修改原有的功能、追加新的功能,还免不了有一些缺陷需要修改。为了实现变更,不可避免的要违反最初的设计构架。经过一段时间以后,软件的架构就千疮百孔了。bug越来越多,越来越难维护,新的需求越来越难实现,软件的架构对新的需求渐渐的失去支持能力,而是成为一种制约。最后新需求的开发成本会超过开发一个新的软件的成本,这就是这个软件系统的生命走到尽头的时候。

重构就能够最大限度的避免这样一种现象。系统发展到一定阶段后,使用重构的方式,不改变系统的外部功能,只对内部的结构进行重新的整理。通过重构,不断的调整系统的结构,使系统对于需求的变更始终具有较强的适应能力。

重构可以降低项目的耦合度,使项目更加模块化,有利于项目的开发效率和后期的维护。让项目主框架突出鲜明,给人一种思路清晰,一目了然的感觉,其实重构是对框架的一种维护。

那么说到重构,可能我们普遍认为就是改改框架、使用一些最新流行的框架或者技术等等,我们到底要从哪些方面来对项目进行重构呢?下面我们进入主题:控制圈复杂度的9种重构技术

提炼函数

例子:如果某段代码可以被组织在一起并独立出来

void printOwing(double previousAmount)

{

Enumeration e = _orders.elements();

double outstanding = previousAmount * 1.2;

// 打印大标题

System.out.println ("**************************");

System.out.println ("***** Customer Owes ******");

System.out.println ("**************************");

// 计算未完成的订单数量

while (e.hasMoreElements())

{

Order each = (Order) e.nextElement();

outstanding += each.getAmount();

}

//打印明细

System.out.println ("name:" + _name);

System.out.println ("amount" + outstanding);

}

将这段代码放进一个独立函数中,并让函数名称解释该函数的用途

void printOwing(double previousAmount)

{

printBanner();

double outstanding = getOutstanding(previousAmount * 1.2);

printDetails(outstanding);

}

void printBanner() //打印大标题

{

System.out.println ("**************************");

System.out.println ("***** Customer Owes ******");

System.out.println ("**************************");

}

// 计算未完成的订单数量

double getOutstanding(double initialValue)

{

double result = initialValue;

Enumeration e = _orders.elements();

while (e.hasMoreElements())

{

Order each = (Order) e.nextElement();

result += each.getAmount();

}

return result;

}

void printDetails (double outstanding) //打印明细

{

System.out.println ("name:" + _name);

System.out.println ("amount" + outstanding);

}

Substitute Algorithm(替换你的算法)

例子:

把当前算法重构成更清晰的算法

String foundPerson(String[] people)

{

for (int i = 0; i < people.length; i++)

{

if (people[i].equals ("Don"))

return "Don";

if (people[i].equals ("John"))

return "John";

if (people[i].equals ("Kent"))

return "Kent";

}

return "";

}

重构成更清晰的算法

String foundPerson(String[] people)

{

List candidates = Arrays.asList(new

String[]{"Don", "John","Kent"});

for (int i=0; i

if (candidates.contains(people[i]))

return people[i];

return "";

}

Decompose Conditional(分解条件式)

例子:你有一个复杂的条件语句

if (date.before (SUMMER_START) || date.after(SUMMER_END))

charge = quantity * _winterRate + _winterServiceCharge;

else

charge = quantity * _summerRate;

从if、then、else三个段落中分别提炼出独立函数

if (notSummer(date))

charge = winterCharge(quantity);

else

charge = summerCharge (quantity);

Consolidate Conditional Expression(合并条件式)

例子:你有一系列条件判断,都得到相同结果

double disabilityAmount()

{

if (_seniority < 2) return 0;

if (_monthsDisabled > 12) return 0;

if (_isPartTime) return 0;

// compute the disability amount

将这些判断合并为一个条件式,并将这个条件式提炼成为一个独立函数,函数名自注释

double disabilityAmount()

{

if (isNotEligableForDisability()) return 0;

// compute the disability amount

Consolidate Duplicate Conditional Fragments(合并重复的条件片断)

例子:在条件式的每个分支上有着相同的一段代码。

if (isSpecialDeal())

{

total = price * 0.95;

send();

}

else

{

total = price * 0.98;

send();

}

将这段重复代码搬移到条件式之外,避免用拷贝粘贴的方式写重复代码

if (isSpecialDeal())

total = price * 0.95;

else

total = price * 0.98;

send();

Remove Control Flag(移除控制标记)

例子:当前代码使用标记变量,可读性差,容易出错

void checkSecurity(String[] people) {

boolean found = false;

for (int i = 0; i < people.length; i++) {

if (! found) {

if (people[i].equals ("Don")){

sendAlert();

found = true;

}

if (people[i].equals ("John")){

sendAlert();

found = true;

}

}

}

}

以break和return取代标记变量

void checkSecurity(String[] people) {

for (int i = 0; i < people.length; i++) {

if (people[i].equals ("Don")){

sendAlert();

break;

}

if (people[i].equals ("John")){

sendAlert();

break;

}

}

}

Separate Query from Modifier(将查询函数和修改函数分离)

例子:某个函数既返回对象状态值,又修改对象状态,建立两个不同的函数,其中一个负责查询,另一个负责修改

Parameterize Method(令函数携带参数)

例子:若干函数做了类似的工作,但在函数本体中却

包含了不同的值

Dollars baseCharge()

{

double result = Math.min(lastUsage(),100) * 0.03;

if (lastUsage() > 100) {

result += (Math.min (lastUsage(),200) - 100) * 0.05;

};

if (lastUsage() > 200) {

result += (lastUsage() - 200) * 0.07;

};

return new Dollars (result);

}

建立单一函数,以参数表达那些不同的值

Dollars baseCharge()

{

double result = usageInRange(0, 100) * 0.03;

result += usageInRange (100,200) * 0.05;

result += usageInRange (200, Integer.MAX_VALUE) * 0.07;

return new Dollars (result);

}

int usageInRange(int start, int end)

{

if (lastUsage() > start)

return Math.min(lastUsage(),end) -start;

else

return 0;

}

java 圈复杂度_控制圈复杂度的9种重构技术相关推荐

  1. java 最大圈复杂度_控制圈复杂度的9种重构技术总结

    可以直接降低圈复杂度的9种重构技术(针对结构化编程): Composing Methods(重新组织你的函数) 1.Extract Method(提炼函数) 分为不同的step步骤进行处理,主干逻辑方 ...

  2. 向量点积衡量相似度_点积相似度、余弦相似度、欧几里得相似度

    看starspace的时候发现它实现了dot和cos两种similarity的度量方式,这里总结一下: 余弦相似度衡量两个向量在方向上的相似性,而不care两个向量的实际长度,A和B的长度即使是一个超 ...

  3. 猿圈 题库_猿圈AI考试题库 智慧在线考试宝典

    原标题:猿圈AI考试题库 智慧在线考试宝典 网络编辑工具箱,一键排版格式化网编工具,网络编辑转帖工具.最终版,不再更新! 猿圈 AI 考试题库 智慧在线考试宝典 作为HR的你 有没有因为不知道某个岗位 ...

  4. 刷圈兔下载_刷圈兔app

    <刷圈兔app>软件使用各种你需要的功能排版清楚明了,支持对三大生活中最常用的手机软件的截图等图片操作,使用刷圈兔app用户可以自定义对话生成,拥有最真实自然的效果,录制的视频有不满意的地 ...

  5. 猿圈 题库_猿圈帮企业“测评”程序员

    猿圈帮企业"测评"程序员 本刊记者 张配豪 [摘 要] "金九银十"招聘季,正是各大企业 HR 最忙碌的时候.在招聘圈, 技术人才尤其是高级编程人才招聘是最令 ...

  6. 刷圈兔下载_刷圈兔最新版

    刷圈兔最新版下载是一款十分好用的图片处理生成制作的应用,用户们可能会经常的看到一些搞笑的或是非常夸张的聊天对话截图的内容,如果你也想尝试制作截图的话,这款应用就是非常不错的选择哦.可以来下载试试. 刷 ...

  7. java消息幂等性实现_探讨一下实现幂等性的几种方式

    什么是幂等性? 对于同一笔业务操作,不管调用多少次,得到的结果都是一样的. 幂等性设计 我们以对接支付宝充值为例,来分析支付回调接口如何设计? 如果我们系统中对接过支付宝充值功能的,我们需要给支付宝提 ...

  8. java各种的不好_译文《最常见的10种Java异常问题》

    封面:洛小汐 译者:潘潘 知彼知己,方能百战不殆. 前言 本文总结了有关Java异常的十大常见问题. 目录 检查型异常(checked) vs. 非检查型异常(Unchecked) 异常管理的最佳实践 ...

  9. 结巴分词关键词相似度_中文文本相似度计算工具集

    [磐创AI导读]:前两篇文章中我们介绍了一些机器学习不错的项目合集和深度学习入门资源合集,本篇文章将对中文文本相似度计算工具做一次汇总.喜欢我们文章的小伙伴,欢迎大家点击上方蓝字关注我们的公众号:磐创 ...

最新文章

  1. .NET 面试题总结 (附有参考答案) 第2部分
  2. python用matplotlib画人口图_Python+Matplotlib画contour图
  3. lower_bound()、upper_bound()
  4. Ubuntu 20.04 搜索引擎环境搭建 (PostgreSQL 12.3, Redis 6, ELK[Elasticsearch 7.8, Logstash 7.8, Kibana 7.8])
  5. LiveVideoStack Meet成都 生活与技术的“矛盾体”(内附资料下载)
  6. D - 邂逅明下 HDU - 2897(有点水平的巴什博奕)
  7. repeated_Ruby中带有示例的Array.repeated_combination()方法
  8. 112_Power Pivot 销售订单按 sku 订单类型特殊分类及占比相关
  9. android spi读写不通,Android-SPI学习笔记
  10. ORACLE数据库表空间查询
  11. 叔丁基氢醌(TBHQ)行业调研报告 - 市场现状分析与发展前景预测
  12. 拼多多公布新iPhone SE补贴后价格:2899元起;BOSS直聘回应“App崩了”;Chrome 新测试版发布|极客头条...
  13. [转载] Pytorch基础介绍
  14. c 语言基础笔试题1
  15. ESP32核心原理图
  16. html5如何引用百度地图api,WebApp如何调用百度地图API
  17. 16条时间管理法则 让你快速提高效率
  18. 生死看淡,不服就GAN——GAN的种类
  19. 人工智能编程语言介绍
  20. MySQL保存特殊字符及表情符

热门文章

  1. 生活不止眼前的代码,还有书和远方!
  2. 有哪些国内最好的危机公关公司分享。
  3. 中国惠普前总裁孙振耀谈人生 [珍藏]
  4. 内网通过nginx代理发送邮件
  5. 缅怀那些正渐行渐远的编程语言
  6. CES Asia直击:小度车载OS为汽车开启新进化
  7. VMware Workstation 9上安装MAC OS X Lion 10.8图解
  8. 面试题目: 一副从1到n的牌,每次从牌堆顶取一张放桌子上,再取一张放牌堆底,直到手中没牌。根据桌上的牌堆顺序,输出原先手中牌堆的顺序数组。
  9. 原生html中modal,基于原生JS封装的Modal对话框插件
  10. Headless Services