refactoring 重构

69
重重 重重重 2009-10-12

Upload: liufabin-66688

Post on 08-May-2015

1.627 views

Category:

Documents


10 download

DESCRIPTION

重构

TRANSCRIPT

Page 1: Refactoring 重构

重构刘发宾

2009-10-12

Page 2: Refactoring 重构

目录• 为何重构?• 何谓重构?• 何时重构?• 代码的坏味道• 测试• 重构名录

Page 3: Refactoring 重构

设计是有限制的,未来不可预知桥梁史上最有名的事故之一。美国华盛顿州 Tacoma Narrows 桥倒塌,这次事故令桥梁的设计规范重新修改,风力和共振分析成为桥梁设计必不可少的一部分,

重构可以带来简单的设计,同时不损失其灵活性,这也降低了设计过程的难度,减轻了设计的压力

Page 4: Refactoring 重构

设计编码是人类的活动软件开发首先是一场沟通博弈,重构就是在代码写好之后改进它的设计

有了设计,我可以思考的更快,但是其中充满了小漏洞

1300 年赵州桥与现代“豆腐渣工程”

Page 5: Refactoring 重构

管理软件的复杂度

程序的规模

程序的复杂度

程序员的工作就是保持程序的复杂度与规模的关系尽量接近线性函数,而不是指数函数,最小的复杂度,不要让无谓的复杂度快速的增长

亚里斯多德的” 事物的本质性质和附属性质”,本质复杂性解决问题核心。致力于本质复杂性,去除附属复杂性。 1 噢卡姆剃刀原理:对一现象的好多种解释,最简单的往往是正确的,如无必要,务增复杂性。2 迪米特法则 : 只跟最亲密的朋友讲话。任何对象不需要制定与之交互的那些对象的实现细节,减少复杂度高内聚,松耦合

Page 6: Refactoring 重构

需求多变杂

小的改动不容忽视,层出不尽

封装,隔离变化

Page 7: Refactoring 重构

Double B (bug bad smell)

Refactoring 是一个 code review 和反馈的过程。在另一个时段重新审视自己或别人代码,可以更容易的发现问题和加深对代码的理解, Refactoring 是一个良好的软件开发习惯,问题越是发现在前端,软件修复以及维护成本会越低 ,问题越是发现在后端,成本越来越高

Page 8: Refactoring 重构

重构的效益• 改进软件设计重构是的设计在代码中演化和完善,和

设计彼此互补,程序员对代码所做的为了满足短期利益代码改动,或再没有完全清楚增个架构下的改动,都很容易是代码失去它的清晰结构,偏离需求或设计。而这些改动的积累很容易使代码偏离它先设计的初衷而变得不可立即和无法维护。

• 使软件更容易理解程序第一是写给人看的,而不是写给机器看的,代码被阅读的和被修改的次数远远多于他被编写的次数

• 助你提高编程速度良好的设计是维持开发速度的根本,重构帮助你快速地开发软件,阻止系统腐败变质,提高设计质量

叫我如何不喜欢你!!!!

脆弱 坚硬

Page 9: Refactoring 重构

何谓重构

Page 10: Refactoring 重构

概念的定义• Refactoring is the process of changing a software system in such a w

ay that it does not alter the external behavior of the code yet improves its internal structure. – MartinFowler

• Refactoring is typically done in small steps. After each small step, you're left with a working system that's functionally unchanged. Practitioners typically interleave bug fixes and feature additions between these steps. So refactoring doesn't preclude changing functionality, it just says that it's a different activity from rearranging code.

• 名词:对软件结构的一种调整;目的是在不改变软件之可察行为,提高可理解性,降低其修改成本。

• 动词:使用一系列重构准则,在不改变软件之可察行为前提下,调整其结构。

• 两顶帽子:添加新功能,重构。交替进行。• 重构不是灵丹妙药,不是什么银弹,但是它是一把银钳子 ,测试,小修改,

测试,小修改• 重构不只是整理代码,高效且受控的代码整理技术,有一定重构准则。

概念——判断——逻辑,概念是抽象的结果,使得我们可以忽略细节,使得我们有限的心灵可以记忆管理更复杂更多的事情,定义了概念也方便我们交流沟通

概念还是要知道地!!!!

Page 11: Refactoring 重构

重构是一种方法论

牛顿万有引力定律无法解释水星运动的不规则形象,爱因斯坦构建的广义相对论理论即向下兼容了牛顿定律,又满足新的需求—自然的探索

数学系统的一直在重新构建,解决危机:有理数 ,无理数,实数,虚数, 欧几里德几何,笛卡尔的解析几何,黎曼几何, 乔治康拓的集合轮

重构也是我们认识世界,改造世界的方法论 .

Page 12: Refactoring 重构

重构和设计模式• 设计模式为重构提供了目标,但不是目的。• 设计模式是经过证实的在一定场景下解决

一般设计问题的解决方案的核心,通过设计模式我们很好得解决了某种问题,并且便于我们思考和交流,降低沟通之间的理解误差,此外同样重要的,设计模式增强了可复用性,便于将来扩展和维护。

• 设计模式是内功,《九阳真经》、《易筋经》 、 《葵花宝典》 、重构是外功,小区里的太极拳。

Page 13: Refactoring 重构

何时重构 ?重构本来就不是一件特别拨出时间做的事情,重构应该随时随地进行,你不应该为重构而重构,你之所以重构,是因为你想做别的事,而重构可以帮助你把那些事情做好。

添加功能,现有代码的设计无法帮助我轻松的 添加我需要的功能,如果用某种设计添加代码会简单很多,隔离变化点

修改错误,改变代码结构有利于我们找到臭虫。关注产生 bug点

复审代码 Bad smell

程序的两面价值观:① 今天可以为你做什么?② 明天可以为你做什么?什么程序让我们难以想与?① 难于阅读的程序② 逻辑重复的程序③ 添加新行为时需要修改既有代码者④ 带有复杂条件逻辑的程序

① 设计本身就是错误的,应该重做,不应该重构

② 已经是发布阶段了,为了稳定性,不应再重构

③ 已经是项目的后期了,如果重构可能会使项目延期,给项目带来很大冲击。

④ 如果没有十足把握,不进行重构

Page 14: Refactoring 重构

代码的坏味道• Duplicated code 重复的代码 Extract Method,Pull up Method,Template Method.• Long method, Class,Parameter list 过长方法, 类,参数 Extract Method ,Replace Temp with Query,Introduce parameter,Extract Cl

ass Extract Subclass Preserve Whole Object• Divergent Change 发散式变化 class 因不同原因在不同方向变化,一种变化导致类内修改几个函数, extract class• Shotgun Surgery 霰弹式变化 一个变化需要到不同的类去做修改,散布各处 Move Method Move Field,Inline Class• Feature Envy 依恋情结 一个类内的函数过多的调用另外类的函数, Move Method Extract Method• Data Clumps 数据泥团 多个地方看到相同数据项,两个类内相同值域 Extrat Method• Primitive Obsession 基本性别偏执,基本数据类型,结构型别 , struct 和 int , replace data alue object replae type code with class • Switch Statements switch 语句在于重复, 分散在各处的 switch 多态解决 replace type code with subclass , introduce null object • Parallel inheritance hierarchies 平行集成体系 每当你为一个 class 增加一个 subclass ,也不许为另外一个增加一个 subclass Move M

othed Move Field • Lazy Class 冗赘类 可以去掉的类 Inline class Collapse Hierarchy• Specultive Generality 夸夸其谈未来性 企图用特殊情况来处理一些非必要的事情,过度设计, rename method , remove parameter t

est cases• Temporary Field 令人迷惑的暂时值域, introduce null object • Message Chains 过度耦合的消息链 hide degate move method extract method • Middle Man 中间转手人,过多使用 delegation 委托。 Replace delegation with inheritance InlineMethod• Inappropriate intimacy 狎昵关系 两个 class 过分关注彼此的 private 。 Move method move field hide delegate• Alternative classes with different interfaces 异曲同工类 函数做同样的功能,名字不同 rename method• Incomplete livray class 别人的类库过度设计, move method introduce foreign method introduce local extension• Data class 纯稚的数据类 拥有值域,一起读写这些的函数,别的什么也没有。 Encapsulate field , remove setting method hide meth

od• Refused bequest 被决绝的馈赠 subclass 继承 superclass 函数和数据 不想喝不需要继承, push down method push down field• Comments 过多的注释 注释很好,代码很糟糕,当你感觉需要撰写注释时,请先尝试重构,试着让所有注释都变得多余

Page 15: Refactoring 重构

测试

Dcut-------design-code-unit test RT RT RT

确保所有测试自动化,让他们检查自己的测试结果

编写未完善的测试并实际运行,好过对完美测试的无尽等待

考虑可能出错的边界条件,把测试的活力集中在哪儿

Page 16: Refactoring 重构

原则一些设计类的原则尽量简单原则:尽可能的简单 隔离变化:区分出系统中变与不变 的部分。 开闭原则:对修改关闭,对扩展开放 单一职责原则:只能让一个类有且仅有一个职责 接口隔离原则:使用多个专门的接口比使用单一的总接口总要好,遵循最小接口原则。 依赖倒置原则:高层模块不应该依赖于低层模块,二者都应该依赖于抽象,抽象不应该依赖于细节 里氏替换原则:子类应当可以替换父类并出现在父类能够出现的任何地方 不要和陌生人说话 编程原则的讨论KISS – Keep It Simple StupidDRY – Don’t Repeat Yourself写代码时时刻设想你就是将来要来维护这坨代码的人 最好设想你的代码会被一个挥着斧头的精神病来维护。不要重新发明轮子 利用分治、抽象,解开子问题之间的耦合。

大自然优秀的面向对象设计师 , 程序员对宇宙人生,须入乎其内,又须出乎其外。入乎其内,故能写之。出乎其外,故能观之。入乎其内,故有生气。出乎其外,故有高致

Page 17: Refactoring 重构

如何重构• 重新组织你的方法• 在对象之间搬移特性 • 简化条件表达式 • 重新组织你的 对象 • 简化函数调用 • 处理概括关系

Page 18: Refactoring 重构

重新组织你的方法

Page 19: Refactoring 重构

Extract Method

Page 20: Refactoring 重构

Inline Method

Int getRating(){

return (moreFiveLateDeliveries()) ? 2 : 1;

}

Boolean moreFiveLateDeliveries() {

return _numberOfLateDeliveries > 5;

}

Int getRating(){

return (_numberOfLateDeliveries > 5) ? 2: 1

}

Page 21: Refactoring 重构

Replace Temp with Query

Page 22: Refactoring 重构

Introduce Explaining Variable

Page 23: Refactoring 重构

Split Temporary Variable

Page 24: Refactoring 重构

Remove Assignments to Parameters

Page 25: Refactoring 重构

Replace Method with Method Object

Page 26: Refactoring 重构

Substitute Algorithm

Page 27: Refactoring 重构

Remove Double Negative

Page 28: Refactoring 重构

Reduce Scope of Variable

Page 29: Refactoring 重构

Replace Iteration with Recursion

Page 30: Refactoring 重构

Replace Assignment with Initialization

Page 31: Refactoring 重构

Replace Static Variable with Parameter

Page 32: Refactoring 重构

Reverse Conditional

Page 33: Refactoring 重构

Split Loop

Page 34: Refactoring 重构

在对象之间搬移特性

Page 35: Refactoring 重构

Move method

Page 36: Refactoring 重构

Move Field

Page 37: Refactoring 重构

Extract Class

Page 38: Refactoring 重构

Inline Class

Page 39: Refactoring 重构

Hide Delegate

Page 40: Refactoring 重构

Remove Middle Man

Page 41: Refactoring 重构

Introduce Foreign Method

Page 42: Refactoring 重构

重新组织数据

Page 43: Refactoring 重构

Self Encapsulate Field

Page 44: Refactoring 重构

Replace Data Value with Object

Page 46: Refactoring 重构

简化条件表达式

Page 47: Refactoring 重构

Decompose Conditional分界表达式

Page 48: Refactoring 重构

Consolidate Conditional Expression 合并

Page 49: Refactoring 重构

Consolidate Duplicate Conditional Fragments

Page 50: Refactoring 重构

Replace Nested Conditional with Guard Clauses

Page 51: Refactoring 重构

Replace Conditional with Polymorphism 多态

Page 52: Refactoring 重构

Introduce Null Object

Page 53: Refactoring 重构

Introduce Assertion

Page 54: Refactoring 重构

简化函数调用• Rename method

• Add/remove parameters

• Separate query from modifier

• Param eterize method 函数带参数• Replace param eter with explicit method 明确函数取代参数• Preserve whole object 保持对象完整• Repalce parameter with methods

• Introduce parameter object

• Remove setting method

• Hide method

• Replace contructor with factory method

• Encapsulate downcast

• Replace error code with exception

• Replace exception with test

Page 55: Refactoring 重构

处理概括关系

Page 56: Refactoring 重构

Pull Up Field

Page 57: Refactoring 重构

Pull Up Method

Page 58: Refactoring 重构

Pull Up Constructor Body

Page 59: Refactoring 重构

Push Down Method

Page 60: Refactoring 重构

Push Down Field

Page 61: Refactoring 重构

Extract Superclass

Page 62: Refactoring 重构

Extract Interface

Page 63: Refactoring 重构

Extract Subclass

Page 64: Refactoring 重构

Collapse Hierarchy折叠继承体系

Page 65: Refactoring 重构

Form Template Method

Page 66: Refactoring 重构

Replace Inheritance/ Delegation with Delegation/Inheritance

Page 67: Refactoring 重构

大型重构

• 梳理并分解继承体系• 将过程化转化为对象化• 将领域和表述 /显示分离• 提炼集成体系

Page 68: Refactoring 重构

总结• 带给我们思考,不需要记住,可以当

成字典,主要是学习重构名录方法,思想,如何遵守一些编码准则。

• 重构并不高深,很简单,我们都在用,只是我们不够系统,不够专业

Page 69: Refactoring 重构

评价经典的书

参考和学习:• http://www.refactoring.com/catalog/index.html

• http://c2.com/cgi/wiki?WhatIsRefactoring

• http://c2.com/cgi/wiki?WikiPagesAboutRefactoring

• http://en.wikipedia.org/wiki/Code_refactoring

• http://www.slideshare.net/liufabin66688/refactoring-and-unit-testing

• http://www.slideshare.net/liufabin66688/refactoring-example

• http://www.slideshare.net/liufabin66688/refactoring-simple-example

• http://www.slideshare.net/liufabin66688/lecture28