Your SlideShare is downloading. ×
软件重构
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

软件重构

3,594
views

Published on


1 Comment
18 Likes
Statistics
Notes
  • Bit, download is disabled.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
3,594
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
0
Comments
1
Likes
18
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. 软件重构讨论
  • 2. 大纲
    • 前言 preface
    • 为什么要重构 (refactoring) why
    • 什么是重构 (refactoring) what
    • 何时何地去重构 (refactoring) when & where
    • 如何去重构 (refactoring) how
    • 一个例子 demo
  • 3. 前言
    • 软件发展的趋势 ( 单纯从大小来看 )
    • Dos 时代 以 K 为单位
    • Windows 单机时代 以 M 为单位
    • 网络时代 以 G 为单位
    • 软件发展的趋势 ( 单纯从系统规模来看 )
    • Dos 时代 无盘工作站
    • Windows 单机时代 个人 PC
    • 网络时代 大规模云计算(成千上万台机器 ,google 有千万台)
  • 4. 前言
    • 尽管软件工程以及工艺水平经过几十年的发展,有了质的提升,但是面对硬件水平的摩尔定律发展速度。以及各种浩如烟海的应用需求及场景,软件水平发展还是有点吃力。我们开发人员所面对的需要解决问题比以前复杂得多,困难得多。
  • 5. 面对的挑战 软件能力
      • 变化
        • 业务发展越来越迅速,需要业务敏捷
        • 长尾理论,个性化需求越来越多
        • 按需定制的需要
      • 技术
        • 技术学习曲线越来越高
        • 大规模计算,分布式场景需要软件高度扩展
      • 复杂
        • 应用场景越来越复杂
        • 系统规模越来越大
        • 计算的规模越来越大
        • 协同,并行,高度分布
      • 硬件
        • CPU 处理能力以及芯片技术发展日新月异
        • 硬件的利用率还是不够高
        • 需要软件能跟上硬件的发展速度
  • 6. 如何应对? 软件能力提升
      • 拥抱变化
        • 业务发展越来越迅速,需要业务敏捷
        • 长尾理论,个性化需求越来越多
        • 按需定制的需要
      • 高度扩展
        • 技术学习曲线越来越高
        • 大规模计算,分布式场景需要软件高度扩展
      • 高度复用
        • 组件复用
        • 业务过程复用
      • 大规模计算
        • 计算能力提升,充分利用硬件能力
  • 7. 如何应对 ?
    • 面对软件危机 ( 有夸大嫌疑咯 :) ,各路神仙大牛纷纷出招。
  • 8. 如何应对?
    • 我们的兵器谱
    • 内功:
    • << 设计模式 >>
    • << 敏捷软件开发原则模式
    • 与实践》
    • 外功:
    • << 重构改善既有代码设计》
    • << 领域驱动设计 >>
    • 内外兼修方能行走江湖!
  • 9. 兵器谱之必杀技 - 重构
    • 今天我们只学习兵器谱上排名前四的重构技术。
    • ~==~,杀人越货之必备技艺
  • 10. 为什么要重构 (why)
    • 案例 : 小 A 是 XX 公司某公用组件的开发者。改组件已经支撑公司多个项目。并且取得了很好的效果 . 改组件运行一年多,小 A 突然发现组件很难维护了
    • A: 各项目的需求差异很明显,为了支持这些特性组件中有太多的逻辑分支。
    • B: 组件本身规划不合理,导致小 A 很难维护。改一个点有可能引起其他点的问题。
    • C: 随着各项目需求 的增多,组件已经不能快速满足醒目的需求。
    • 小 A 已经被搞的一头乱麻,天天喊 somebody help me ?
    • who? 只有靠自己
  • 11. 为什么要重构 (why)
    • 为什么要重构 (refactoring) why
    •  程序员的三大敌人。
  • 12. 为什么要重构 (why)
    • 为什么要重构 (refactoring) why
    •  程序员的三大敌人。
    •  变化:业务需求变化快,唯一不变的是变化 ( 至理名言 )
    •  重复:冗余,繁复,导致难以快速修改
    •  复杂:大型程序结构复杂,牵一发而动全身
    •   只要你选择了这个职业,就需要好好的重视我们的对手,是我们一辈子的敌人,要穷一生精力与其奋斗到底,与敌人斗其乐无穷。
  • 13. 为什么要重构 (why)
    • 困惑
    • 开发人员:为什么代码这么难懂?为什么修改来修改去的,为什么天天加班?
    • 产品经理:为什么开发推出这么慢?
    • 设计人员:不是我慢,是这需求变化快。
    • 测试人员:为什么缺陷居高不下。
    • 项目经理:为什么风险不可控?
  • 14. 为什么要重构 (why)
    • 改进软件的设计。
      • 程序员对代码所做的为了满足短期利益代码改动,或再没有完全清楚增个架构下的改动,都很容易是代码失去它的清晰结构,偏离需求或设计。而这些改动的积累很容易使代码偏离它原先设计的初衷而变得不可立即和无法维护。
      • Refactoring 则帮助重新组织代码,重新清晰的体现结构和进一步改进设计
  • 15. 为什么要重构 (why)
    • 提高代码质量,更易被理解
      • 容易理解的代码可以很容易的维护和做进一步的开发。即使对写这些代码的程序员本身,容易理解代码也可以帮助容易地做修改。程序代码也是文档。而代码首先是写给人看的,让后才是给计算机看的
  • 16. 为什么要重构 (why)
    • Refactoring 帮助尽早的发现错 (Bugs)
      • Refactoring 是一个 code review 和反馈的过程。在另一个时段重新审视自己或别人代码,可以更容易的发现问题和加深对代码的理解。
      • Refactoring 是一个良好的软件开发习惯
      • 问题越是发现在前端,软件修复以及维护成本会越低
      • 问题越是发现在后端,成本越来越高
  • 17. 为什么要重构 (why)
    • Refactoring 可以提高开发速度
      • Refactoring 对设计和代码的改进,都可以有效的提高开发速度。好的设计和代码质量实体提高开发速度的关键。在一个有缺陷的设计和混乱代码基础上的开发,即使表面上进度较快,但本质是试延后对设计缺陷的发现和对错误的修改,也就是延后了开发风险,最终要在开发的后期付出更多的时间和代价。
      • 项目的维护成本远高于开发成本 .
      • 古人云:谋定而后动。
  • 18. 为什么要重构 (why)
    • Refactoring 可以 演进出新的架构
      • Refactoring 对于遗留系统做出持续改进 。 有利于在已经寄出上演进出新的架构。
      • 项目 不是推到重来而是演进 .
      • 花费代价最少,效果可能最好。
  • 19. 什么是重构
    • 什么是重构 (refactoring) What
    • Fowler 定义: Refactoring 是对软件内部结构的一种调整,目的是在不改变外部行为的前提下,提高其可理解性 , 降低其修改成本 。
    • 重构与重做的区别:重构是在已有基础上的完善,去其糟粕取其精华。是循序渐进式的进化过程。
    • 重做是推到重来,完全的另起炉灶。革命式的进化过程。往往杀伤力极强。
  • 20. 什么是重构 (refacting)
    • 重构的几个层次及种类
    • 低层次重构
    • 包重构
    • 类重构
    • 高层次重构
    • 设计重构
    • 系统重构
    • 服务重构
    • 业务重构
  • 21. 何时何地去重构 (refactoring)
    • 何时应该去重构
    • 代码很难读懂时考虑重构
    • 添加新功能时一并重构
      • 为了增加一个新的功能,程序员需要首先读懂现有的代码。
    • 修补错误时一并重构
      • 为了修复一个 Bug, 程序员需要读懂现有的代码。
    • Code Revie w 发现错误考虑重构
    • 发现代码坏味时考虑重构
  • 22. 何时何地去重构 (refactoring)
    • 在什么地方进行重构
    • 需要有猎狗的嗅觉?
    • 发现代码坏味道。
    • 重复的代码( Duplicated Code)
    • 过长的函数 (Long Method)
    • 过大类 (Large Class)
    • 过长的参数列 (Long Parameter List)
    • 发散式变化 (Divergent Change)
    • 霰弹式修改 (Shotgun Surgery)
    • 依恋情结 (Feature Envy)
    • 数据泥团 (Data Clumps)
    • 基本型别偏执 (Primitive Obsession)
    • Switch 语句 (Swtich Statements)
    • 平行继承体系 (Parallel Inheritance Hierarchies)
    • 冗赘类 (Lazy Class)
    • 夸夸其谈未来性 (Speculative Generality)
    • 令人迷惑的暂时值域 (Temporary Field)
    • 过度 耦合 的消息链 (Message Chains)
    • 中间转手人 (Middle Man)
    • 狎昵关系 (Inappropriate Intimacy)
    • 异曲同工的类 (Alternative Classes with Different Interfaces)
    • 不完善的程序库类 (Incomplete Library Class)
    • 纯粹的数据类 (Data Class)
    • 被拒绝的遗赠 (Refused Bequest)
    • 过多的注释 (Comments)
  • 23. 何时何地去重构 (refactoring)
    • 何时不应该重构
    • 设计本身就是错误的,应该重做,不应该重构
    • 已经是发布阶段了,为了稳定性,不应再重构
    • 已经是项目的后期了,如果重构可能会使项目延期,给项目带来很大冲击。
    • 如果没有十足把握,不进行重构
  • 24. 何时何地去重构 (refactoring)
    • 重构遵循的流程
    • 读懂已有代码
    • 写好单元测试
    • 找到代码坏味
    • 重构 Action
    • 编译并做单元测试
  • 25. 如何去重构 (refactoring)
    • 低层次重构
    • 包重构
    • 类重构
    • 高层次重构
    • 设计重构
    • 本胶片只涉及以上 3 种类型的重构,重点阐述包重构与类重构的。设计重构略作探讨。系统以及应用重构不做探讨,有兴趣线下探讨。
  • 26. 如何去重构 (refactoring)—— 包重构
    • 包重构
    • 指导我们重构的原则 ( 不二法门 ) :
    • 包无循环依赖原则 : 包与包之间不能形成循环依赖
    • 稳定依赖原则 : 包应该依赖比自己稳定包,抽像不能依赖具体 。
    • 稳定抽象原则 : 越稳定包应该也是越抽象的
    • 共同封闭原则 : 同一个包内的类应该对修改同时开闭,一起修 改的类,应该组合在一起,使包容易变大
    • 共同复用原则 : 同一个包内的类应该被同时复用,估计包变小
  • 27. 如何去重构 (refactoring)—— 包重构
    • 违反了哪几个原则
    • 面向接口编程的原则:没有清晰的接口定义层
    • 循环依赖的原则: client 依赖 core,core 又依赖 client
    • Client 接口蔓延 : client 本身应该是与业务接口的门面,是隔离内部实现与外部接口的。但是目前 client 信息散发到各处,导致内部重构不方便。
  • 28. 如何去重构 (refactoring)—— 包重构
    • 重构后的包结构
    各实现子模块不再有私密关系了,通过高层的接口契约实现沟通,完全做到可插拔
  • 29. 如何去重构 (refactoring)—— 类重构
    • 指导类设计的原则
    • 尽量简单原则:尽可能的简单
    • 隔离变化:区分出系统中变与不变 的部分。
    • 开闭原则:对修改关闭,对扩展开放
    • 单一职责原则:只能让一个类有且仅有一个职责
    • 接口隔离原则:使用多个专门的接口比使用单一的总接口总要好,遵循最小接口原则。
    • 依赖倒置原则:高层模块不应该依赖于低层模块,二者都应该依赖于抽象,抽象不应该依赖于细节
    • 里氏替换原则:子类应当可以替换父类并出现在父类能够出现的任何地方
    • 不要和陌生人说话
  • 30. 如何去重构 (refactoring)— 技巧
    • 重新组织你的 方法
    • 简化条件表达式
    • 重新组织你的 对象
    • 简化函数调用
    • 处理概括关系
  • 31. Extract Methods( demo1 )
    • String name = request.getParameter(&quot;Name&quot;);
    • if ( name != null && name.length() > 0 ){
      • ......
    • }
    • String age = request.getParameter(&quot;Age&quot;);
    • if ( age != null && age.length() > 0 ){
      • ......
    • }
    • String name = request.getParameter(&quot;Name&quot;);
    • if ( ! isNullOrEmpty ( name ) ){
      • ......
    • }
    • String age = request.getParameter(&quot;Age&quot;);
    • if ( ! isNullOrEmpty ( age ) ){
      • ......
    • }
    • private boolean isNullOrEmpty ( final String string ){
      • if( string != null && string.length() > 0 ){
        • return true;
      • }else{
        • return false;
      • }
    • }
  • 32. Extract Methods( demo2 )
    • void printOwing() {
      • //print banner
      • System.out.println(“*********”);
      • System.out.println(“Banner”);
      • System.out.println(“*********”);
      • //print details
      • System.out.println (&quot;name: &quot; + _name);
      • System.out.println (&quot;amount &quot; +
      • getOutstanding());
    • }
    • void printOwing(){
      • printBanner ();
      • printDetails (getOutstanding());
    • }
    • void printBanner (){
      • System.out.println(“*********”);
      • System.out.println(“Banner”);
      • System.out.println(“*********”);
    • }
    • void printDetails (double outstanding){
      • System.out.println (&quot;name: &quot; + _name);
      • System.out.println (&quot;amount &quot; + outstanding);
    • }
  • 33. 方法内联化( demo )
  • 34. 查询替代临时变量( demo )
  • 35. 引入解释性变量( demo )
  • 36. 合并重复条件段( demo )
  • 37. 传递整个对象( demo )
  • 38. 简化条件表达式 --- 分解条件
  • 39. 简化条件表达式 --- 移除双重否定
  • 40. 重新组织你的对象 --- 提炼类
  • 41. 重新组织你的对象 --- 提炼接口
  • 42. 简化条件表达式 --- 提炼子类
  • 43. 重新组织你的对象 --- 提炼父类
  • 44. 重新组织你的对象 --- 内联类
  • 45. 重新组织你的对象 --- 隐藏代理 { person.getDepartment().getManager() } { person.getManager() } 不要和 陌生人说话 !
  • 46. 重新组织你的对象 --- 搬移类 便于重用
  • 47. 重新组织你的对象 --- 搬移方法
  • 48. 简化函数调用—分离查询与修改
  • 49. 讨论
    • 重构与模式的关系 ?
    • 不要刻意为模式而重构。
    • 重构合理自然会过度到模式。
    • 重构会影响代码性能?
    • 会有点影响,现代编译器技术进步,可以不用考虑,即使有性能问题重构后的代码更好定位。再重构解决
    • 重构到什么程度?
    • 自己阅读起来很舒服就算合理
    Q&A ?
  • 50. 讨论
    • 重构就是这么简单,让我行动起来!
    • 每天重构一小步,进步一大步!
    • 谢谢!