重构的关键理念
1、如果一段代码能正常工作,并且不会再被修改,或者我不需要修改它来帮助我工作,那么完全可以不去重构它
2、代码被阅读和修改的次数,远远多于它被编写的次数
- 实质:这个修改者可能是我自己,而我总是记不住自己写过的代码
3、本质上来说,重构就是在代码写好之后改进它的设计。
- 程序设计不是在一开始完成的,而是在整个开发过程中逐渐浮现出来。在系统构筑过程中,要学会了如何不断改进设计。
- 与其推测未来需要哪些灵活性的机制,不如当前实现高质量的构造程序,随着需求理解的加深,可以对架构进行重构(增量式设计)
- 随着系统功能演进,函数边界发生偏移,可能需要反向重构
4、本书的目的:提供一种可控且高效的方式进行重构
5、如果程序杂乱无章,先为它整理出结构来,再做需要的修改,通常来说更加简单
6、无论每次重构多么简单,养成重构后即运行测试的习惯非常重要 - 重构的精髓:小步修改,每次修改后就运行测试
- 在重构过程中,代码很少会进入不可用的状态,即使重构没有完成,我也可以在任何时刻停下来
- 每次重构过我都会提交代码,以便能够轻松回滚到上一个可工作的状态
7、不要想一次性优化代码的结构,同时性能调优到最高:先编写构造良好的程序 -> 直至开发后期的性能优化阶段,然后 处理性能热点所在的一小段代码 -> 性能调优往往可以通过较少的工作量便有较好的成果 -> 一个程序的大半时间都耗费在一小半代码身上
- 重构的目的是为了让代码「更容易理解,更易于修改」,这可能使程序运行得更快,也可能更慢;性能优化的目的是为了让程序运行得更快,最终得到的代码可能难以理解和维护,要有心理准备和取舍
- 为了提高性能的修改,可能会造成程序难以维护,减缓开发速度
- 在聪明的编译器、现代的缓存技术面前,我们很多直觉都是不准确的 -> 不要太害怕引入多个循环 –> 有一份结构良好的代码,先写出可调优的软件,然后调优它以求获得足够的速度
8、好代码应该能清楚地表明它在做什么,而变量命名是代码清晰的关键。只要改名能够提升代码的可读性,那就应该毫不犹豫地去做。
- 函数怎么命名:根据这个函数的意图来对它进行命名(以它“做什么”来命名,而不是以它“怎么做”命名)
- 转换函数倾向于使用 toString 而不是用取值函数 value -> 一个返回字符串描述的 API 更能传达“发生了数据转换”的信息
- 变换函数 - 如果是在原来的对象上添加更多的信息,可以使用「enrich」;如果返回的是跟原来完全不同的对象,可以使用「transform」
- 技巧:先写一句注释描述这个函数的用途,再把这句注释变成函数的名字
9、有一些做法复杂时,应该采用迁移式重构做法:保留原有函数,重构新函数,逐步替换旧的调用(增量式将新的重构写入代码 -> 然后再逐一替换,保证函数功能随时可用)
10、统一访问原则:客户端代码不应该由属性是通过字段实现还是 方法 实现而受影响
- 即:不论后部的是实现是方法还是属性,外部对一个属性的访问都具有唯一的标识 -> 变量和无参数的函数都是以同样的方式访问
11、好的模块化能够让我们在修改程序时只需要理解程序的一小部分
12、程序抽象能力的源泉来自函数
- 改进程序的一个重要方向就是消除重复代码 - 代码量少并不会使系统运行更快,但是将会使可能的程序修改动作容易得多 - 代码越多,要理解的代码就越多,修改就越困难
13、想清楚两件事:本次调整的目标是什么,以及该目标能否达到(是否会产生干扰、改变程序的可观测行为)?
14、一般来说,重构早期的主要动力是尝试理解代码如何工作。通常你需要先通读代码,找到一些感觉,然后再通过重构将这些感觉从脑海里搬回到代码中。
15、好代码的检验标准就是 人们是否能轻而易举地修改它,而不易引入其他错误
16、工作中的技巧:
- 添加新功能时,我不应该修改既有代 码,只管添加新功能;
- 重构时我就不能再添加功能,只 管调整代码的结构
17、重构的唯一目的就是让我们开发更快,用更少的工作量创造更大的价值 — 重构的意义不在于把代码库打磨得熠熠发光,而在于纯粹的经济角度考量 -> 添加功能更快、修复 bug 更快 -> 是一种经济利益驱动
18、重构的时候,有时把相关元素一口气搬移到位更简单,然后再提炼、拆分
19、函数的参数列表应该总结当前函数的可变性,标示出可能体现函数行为差异的主要方式(越短越容易理解,不要重复)
- 如果传入的参数,函数自己也可以获得,这就是重复
产品总是觉得开发者在重构上面花时间是浪费他们的时间,影响需求交付的事情;殊不知,重构就是程序员去尝试理解一段代码,并将这段代码整合成后续更方便自己或者其他人理解、易于修改的结构的过程,难以阅读修改的代码,在增加功能、修改功能时,耗费的时间更久、改出bug的可能性更高,而我们的需求迭代比新增多得多,如果每段代码都有较好的可读性,做好了易修改、不易引入错误的特性,那重构就不需要发生了。
并且,重构并不需要专门花两三周时间去做,大可在日常修改 bug 和添加新功能前进行梳理 - 重构让这两项活动进行得更快,让我未来的工作也更轻松,自然也就不需要告知产品了。
碎碎念:有时候我觉得进大厂,出了身边会环绕更多优秀的人,促使自己成长以外,还有一个很重要的点是提升自己的工作体验,一个健康的代码库,尝试轻松的、高效的、强大的开发方式,获得更愉快的工作体验。
碎碎念:有时候我看到工程里面的高级设计写法,我也想要写出易读、易扩展,让我看到了想要抄个小笔记,让自己记住下次遇到类似的需求也要这样写。但是这样的方式只能一点点累积,做一个什么需求遇到什么代码,都是随机的,有些你当前觉得不错的写法,但其实存在隐藏 bug,一次次踩坑才慢慢能在写代码的时候有一些长进。我从来不觉得写漂亮代码只是为了漂亮好看,我更希望写出业务价值高的代码。我也想写出有预见性的,可拓展的,兼容业务发展的代码,我不想一直做那个创造 bug 的人,我想要做写出可靠代码的那个人。而这本书,仿佛给了个标准,让我知道我要把代码写成什么样子,才算是业务价值高的代码,是寿命长的代码,这对我来说十分十分重要。
“设计耐久性假说”:通过投入精力改善内部设计,增加了软件的耐久性,从而可以更长时间地保持开发的快速
书中对重构的两重定义:
- 名词:对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本
- 动词:使用一系列重构首发,在不改变软件可观察行为的前提下,调整其结构