你会看到
- 神秘命名
- 重复代码
- 过长函数
- 全局数据
- 发散式变化
- 霰弹式修改
- 依恋情结
- 数据泥团
- 基本类型偏执
- 重复的switch
- 循环语句
- 冗余的元素
- 夸夸其谈通用性
- 临时字段
- 过长的消息链
- 中间人
- 过大的类
- 内幕交易
- 异曲同工的类
- 纯数据类
- 被拒绝的遗赠
- 注释
神秘命名
修改命名可能是最常规的重构首发,包括修改函数声明,变量改名,字段改名等等
很多人并不愿意给程序元素改名,觉得不值得费这个时间,但好的名字能节省未来用在猜谜上的大把时间
改名并不仅仅是修改名字而已,如果你想不出一个好名字,说明背后很有可能潜藏着更深的设计问题
。为了一个恼人的名字所付出的纠结,往往能够推动我们对代码进行精简
重复代码
如果你在一个以上的地点看到相同的代码结构,那么可以肯定:设法将他们合二为一
阅读这些重复的代码时你就必须加倍仔细,留意其间细微的差异,如果要修改就必须找出所有的副本来修改
过长代码
据我们的经验,活得最长,最好的程序,其中的函数都比较短
初次接触到这种代码库的程序员常常会觉得“计算都没有发生”——程序里满是无穷无尽的委托调用。
但和这样的程序共处几年后,你会发现小函数的价值所在。
间接性带来的好处——更好的诠释力,更易于分享,更多的选择——都是由小函数来支持的
固然小函数也会给代码的阅读者带来一些负担,因为你必须经常切换上下文,才能看明函数做了什么,但现代的开发环境能够在函数的调用处和声明处之间快速跳转,或是同时看到这两处。
不过说到底,让小函数易于理解的关键还是在于良好的命名
最终的效果是:你应该更积极的分解函数,
我们要遵循这样一条原则:每当感觉需要用注释来说明什么的时候,就应该把需要说明的东西写进一个单独的函数里,并以其用途(而非实现手法)命名
。我么可以对一组甚至短短一行代码做这样的事,哪怕替换后的函数调用动作比函数自身还要长,只要函数名称能够解释其用途,我们也该毫不犹豫那么做。关键不在于函数的长度,而在于函数“做什么”和“如何做”之间的语义距离
全局变量
它们是如何被来自地狱第四层的恶魔发明出来,胆敢使用它们的程序员如今在何处安息
全局变量的问题在于可以在代码的任何地方
修改他们
而且没有任何机制可以侦测出到底哪段代码做出了修改,一次又一次,全局数据造成了哪些诡异的bug,而这些问题的根源却在遥远的别处,想要找出出错的代码难于登天
首要的防御手段是封装变量
// bad
const info = { name : "haha" }
// good
const info = { name : "haha" }
export function defaultGetInfo(){return info}
export function setGetInfo(arg){info = arg}
每当我们看到可能被各处代码污染的数据,这总是我们应对的第一招。
至少你可以看见修改它的地方,并开始控制对它的访问,随后最好将这个函数转移到一个类或者模块中,只允许模块内部的代码使用它,从而尽量控制其作用域
全局数据印证了帕拉塞尔斯的格言:良药和毒药之间的区别就在于剂量。有少量的全局数据或许无妨,但数量越多,处理的难度就会指数上升。
即使只有少量数据,我们也愿意将他们封装起来,这是软件演进过程中应对变化的关键所在