初识重构
2017年的时候,领导让我看公司的一本书《重构——改善代码的既有设计》,这是一本JAVA版本的,前后看了2遍。那时候看书因为不懂看的格外仔细。我只是那时候不懂,然而多年后的今天我仍然发现很多人对重构充满误解。在刚进入职场的几年里能碰到支持下属做重构的领导也是我个人的荣幸。
这本书里面举了很多的例子,能让我现在还记得的有两个
- 函数是要throw Exception还是要return -1
- 函数是要先判断异常情况还是要先执行正常情况
搞笑的是,这两个问题的详细答案我现在还想不起来,因为实际编程的时候我基本不会抛出异常,如果真这么做我还要在上层去catch异常,影响编程效率,而且到底throw什么异常,异常的参数也要设计,太麻烦了,并且在我的有的项目里我确实这么实践过,真是给自己挖坑。当然如果是设计sdk的api,可以考虑throw exception,因为给别人调用,还是要明确一下程序运行的条件,一旦程序不满足运行条件,“显示”的告知,比“隐式”的让别人猜好很多。第二个问题,我现在不是很在意,默认先判断异常。但是这种方式如果需要打印异常日志,就显得麻烦,下面的例子每个error要使用一次print,
if (error1) {
print("error1")
return
}
if (error2) {
print("error2")
return
}
当然后来我做了改进,只要最后只有一个return,就只需要一个print,避免代码里到处都是日志
errorType = 0
if (error1) {
errorType = 1
}
else if (error2) {
errorType = 2
}
...
print("errorType: " + errorType)
修正对重构的理解
- 重构并不会增加bug
2017年的时候我跟领导反馈过,我担心重构后本来没明显bug,结果重构完bug更多了。当时领导跟我讲,重构是改变的内部结构,不改变外部结构。也就是说,以前是什么样,重构后还是什么样,重构的目标也不是改bug,是把已经没bug的功能用更容易理解的方式优化一遍,目标就是“更容易读”。从此我写代码会一直考虑“容易读”这一个特征。甚至我写的所有代码哪怕放到几年之后我依然读起来很容易。 - 重命名也属于重构
很多人一提重构就说自己没做过,或者没有时间重构,公司不给时间重构,等等。随着程序功能的增多,有时候变量要换新的名字,重命名就需要做,重命名在Refactor->Rename里面,从这个IDE对这个功能的划分就知道,重构rename属于Refactor。 另外关于很多人说自己没做过重构,除了他不知道rename属于重构以外,他可能也没听说过rename的时机——“立即”,在书上明确写到,“当你想起一个新的名字更有表现力的时候,要立即重命名”,也就是说重构几乎是频繁发生的,在任何需要修改代码的时候都可能会需要重构。 - 重构的过程中软件产品长期不可用
最近就听到有的人重构了一个会议类项目半年,新版本半年不可用。我当时就在想,他们是不是不知道自己是在重写,以为自己是在重构。从网上专门翻了一篇文章,并截图如下,最后一句,“他在做的事情不是重构”
很久以前我的同事也经常把重写当成重构,这是一个很关键的误区,为了避免本博客把个人观点作为事实去阐述,我还专门又百度了一下,如下
重构的一些原则
如果要把实践抽象成理论,并逐一解释每个理论在实践中使用的例子,这是很困难的。不仅总结知识困难,表达和分享知识也很困难。先看下官方的说法
如果是给别人听,这样说会显得专业,但是每个人其实都有自己对于各个原则的实践情况,从而形成自己的理解,就比如百度智能问答有时候给我说7个原则,于是我还发现了三大原则,四大原则,五大原则。真的是除了一大原则,二大原则,其他的真多呀,虽然很好笑,但是经过思考的东西肯定比背诵没有消化的知识更有价值。关于这些原则的截图放在文末。其实对于这些原则除了极个别的会经常考虑,有的原则仅仅在理解以后立马抛之脑后,即便抛之脑后,如果仅仅是保持着“非必要,不让代码冗余”的原则,大概也能满足上述原则。
如何评估代码质量
1、代码重用性。2、可读性。3、可扩展性。4、可靠性。5、高内聚,低耦合。
这5条每一条都能在每一段代码中体现,甚至我常常都不去记忆上述的6大原则,而仅仅遵循这些评估代码质量的标准,就能够逐渐写出很少需要改动的代码。这5个特性因为太重要所以需要很长的篇幅才能从多个方向去讲清楚。
附图:网友的程序设计原则
三大原则
四大原则
五大原则
七大原则