Refresh 重构(Refactor)
最近在闲暇之余重(第)温(一..次)此书, 首先能感受到的, 无论你是新程序员还是老程序员, 这本书都已经不具备太多的可读性了.
由于本书成书年代久远, 那个时候软件行业还不够发达, 面向对象还没有被大数人理解, 加之编译器也非常落后, 设计模式也不深入人心, 所以文中提供的所谓重构的心法, 在当时或许有一些意义. 而今看来, 整书400多页的文字, 主要的思想就是「抽」, 无论是类, 接口, 方法, 逻辑, 还是参数. 但是为什么会有这么大的篇幅, 其中一半的内容是教你如何在一个IDE功能匮乏的年代, 以一个出错率更低的顺序, 来进行上面所说的多种抽象操作.
当然我去除了大量书中已经没有任何价值的点后, 总结了如下的一些内容, 应该大多数大家已经在工作实践中已有体会, 主要还是总结一下, 温故知新吧.
- 思想方面
- 如果发现加特性很难, 就需要重构
- 重构前需要想想有没有可靠的测试机制
- 重构要微小步伐, 容易发现错误
- Extract method是最简单的重构
- 写出机器认识的代码容易, 写出人类容易理解的才是应该的, 最大的影响就是命名
- 做移动重构时, 最好先复制粘贴, 测后再删除旧的代码
- 对于另外对象的switch往往可以通过继承, 多态来取代
- 三次遇到不合理的, 可能就是重构的时候了
- 重构往往通过加隔离层进行
- 不要过早发布接口
- 性能优化应该基于良好的代码结构, 性能瓶颈往往只会在很小的代码片段里
- 每次遇到一个bug, 尽量写个单元测试覆盖
- 测试集中覆盖边缘case
- 代码坏味道与手段
- 重复代码
- 抽方法
- 大函数
- 抽方法, 抽类
- 大类
- 抽类, 抽子类
- 太多参数
- 参数变方法, 抽参数对象
- 加新功能修改多个函数
- 抽子类
- 加新功能需要改很多类
- 挪方法, 挪成员
- 函数过度依赖其他类
- 挪方法, 抽方法
- 同样的几个参数到处出现
- 抽参数对象
- 大量同样的基本类型做参数
- 抽类, 不同表达式可抽进子类
- 很多switch
- 考虑用多态取代
- 子类需平行同时添加
- 先持有对方, 再挪方法, 再挪变量, 再合并
- 没人用的类
- 做内部类
- 没太大用处的抽象, 参数, 命名
- 删除, 重命名, 内联
- 临时变量命名模糊
- 抽方法, 抽类
- 消息链过长, 对象转换过多
- 对同一对象的使用抽方法, 推入消息链消除对象
- 过度代理
- 内联代理
- 注释太多
- 可能代码写的太难懂, 需要重构
- 重复代码
- 数据
- 临时变量被赋值多次, 则可以抽成方法
- 有时候需要提取多个临时变量对逻辑进行解释, 当然更好的可以再抽成方法
- Java按值传递, 本质上是对象的引用按值传递
- 移除中间人与隐藏委托是相辅相成的
- 如果类无法更改, 就写个函数包装他, 类似于工厂方法?
- 如果不能修改, Adapter模式常常用于扩展方法功能
- 子类修改某些变量的获取可以通过自封装, 把变量抽象成函数
- 成员如果不用改变, 就由引用变为值对象, 即immutable对象
- 当业务复杂度变高需要将类之间单向关系改为双向绑定关系, 甚至一对多与多对一的关系
- 双向绑定可能会造成很多僵尸对象, 增加复杂度与空间占用, 所以只有真正需要的时候用, 删除可以通过将内部绑定查询转移为传参, 再在调用的位置进行判断是否为僵尸对象
- 不要使用Magic Number, 常量即可以优化储存, 又可读性高
- 封装字段可以控制字段的读写, 称之为数据隐藏
- 对于返回集合的函数需要返回只读副本, 如果需要修改, 则可另行提供修改方法
- 原始类型替换成类, 有类型字段的类转换为多个子类, 或者抽象成策略模式, 从而合理改变数据结构
- 如果子类只有常量, 可以抽成变量放父类, 再添加工厂方法创建, 降低复杂度
- 条件表达式
- 条件表达式很复杂的时候, 可以将条件, 执行代码进行封装, 更表意
- 嵌套很深的条件表达式的每个结果都作为返回值的话, 可以简化为多个if+return, 类似于swift里面的guard, 或者kotlin里面的?:return, 书里叫卫语句(Guard Clauses)
- 嵌套很深的条件表达式可以将范围大的if反向, 实现提前return
- switch表达式有时候可以通过多态来取代
- 函数调用
- 函数最好读写分离
- 抽象重复性的函数用以复用
- switch构造可以替换成工厂方法
- 从对象内拿出参数再传递给某函数不如直接将对象传入函数
- 当函数的参数来自另外一个函数时, 也可以删掉参数, 把函数调用挪进去
- 函数参数过多可以同对象替代
- 如果不需要设置就不要提供set方法, 变量都需要为final
- 有时候用抛异常替代返回错误码, 如果程序无法继续进行的话
- 如果可以条件逻辑避免Runtime异常, 应不要无脑try/catch
- 继承关系
- 子类同样的方法应该向上提, 并将不同的地方抽象为抽象方法分别继承
- 子类构造复制父类字段应该通过父类构造, super
- 超类与子类差不多, 就合并
- 逻辑相同, 类型不同可以通过模板函数, 模板类解决
- 不能滥用继承, 组合代理好过继承, 但也有特殊, 如果需要使用委托函数所有函数或者大量, 则就需要继承, 不过这一点在kotlin里面也可以通过by来代理
- 复杂的重构
- 整理复杂的继承关系, 该抽接口抽接口, 摘出更多深层子类
- 领域与表述分离, 就是UI与逻辑分离
- 过程抽象为对象
- 提炼继承体系
Refresh 重构(Refactor)的更多相关文章
- IDEA工具java开发之 代码重构Refactor 重命名 删除移动复制 生成变量 抽取方法
一.重命名 用shift + F6 或者右键单击 二.抽取方法 .三.生成变量 . 四.文件移动复制和删除 可以右键
- java重构、js与接口的实现
一.接口 接口的方法不一定必须实现的!!! 加入default,这样的方法可以不实现,如图所示 二.关于语言的特性 1.C++多继承 2.很多编程语言JavaScript.Python支持混入(Mix ...
- 利用pycharm进行重构学习记录
pycharm是非常强大的pythonIDE,集成了很多实用的功能,其中就包括重构Refactor 记录下使用pycharm的重构 pycharm的Refactor默认在主菜单上就有了 Refacto ...
- VS快捷键总结(包括ReSharper)
Shift+Alt+Enter 全屏显示代码Ctrl+E 最近文件列表Ctrl+B 转到定义Ctrl+Alt+B 转到继承类或接口处Ctrl+U 转到基类Ctrl+D 复制当前行或选定的块(Dupli ...
- 实验三 敏捷开发与XP实践
实验内容 1. XP基础 2. XP核心实践 3. 相关工具 实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑器> 课程 2.完成实验 ...
- 20145206《Java程序设计》实验三实验报告
20145206<Java程序设计>实验三实验报告 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运 ...
- 20145334实验三《敏捷开发与XP实践》
实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步骤 1.敏捷开发与XP 敏捷开发(Agile Dev ...
- Java程序设计 实验三
北京电子科技学院(BESTI) 实 验 报 告 课程:Java程序设计 班级:1353 姓名:李海空 学号:20135329 成绩: 指 ...
- 20145320《Java程序设计》第三次实验报告
20145320<Java程序设计>第三次实验报告 北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1453 指导教师:娄嘉鹏 实验日期:2016.04.22 15: ...
- 实验三 java敏捷开发与XP
一.实验内容 (一)敏捷开发与XP 软件开发流程的目的是为了提高软件开发.运营.维护的效率,并提高软件的质量.用户满意度.可靠性和软件的可维护性. 光有各种流程的思想是不够的,我们还要有一系列的工具来 ...
随机推荐
- Redis原理再学习02:数据结构-动态字符串sds
Redis原理再学习:动态字符串sds 字符 字符就是英文里的一个一个英文字母,比如:a.中文里的单个汉字,比如:好. 字符串就是多个字母或多个汉字组成,比如字符串:redis,中文字符串:你好吗. ...
- Apple设备屏幕尺寸和方向
表格中包括了各种型号的iPad.iPhone.以及iPod touch等设备的详细信息,涵盖了从iPad Pro到各代iPhone和iPod touch的多个型号. 这些信息可用于开发应用程序时优化界 ...
- 迭代器,map,filter,reduce,sorted函数---day12
1.迭代器 迭代器能被next调用,并不断返回下一个值的对象,叫作迭代器(迭代器是对象) 概念:迭代器指的是迭代取值的工具,迭代是一个重复的过程每次重复都是基于上一次的结果而继续单纯的重复不是迭代. ...
- ubuntu18.04更换下载源
步骤一 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak 步骤二 vim /etc/apt/sources.list 步骤三 # http ...
- 【Docker】.Net Core 结合Nlog集成ELK框架(Elasticsearch , Logstash, Kibana) (五)
之前有项目有用过ELK做过日志架构,不过是非docker形式安装的,今天来探究一下ELK的容器化技术 Elasticsearch 是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动 ...
- sql判断字符串中含中文方法
基于UTF-8字符集 它是一种多字节字符集,编码为变长编码.那么它的编码范围根据:http://www.iteye.com/topic/977671 作者提供的资料学习,整理出它编码范围如下: u2e ...
- 【算法day5】排序算法的稳定性及其汇总
稳定性 定义:值相同的元素在排序完成之后能否保证原有的次序不变(同样值的个体之间,如果不因为排序而改变相对次序,这个排序就是有稳定性的,否则就没有) 举例: [2,1,3,1]-->[1,1,2 ...
- 07、Etcd 中Raft算法简介
本篇内容主要来源于自己学习的视频,如有侵权,请联系删除,谢谢. 思考: etcd是如何基于Raft来实现高可用.数据强-致性的? 1.什么是Raft算法 Raft 算法是现在分布式系统开发首选的共识算 ...
- C笔记(2014-12备份)
Video1: 1-编译器对待全局变量和局部变量的差别.全局变量分配空间是在数据区,局部变量分配在代码区. (比如局部变量 int lo_var = 2;后面的 = 2;是赋值语句,被编译器转化成机器 ...
- STM32SPIFLASH读写
STM32SPIFLASH读写 1.1 SPI注意事项 SPI是同步通信,即通信双方每次信息交互必会带有一问一答,这代表在正常的单核MCU(例如STM32)中很难实现软件模拟的双向SPI通信(TFT屏 ...