【重构.改善既有代码的设计】14、总结&读后感
14、总结
首先,这是一本太老的书,很多观点已经被固化或者过时了。但核心观点没有问题,虽然大多数观点已经被认为是理所当然的事情了。
重构的定义
重构分几种:
1、狭义的代码重构
就是本书讲的,在不改变软件可观察行为的前提下,改变其内部结构。这就是完全不改变程序的功能,只是改变代码的组织方式,也就是只是整理代码而已,目的是优化代码架构,而不是优化行为、算法、逻辑或流程。
2、普通意义的重构
事实上,我们一般很少会去做纯粹的重构,所以,了解了软件行为,从行为、算法、逻辑或流程上进行优化,,往往会更加能够选择更好的方法重构了,而且更加奏效。
3、重写
有些时候,当代码已经比较腐烂时,重写是更好的重构方法,特别是功能单一的模块。
比如我们18年刚刚借着优化的名字,把一个6万行代码的模块给重写了,效果杠杠的。
重构与设计的关系
简单设计与预先设计的关系:尽可能简单的预先设计。
如果已经预测到软件会遇到某方面的变化,就必须在开始设计的时候考虑到这个变化会对代码造成的风险,使在变化发生的时候,能够方便的改动。
也就是说,你可以不去实现那些变化,但是要保证以后可以方便的实现那些变化。
重构的目的
重构就想锻炼身体,让代码保持健康。
重构的目的是优化设计,设计优化后带来的好处:
1、提高理解性
程序主要是给人看的,而不是给机器看的。
2、降低修改成本
程序的维护时间比开发时间要长的多。
所有逻辑都只在唯一的地点出现。
3、提高编程速度
--良好的设计是快速开发的基础。
重构的时机
1、小的重构
随时可以开始,当现有代码让你难受时,就重构它。除非已经到了交付的末期。
2、大规模重构
要项目统筹安排。
如何说服经理做重构工作
1、如果经理懂技术。那么说服他应该不难。
2、如果经理不懂技术,但对质量感兴趣。先让他接受review的价值,然后把重构的意见放入review中。
3、如果经理只关注进度(假装也关注质量,其实已经向进度妥协)。不告诉他,自己重构。
重构前的准备工作
小型重构
1、构建自动测试系统,保证重构安全
大型重构
1、把它分成多个模块,分块重构。
2、整个团队都必须意识到:有一个大型重构正在进行,不能让其他人把你的重构成果破坏了。
重构开始前需要明确的原则
1、重构不能损失功能,要有测试用例保证。
2、重构要与增量开发隔离,以保证随时可以回退。
3、要小步快跑,完成一块重构,就立刻跑过测试用例,然后闭环此部分重构。
4、如果某次重构后,用例不通过了,只花一小点时间定位,解决不了,立刻回退。
5、当无法决定时,不论是因为无法判断做了是否会更好,还是做起来有难度,亦或是无法决定到底如何做,那都证明,现在不是做这个的最佳时机。
重构的安全保障
安全应该有两层含义:1、代码安全;2、你自己的安全。
所谓「安全重构」(safe refactoring)就是不会对程序造成破坏的重构。由于重构的意图就是在不改变程序行为的前提下修改程序结构,所以重构后的程序行为应该与重构前完全相同。
如何进行安全重构呢?你有以下数种选择:
· 相信你自己的编码功力。
· 相信你的编译器能捕捉你遗漏的错误。
· 相信你的测试套件(test suite )能捕捉你和编译器都遗漏的错误。
· 相信代码复审(code review)能捕捉你、编译器和测试套件(test suite )都遗漏的错误。
Martin 在他的重构原则中比较关注前三个选项。大中型公司则常常以代码复审作为前三个步骤的补充。
但,百密一疏,重构是人为的动作,人不可能万无一失。所以,如果你无法承担错误的后果,就不要重构了。
重构的方法
现在已经经过层层思考,决定要重构了。
1、发现代码的坏味道
简单的,可以通过工具发现
复杂的,则要靠自己发现了
2、不停地重构一块块坏的代码
重构的各种方法,文中已经列出了,但看过不等于会用,只有日积月累的勤学苦练,才能有信心面对各种复杂的情况————学会所有的招式,才能无招胜有招。
张三丰较张无忌学太极拳,也是先学会所有的招式,然后忘掉,做到的无招胜有招。
有些人那些学了思想,就声称掌握了这门技术,往往是眼高手低罢了。
设计模式为重构提供了目标。
文中方法的缺点:不适用于并发式、分布式环境。
重构,复用与现实
为什么开发者不愿意重构他们的程序?
重构的好处是显而易见的,但这只是开发者的梦想,那么让梦想进入现实:
为什么还不肯重构你的程序呢?有几个可能的原因:
1. 你不知道如何重构。
2. 如果这些利益是长远(才展现)的,何必现在付出这些努力呢?长远看来,说不定当项目收获这些利益时,你已经不在职位上了。
3. 代码重构是一项额外工作,老板付钱给你,主要是让你编写新功能。
4. 重构可能破坏现有程序。
5. 如果你不是代码的唯一owner,怎么办?
6. 如果代码有多个分支,怎么办?
1、4可以技术解决,但2、3就到了人性层面了,尤其是当领导不支持的时候,坚持重构可能会让自己伤痕累累。
重构的难题
1、数据库
难点在于数据层与业务层耦合、数据迁移。
解决办法:加分隔层、
2、修改对外接口
这不是狭义重构允许做的,但有时你会修改接口。
解决办法:
接口共存,旧接口调新接口,直到确认旧接口没有再被调用了。
不要过早的发布接口。
重构与性能
保证软件性能的方法:
1、时间预算法。从开始就监控时间,分解每个组件允许耗费的时间,永远不允许其超过这个时间限制。这个是在对系统实时性要求非常高的软件中使用。
2、持续关切法。要求程序员任何时刻持续不断的关切新开发的代码,已保证性能。这个很难做到全面。
3、重点关切法。一般用的就是这个。类似二八原则,但这个更甚,估计要超过一九原则。90%的优化工作都是徒劳的,只有10%的优化工作是真正解决90%以上问题的。所以,把优化的重点放在这10%工作上。首要的问题,就是如何发现性能拼接在哪里?必须使用检测工具,而不是臆测,臆测的一般是错误的,会让你投入大量的时间到徒劳的工作部分。
【重构.改善既有代码的设计】14、总结&读后感的更多相关文章
- 《重构——改善既有代码的设计》【PDF】下载
<重构--改善既有代码的设计>[PDF]下载链接: https://u253469.ctfile.com/fs/253469-231196358 编辑推荐 重构,一言以蔽之,就是在不改变外 ...
- 【转】PHP 杂谈《重构-改善既有代码的设计》之一 重新组织你的函数
原文地址: PHP 杂谈<重构-改善既有代码的设计>之一 重新组织你的函数 思维导图 点击下图,可以看大图. 介绍 我把我比较喜欢的和比较关注的地方写下来和大家分享.上次我写 ...
- 《重构--改善既有代码的设计》总结or读后感:重构是程序员的本能
此文写得有点晚,记得去年7月读完的这本书,只是那时没有写文章的意识,也无所谓总结了,现在稍微聊一下吧. 想起写这篇感想,还是前几天看了这么一篇文章 研究发现重构软件并不会改善代码质量 先从一个大家都有 ...
- 重构 改善既有代码的设计 (Martin Fowler 著)
第1章 重构, 第一个案例 1.1 起点 1.2 重构的第一步 1.3 分解并重组 statement() 1.4 运用多态取代与价格相关的条件逻辑 1.5 结语 第2章 重构原则 2.1 何谓重构 ...
- 『重构--改善既有代码的设计』读书笔记----Extract Method
在编程中,比较忌讳的一件事情就是长函数.因为长函数代表了你这段代码不能很好的复用以及内部可能出现很多别的地方的重复代码,而且这段长函数内部的处理逻辑你也不能很好的看清楚.因此,今天重构第一个手法就是处 ...
- 『重构--改善既有代码的设计』读书笔记---Duplicate Observed Data
当MVC出现的时候,极大的推动了Model与View分离的潮流.然而对于一些已存在的老系统或者没有维护好的系统,你都会看到当前存在大把的巨大类----将Model,View,Controller都写在 ...
- 『重构--改善既有代码的设计』读书笔记----Replace Array with Object
如果你有一个数组,其中的元素各自代表不同东西,比如你有一个 QList<QString> strList; 其中strList[0]代表选手姓名,strList[1]代表选手家庭住址,很显 ...
- 『重构--改善既有代码的设计』读书笔记----Change Reference to Value
如果你有一个引用对象,很小且不可改变,而且不易管理,你就需要考虑将他改为一个值对象.在Change Value to Reference我们说过,要在引用对象和值对象之间做选择,有时候并不容易,有了重 ...
- 『重构--改善既有代码的设计』读书笔记----Change Value to Reference
有时候你会认为某个对象应该是去全局唯一的,这就是引用(Reference)的概念.它代表当你在某个地点对他进行修改之后,那么所有共享他的对象都应该在再次访问他的时候得到相应的修改.而不会像值对象(Va ...
随机推荐
- STL中deque 解析
一.deque的中控器 deque是连续空间(至少逻辑上看来如此),连续线性空间总令我们联想到array或vector.array无法成长,vector虽可成长,却只能向尾端成长,而且其所谓的成长原是 ...
- 记录一次nginx502/504问题解决过程
最近自己在阿里云购买有段时间的服务器,一访问就出现nginx 504 Gateway Time-out. 想起以前是可以访问的,细想最近改动的配置应该不会涉及到这块啊. 就网上各种百度谷歌,最后终于找 ...
- java调用ruby代码
问题: 最近在做一个应用的时候碰到了一个问题.客户端需要调用服务器端传回的脚本信息,然后执行.其中脚本类型包括ruby.而java中调用ruby的代码大致如下: String jrubyCode=&q ...
- developer.android.google.cn
Android Studio官方 Android IDE https://developer.android.google.cn/studio/index.html 探索 Android Studio ...
- 禁止选中页面内容-兼容ie、firefox、chrome
使用js禁止用户选中网页上的内容,IE及Chrome下的方法一样.使用onselectstart, 比如: 在body中加入<body onselectstart="return fa ...
- 第6天:数据Array
数组Array every() 方法测试数组的所有元素是否都通过了指定函数的测试. array.every callback[, thisArg] callback 被调用时传入三个参数:元素值,元素 ...
- 【原】Java跨域以及实现原理
前言:最近研究了一下跨域,主要是jsonp的实现,经过测试后总结如下: 一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面.动态网页.web服务.WCF,只要是跨 ...
- WCF4.0安装 NET.TCP启用及常见问题
WCF4.0安装及NET.TCP启用 WCF 4.0 一般默认安装.net Framework 4.0的时候已经安装. 但如果先装.net framework 4.0,后装IIS,就会出现问题.需要重 ...
- Git基础--笔记
0.取的项目的git仓库 有两种取得 Git 项目仓库的方法.第一种是在现存的目录下,通过导入所有文件来创建新的 Git 仓库. 第二种是从已有的 Git 仓库克隆出一个新的镜像仓库来 1.在工作目录 ...
- OpenStack IceHouse 部署 - 3 - 控制节点部署
Mysql部署配置 安装 安装mysql,mysql的python绑定 apt-get install mysql-server 安装过程中会要求设定mysql的root账户的密码,这里假定设为my ...