Refactoring Patterns (Seventh Part)
来源:互联网 发布:it人员招聘要求 编辑:程序博客网 时间:2024/04/27 18:45
refactoring Patterns:第七部分 | ||||
石一楹 (shiyiying@hotmail.com) 虽然refactoring几乎可以随时进行,然而,按照我们关于两顶帽子的原则,在某些场合下,refactoring的介入显得更加实际、有意义、富有成效。 另外,在最后进入Refactoring实践之前,我把Kent Beck和Martin Fowler给我们的忠告和建议放在这里。这些内容,特别是Code Smell和命名规则不但对我们进行refactoring具有很强的实践意义。同时,他们也促使我们对很多OO设计和编码的原则进行更多的思考。 增加功能 另一个原因是原来代码的结构很难直接扩展,可能是因为一个类和另外一个类的绑定太紧,或者是他使用了大量的case语句,或者是有一些重复的代码让你觉得加入你的代码会使结构更差。总而言之,直接加入新功能不是太方便。这时候,你就需要Refactoring,使得旧的代码在能让旧的test case通过的情况下,让新的代码加入更加方便、快捷。 重用 如果你的代码是一个框架,那么当把代码交给其他人使用时,你必须重点考虑框架的重用方法。譬如,你想在框架之上增加一层facade,这时候,你可能需要refactoring一些内部类,让这个Facade的结构更容易加入。 对框架Refactoring可能需要是一个反馈的过程。因为框架一旦稳定就可能长期存在,一般你不会直接对这个框架增加功能。这时,不同应用程序对框架使用经验的积累可能使得你的Refactoring具有更加明确的目标,更加深层次的抽象。 修正bug Refactoring所追求的目标和过程往往使得代码的Bug无处遁形。Eric E. Allen在IBM中developerWorks的bug pattern中的一个模式就是copy-and-paste方法造成代码重复,从而产生bug的一个例子。这个 Rogue Title Pattern是一个非常常见的bug例子,当你修正了程序中一个bug时,你发现程序运行的结果是你明明已经修正的bug还在作怪。究其原因,就是程序员在实现一个功能的时候把一段代码复制过去,稍加修改,就成为一个新的函数。你修改了一个地方,但却忘了另外一个地方。 Refactoring力求排除重复代码,如果有这样的bug,在refactoring以后,一次修改就能纠正所有的问题。 Code Review 按照Martin Fowler的建议,我使用refactoring作为我的主要review方法。我有比较多的机会做这样的Code Review,在程序员发现一个难以解决的bug,或者当他们觉得自己的思路无法进行下去的时候,他们通常会要求我的帮助。 我的方法通常是问几个简单的问题,然后直接找到他们的代码,进行refactoring,在这个过程中,我总是一边refactoring,一边和程序员讲解我这样做的意图。令人惊奇的是,一旦我这样去做,程序员往往能够在我refactoring的过程中自己发现问题。由于Refactoring的结果非常具体,我很容易对程序员讲述一些本来就可以直接这样实现的例子,这对提高程序员的编程能力有极大的帮助。 味道 虽然对Refactoring的研究涉及到了形式化地探测代码的结构,譬如专门的重复代码监测工具。但这些研究尚处于幼年期。更何况,很多代码的结构并不是能够用简单的数字统计和抽象语法树所能解决的。 Code Smell是高水平的程序员对代码的一种感觉,当你能够闻到这样的味道时,你就可以在不涉及到程序所要解决的具体问题时,就"闻到"代码结构的好坏。 Kent Beck 和Martin Fowler列出的代码味道有:
Refactoring和命名 类命名 简单超类名-传达设计目的 Kent Beck给出的第一个规则就是不要缩写。缩写对输入(20年内10-100次)的考虑多余对理解(20年内1000-10000次)的考虑。理解缩写词需要两步,第一步理解这些缩写代表的词语,第二步采取理解这些词语所代表的意义。 对一个大层次的根类命名是一个重大的决策。在未来的20年中,人们可能不断地使用你所给出的名字。你必须不犯错误。 人们通常在命名超类时加上各种各样的修饰,富有计算机科学意义、给人深刻印象但最终却没有意义的单词,如Object,Thing,Component,Part,Manager,Entity或Item。 你在创建一个词汇表,而不是写一个程序。暂时做一回诗人。简单、生气勃勃、容易记忆远远比说出全部内容更有效。规则: (用一个单词命名超类,传达它的设计目的),好的例子包括:Number 、Collection、Magnitude、Model 全称子类名-区分异同 这对于通用术语来说是对的。Array是Collection的一个子类,因为绝大多数人都知道"Array"意味着什么。 但在绝大多数情况下,类继承的层次结构对于理解你的代码十分重要,特别是一个子类概念上是超类的变种同时又和超类共享实现的情况。你需要传递两部分信息:1. 新类如何相同,以及 2. 新类如何不同 要表达相同,你可以借用超类的名字。这不一定是一个直接的子类和父类关系,层次上有一定距离也无妨。要表达不同,你需要一个单词确切地强调新类为什么不是超类的理由。所以,有规则: Name subclasses in your hierarchies by prepending on an adjective to the superclass name。(在超类名字前加上内容命名你层次中的子类。)例如:BigInteger 是一个可以表达很大很大数字的整数。 方法命名-揭示意图
这个highlight只是分派到reverse,为什么还需要?关键在于Communication。因为有了这个方法,以后的代码就可以用highlight来说话。我要加亮一个区域,我就highlight它。 你当然可以直接使用reverse,结果是一样的。但所有调用代码都揭示了实现-"我通过反转一个矩形来加亮它"。代码应当揭示意图,它另外的好处是可以更方便通过继承修整。如果你想要一个ParagraphEditor用颜色加亮,那么只需继承ParagraphEditor并覆盖highlight即可。所以: communicate what is to be done rather than how it is to be done。(传达你要做什么(接口)而不是你如何做(实现)) 实例(临时)变量命名-暗示角色
一个变量的目的或者说它担当的角色对读者非常重要,因为它能够正确地引导读者的注意力。一般,你在阅读代码时脑袋里总有一个目的。如果你理解变量的角色,而这个角色和你的目的无关,那么你可以直接跳过使用该变量的无关代码。如果发现该变量的角色和你的目的有关,那么你就能马上缩小你的阅读范围-那些引用此变量的相关代码。 一个变量如何被使用和发送给它什么消息通常是它的"类型"。理解类型并非不重要。但是,对于实例变量来说,你能够了解这个变量所担当角色的唯一地方就是它的名字。如果一个Point中有两个实例变量叫做int1、int2而并非x、y,那么在你理解哪一个是横向坐标,哪一个是纵向坐标前,你可能要都上一堆代码。更何况你还要阅读与之相关的很多代码。而变量的类型很容易从它声明、传递给它的消息看出来。所以: (用计算中实例变量所承担的角色对它命名。如果变量持有一个集合,使用复数。)
|
- Refactoring Patterns (Seventh Part)
- Refactoring Patterns (Seventh Part)
- Refactoring Patterns (First Part)
- Refactoring Patterns (Second Part)
- Refactoring Patterns (Third Part)
- Refactoring Patterns (Forth Part)
- Refactoring Patterns (Fifth Part)
- Refactoring Patterns (Sixth Part)
- Refactoring Patterns (First Part)
- Refactoring Patterns (Second Part)
- Refactoring Patterns (Third Part)
- Refactoring Patterns (Forth Part)
- Refactoring Patterns (Fifth Part)
- Refactoring Patterns (Sixth Part)
- Refactoring Patterns
- refactoring Patterns:第一部分
- refactoring Patterns:第二部分
- refactoring Patterns:第三部分
- Refactoring Patterns (Second Part)
- Refactoring Patterns (Third Part)
- Refactoring Patterns (Forth Part)
- Refactoring Patterns (Fifth Part)
- Refactoring Patterns (Sixth Part)
- Refactoring Patterns (Seventh Part)
- "联想IT服务吃定金融业"随想
- “中关村软件园牵手Soft Tech 开拓美国软件外包市场”随想
- 天生矛盾 (全球盗版问题随想)
- 理解VC++里字符串类型的真正含义
- 微软亚洲研究院的管理方程式
- 软件公司的技术战略
- 一封写给中国学生的信
- 我的人才观