博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
重构:仔细查看,改进代码
阅读量:5223 次
发布时间:2019-06-14

本文共 2983 字,大约阅读时间需要 9 分钟。

我建议你进行一个练习:当你第二天早晨开始工作的时候,重新审视你的项目源码,尝试发现进行的机会。就算你的领导没有要求,仍然去做。因为在工作中,你希望有一些激动人心的时候。

重构是一门改变已经正常的工作的艺术。但是重构是需要理由的。可能是设计改进,性能问题,安全角色或者很多其他的原因。改进程序的技术缺点是要冒风险的,尽管能够使其更稳定,并且可能能够提高你自己今后的生产力。

这不是为了公司或者领导好,而是为了自己。为什么?因为问题都是逐渐累积的,到达一个程度之后,你会失去对代码的控制。你将会面对苦于交付结果的境地,最终可能毁掉你的职业生涯。

好吧,让我们从一个更加积极的角度来看这个问题。在重构过程中你会学习到很多,并且很快意识到你产出了比之前更好的代码。重构越多,你就越聪明,慢慢累积直到你达到创新的级别。但是这意味着什么,你又如何知道你达到了呢?

当你发现一个明显的机会来对你当前的工作进行改进,并且你意识到至今为止还没有别人做过这样的事情(至少你找不到)。这不容易,这不容易,但这常发生在你不断重复做一件事情,并且你能够发现你如何能够使得同样的事情做得又快又好。让我用一个真实的故事来说明。

例子是在Java中进行字符串连接:一个经典问题,曾经在过去数年困扰了大量专家,但在今天可能已经被忽略了。在JDK1.5之前,尽管可读性高而且简单,但使用“+”来进行字符串连接可能产生效率极低的代码。之后,“+”操作符被换成了StringBuffer,从而真正改进了连接。使用“+”越多,则在内存中的String和StringBuffer实例越多,为了管理所有的对象花费的时间也越多。因此,开发者们被推动使用StringBuffer而忽略“+”。看下面的例子:

1
2
3
4
5
6
7
8
9
String title =
"Mr."
;
  
String name =
"John"
;
  
String familyName =
"Smith"
;
  
String message =
"Dear "
+ title +
" "
+
  
                 
name +
" "
+ familyName +
","
;

开发者习惯于这样写代码,但是现在被推动这么做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
StringBuffer sb =
new
StringBuffer();
  
sb.append(
"Dear "
);
  
sb.append(title);
  
sb.append(
" "
);
  
sb.append(name);
  
sb.append(
" "
);
  
sb.append(familyName);
  
sb.append(
","
);

你可能同意第一个例子可读性高于第二个。开发者使用“+”进行字符串连接时很自然的,所以丢弃这样的形式不合适。好消息是,编译人员做了一些事情来维护这样的习惯,确保了JDK1.5会优化连接方法。代替线程安全的StringBuffer,他们建立了一个叫做StringBuilder(非线程安全,但更快)的类,并且他们确保能够像第一个例子中那样,使用一个实例就能处理所有的连接。这是一个很重要的进步,因为他们兼顾了简洁而不单纯是技术性。第一个例子在编译时会自动转换成如下情况:

1
2
3
4
5
6
7
StringBuilder sb =
new
StringBuilder();
  
sb.append(
"Dear "
).append(title).append(
" "
)
  
  
.append(name).append(
" "
).append(familyName)
  
  
.append(
","
);

但是,在一些复杂逻辑代码中的字符串连接还是需要使用StringBuilder,因为编译器还没有那么智能,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<Student> students = studentBean.findStudents();
String intro =
"The following students were approved:\n"
;
String listedNames =
""
;
String separator =
""
;
for
(Student student: students) {
  
if
(student.approved()) {
    
if
(!listedNames.isEmpty()) {
      
separator =
", "
;
    
}
    
listedNames += separator + student.getName();
  
}
}
String msg = intro + listedNames;
messengerBean.sendMessage(msg);

如下写法会更有效率:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
List<Student> students = studentBean.findStudents();
String intro =
"The following students were approved:\n"
;
StringBuilder listedNames =
new
StringBuilder();
String separator =
""
;
for
(Student student: students) {
  
if
(student.approved()) {
    
if
(!listedNames.length() >
0
) {
      
separator =
", "
;
    
}
    
listedNames.append(separator)
               
.append(student.getName());
  
}
}
String msg = intro + listedNames.toString();
messengerBean.sendMessage(msg);

呃!你注意到有什么奇怪的东西了么?可能一眼看起来不是很明显,但是看看他们是如何在定义分隔符之前检查listedNames是否为空的。String类在JDK1.6中有一个可读性很好的方法isEmpty(),但是StringBuilder仍然使用相对比较老的方式。为什么他们不将StringBuilder 和 StringBuffer改为同样的方式呢?

在核心库开发的邮件列表中讨论了这个问题,没有发现什么明显原因导致他们之前没有这么做。可能只是忘记了。要感谢大规模的重构,试图改进效率低下的字符串连接方法,才能发现这样的不一致。我相信在明年推出的Java8中会有时间修复这个问题。只要在接口CharSequence加入isEmpty()方法,这样就能使得所有实现都变得同样优雅。

这可能是一件简单的事情,但是Java是一个严格审查下的复杂的语言,所以每个细节都会带来很大的影响。所以,做一些重构,发现一些改进代码的机会,同样也能够改进你使用的编程语言。让我们一起推动Java进步吧!

 

转载于:https://www.cnblogs.com/wala-wo/p/5119319.html

你可能感兴趣的文章
Apache Common-IO 使用
查看>>
Java-第一课正则表达式
查看>>
深入剖析,什么是eval的直接调用.
查看>>
apidoc
查看>>
3月14日-15日学习总结
查看>>
关于 ++x 和 x++ 比较难的一个例子
查看>>
第三次作业 105032014021
查看>>
记录一些容易忘记的属性 -- UILabel
查看>>
android新手关于左右滑动的问题,布局把<android.support.v4.view.ViewPager/><ImageView/> 放在上面就不行了。...
查看>>
人脸识别FaceNet+TensorFlow
查看>>
STL之map UVa156
查看>>
从Angular.JS菜鸟到专家
查看>>
再谈Vmware NAT的配置和路由流程
查看>>
javaScript数组去重方法汇总
查看>>
评价意见整合
查看>>
MySQL表的四种分区类型
查看>>
C++变量的“总分性”(Mereology)
查看>>
应用软件学习心得之mapgis功能学习
查看>>
二、create-react-app自定义配置
查看>>
Android PullToRefreshExpandableListView的点击事件
查看>>