`
kuyuyingzi
  • 浏览: 54147 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

重构改善既有代码的设计-- 重构原则

 
阅读更多


重构定义:对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。

为何重构:重构改进软件设计、重构使软件更容易理解、重构帮助找bug、重构提高编程速度

何时重构:三次原则(三次再做类似的事)、添加功能时重构、修补错误时重构、复审代码时重构

是什么让程序如此难以修改?四个原因:

1、难以阅读的程序,难以修改;

2、逻辑重复的程序,难以修改;

3、添加新行为时需要修改已有代码的程序,难以修改;

4、带复杂条件逻辑的程序,难以修改

我们希望程序:容易阅读;所有逻辑都只在唯一地点制定;新的改动不会危及现有行为;尽可能简单表达条件逻辑。

修改接口:让旧街口调用新接口。当你要修改某个函数名称时,请留下就函数,让它调用新函数。千万不要复制函数实现,那会让你陷入重复代码的泥沼中难以自拔。你应该使用Java提供的deprecation(不建议使用)设置,将旧接口标记为deprecated。这么一来你的调用者就会注意到它了。

何时不该重构:重写(而非重构)的一个清楚讯号就是:现有代码根本不能正常运作。你可能只是试点做点测试,然后就发现代码中满是错误,根本无法稳定运作。记住,重构之前,代码必须起码能够在大部分情况下正常运作。

重构和设计:预先设计-写代码-重构。使用CRC卡或类似的东西来检验各种不同想法,然后才得到第一个可被接受的解决方案,然后才能开始编码,然后才能重构。

附录一:劳而无获—RonJeffries

ChryslerComprehensiveCompensation(克莱斯勒综合薪资系统)的支付过程太慢了。虽然我们的开发还没结束,这个问题却已经开始困扰我们,因为它已经拖累了测试速度。
  KentBeck、MartinFowler和我决定解决这个问题。等待大伙儿会合的时间里,凭着我对这个系统的全盘了解,我开始推测:到底是什么让系统变慢了?我想到数种可能,然后和伙伴们谈了几种可能的修改方案。最后,关于「如何让这个系统运行更快」,我们提出了一些真正的好点子。
  然后,我们拿Kent的量测工具度量了系统性能。我一开始所想的可能性竟然全都不是问题肇因。我们发现:系统把一半时间用来创建「日期」实体(instance)。更有趣的是,所有这些实体都有相同的值。
  于是我们观察日期的创建逻辑,发现有机会将它优化。日期原本是由字符串转换而生,即使无外部输入也是如此。之所以使用字符串转换方式,完全是为了方便键盘输入。好,也许我们可以将它优化。
  于是我们观察日期怎样被这个程序运用。我们发现,很多日期对象都被用来产生「日期区间」实体(instance)。「日期区间」是个对象,由一个起始日期和一个结束日期组成。仔细追踪下去,我们发现绝大多数日期区间是空的!
  处理日期区间时我们遵循这样一个规则:如果结束日期在起始日期之前,这个日期区间就该是空的。这是一条很好的规则,完全符合这个class的需要。采用此一规则后不久,我们意识到,创建一个「起始日期在结束日期之后」的日期区间,仍然不算是清晰的代码,于是我们把这个行为提炼到一个factorymethod(译注:一个著名的设计模式,见《DesignPatterns》),由它专门创建「空的日期区间」。
  我们做了上述修改,使代码更加清晰,却意外得到了一个惊喜。我们创建一个固定不变的「空日期区间」对象,并让上述调整后的factorymethod每次都返回该对象,而不再每次都创建新对象。这一修改把系统速度提升了几乎一倍,足以让测试速度达到可接受程度。这只花了我们大约五分钟。
  我和团队成员(Kent和Martin谢绝参加)认真推测过:我们了若指掌的这个程序中可能有什么错误?我们甚至凭空做了些改进设计,却没有先对系统的真实情况进行量测。
  我们完全错了。除了一场很有趣的交谈,我们什么好事都没做。
  教训:哪怕你完全了解系统,也请实际量测它的性能,不要臆测。臆测会让你学到一些东西,但十有八九你是错的

附录二:优化一个薪资系统—RichGarzaniti

  将ChryslerComprehensiveCompensation(克莱斯勒综合薪资系统)交给GemStone公司之前,我们用了相当长的时间开发它。开发过程中我们无可避免地发现程序不够快,于是找了JimHaungs—GemSmith中的一位好手—请他帮我们优化这个系统。
  Jim先用一点时间让他的团队了解系统运作方式,然后以GemStone的ProfMonitor特性编写出一个性能量测工具,将它插入我们的功能测试中。这个工具可以显示系统产生的对象数量,以及这些对象的诞生点。
  令我们吃惊的是:创建量最大的对象竟是字符串。其中最大的工作量则是反复产生12,000-bytes的字符串。这很特别,因为这字符串实在太大了,连GemStone惯用的垃圾回收设施都无法处理它。由于它是如此巨大,每当被创建出来,GemStone都会将它分页(paging)至磁盘上。也就是说字符串的创建竟然用上了I/O子系统(译注:分页机制会动用I/O),而每次输出记录时都要产生这样的字符串三次﹗
  我们的第一个解决办法是把一个12,000-bytes字符串缓存(cached)起来,这可解决一大半问题。后来我们又加以修改,将它直接写入一个filestream,从而避免产生字符串。
  解决了「巨大字符串」问题后,Jim的量测工具又发现了一些类似问题,只不过字符串稍微小一些:800-bytes、500-bytes……等等,我们也都对它们改用filestream,于是问题都解决了。
  使用这些技术,我们稳步提高了系统性能。开发过程中原本似乎需要1,000小时以上才能完成的薪资计算,实际运作时只花40小时。一个月后我们把时间缩短到18小时。正式投入运转时只花12小时。经过一年的运行和改善后,全部计算只需9小时。
  我们的最大改进就是:将程序放在多处理器(multi-processor)计算器上,以多线程(multiplethreads)方式运行。最初这个系统并非按照多线程思维来设计,但由于代码有良好分解(wellfactored),所以我们只花三天时间就让它得以同时运行多个线程了。现在,薪资的计算只需2小时。
  在Jim提供工具使我们得以在实际操作中量度系统性能之前,我们也猜测过问题所在。但如果只靠猜测,我们需要很长的时间才能试出真正的解法。真实的量测指出了一个完全不同的方向,并大大加快了我们的进度。


分享到:
评论

相关推荐

    重构-改善既有代码的设计 中文版.pdf

    第2章 重构原则 2.1 何谓重构 2.2 为何重构 2.3 何时重构 2.4 怎么对经理说 2.5 重构的难题 2.6 重构与设计 2.7 重构与性能 2.8 重构起源何处 第3章 代码的坏味道 3.1 Duplicated Code(重复的代码) 3.2 Long ...

    重构-改善既有代码的设计

    第2章 重构原则 53 2.1 何谓重构 53 2.2 为何重构 55 2.3 何时重构 57 2.4 怎么对经理说 60 2.5 重构的难题 62 2.6 重构与设计 66 2.7 重构与性能 69 2.8 重构起源何处 71 第3章 代码的坏味道 75...

    重构:改善既有代码的设计(中文高清版)

    第2章 重构原则53 2.1 何谓重构53 2.2 为何重构55 2.3 何时重构57 2.4 怎么对经理说60 2.5 重构的难题62 2.6 重构与设计66 2.7 重构与性能69 2.8 重构起源何处71 第3章 代码的坏味道75 3.1 DuplicatedCode(重复...

    重构-改善既有代码的设计(简体中文)

    本书使用通俗易懂的语言表达,阐述了什么是重构、重构的案例、重构原则。对于初学设计模式和具有一定编程经验的程序员都是一本很值得去读、去学习的书籍。

    重构-改善既有代码的设计 中文版

    第2章 重构原则 2.1 何谓重构 2.2 为何重构 2.3 何时重构 2.4 怎么对经理说 2.5 重构的难题 2.6 重构与设计 2.7 重构与性能 2.8 重构起源何处 第3章 代码的坏味道 3.1 Duplicated Code(重复的代码) 3.2 Long ...

    重构_改善既有代码的设计[高清版]【已进行内容识别处理,可搜索,可编辑+有目录】

    第2 章重构原则······ · ···· ······· ·· · · ·· ··· ·· · · ··· · · · · ·· · ·· ·· ·· · ···· ·· · ·· ·· ·· · ·· · ·· ···· ·····...

    重构_改善既有代码的设计[高清版]中文版

    Chapter 2:Principles in Refactoring 重构原则   Defining Refactoring 何谓重构   Why Should You Refactor? 为何重构   When Should You Refactor? 何时重构   What Do I Tell My Manager? 怎样说服...

    重构:改善既有代码的设计(中文版).

    第2章 重构原则53 2.1 何谓重构53 2.2 为何重构55 2.3 何时重构57 2.4 怎么对经理说60 2.5 重构的难题62 2.6 重构与设计66 2.7 重构与性能69 2.8 重构起源何处71 第3章 代码的坏味道75 3.1 DuplicatedCode(重复...

    程序员该读的十本好书之《重构改善既有代码的设计》

    按照传统,书籍应该以一个简介开头口尽管我也同意这个原则,但是我发现以概括性的讨论或定义来介绍重构,实在不是件容易的事。所以我决定拿一个实例做为开路先锋。 第1章展示一个小程序,其中有些常见的设汁缺陷,...

    重构-改善既有代码的设计.pdf

    重构-改善既有代码的设计,讲述什么是重构和安全重构的一些原则。

    重构_改善既有代码的设计.pdf

    第2章 重构原则53 2.1 何谓重构53 2.2 为何重构55 2.3 何时重构57 2.4 怎么对经理说60 2.5 重构的难题62 2.6 重构与设计66 2.7 重构与性能69 2.8 重构起源何处71 第3章 代码的坏味道75 3.1 DuplicatedCode(重复代码...

    重构-改善既有代码质量

    我们遵循这样一条原则:每当感觉需要以注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途(而非实现手法)命名。---P77

    重构-改善既有代码的设计(chm清晰版)

    章节二 重构原则 章节三 代码的坏味道 章节四 构筑测试体系 章节五 重构名录 章节六 重新组织你的函数 章节七 在对象之间搬移特性 章节八 重新组织数据 章节九 简化条件表达式 章节十 简化函数调用 章节十一 处理...

    重建——改善既有代码的设计

    第2章 重构原则53 2.1 何谓重构53 2.2 为何重构55 2.3 何时重构57 2.4 怎么对经理说60 2.5 重构的难题62 2.6 重构与设计66 2.7 重构与性能69 2.8 重构起源何处71 第3章 代码的坏味道75 3.1 DuplicatedCode(重复代码...

    重构 改善既有代码的设计

    Chapter 2:Principles in Refactoring 重构原则   Defining Refactoring 何谓重构   Why Should You Refactor? 为何重构   When Should You Refactor? 何时重构   What Do I Tell My Manager? 怎样说服...

    重构-改善既有代码的设计+中文版

    Chapter 2:Principles in Refactoring 重构原则   Defining Refactoring 何谓重构   Why Should You Refactor? 为何重构   When Should You Refactor? 何时重构   What Do I Tell My Manager? 怎样说服经理...

    重构-改善既有代码的设计(中文版)

    Chapter 2:Principles in Refactoring 重构原则   Defining Refactoring 何谓重构   Why Should You Refactor? 为何重构   When Should You Refactor? 何时重构   What Do I Tell My Manager? 怎样说服经理...

    重构——改善既有代码的设计

    Chapter 2:Principles in Refactoring 重构原则   Defining Refactoring 何谓重构   Why Should You Refactor? 为何重构   When Should You Refactor? 何时重构   What Do I Tell My Manager? 怎样说服经理...

Global site tag (gtag.js) - Google Analytics