《重构》学习笔记-构筑测试系统与大型重构

构筑测试系统 测试……一年前,我开发的时候还是很不在乎测试,不过那个时候也没人告诉我测试的重要性。直到意识到要提高自己,学习中看到了那么多提到测试的,所以慢慢的尝试使用(大部分是单元测试),然后深深的爱上了单元测试(其他测试呢,好吧,编程中的确比较少用到其他测试,我比较懒)。 作者在前面反复提到测试在重构中的重要性,这章就是介绍测试的。 自我测试代码的价值: 编码往往只占了开发中的小部分时间,很多时间不是在沟通、设计,就是在找 BUG 。。。专业点,应该叫调试( debug )。测试的主要作用就是帮助调试,帮助开发中发现潜在的 BUG ,这样我们就可以少话点时间在调试上了。频繁进行测试是极限编程(下一个学习的内容)的重要一环。 确保所有测试都是自动化,让它们检查自己的测试结果。 一整组测试就是一个强大的 BUG 侦测器,能够大大缩减查找 BUG 所需要的时间。 JUNIT : 看来 JUNIT 的历史很悠久啊,作者写书的时候就已经很成熟了。我想这个不需要多说了,现在有关 JUNIT 的介绍到处都是。我也喜欢用 JUNIT ,不过看书中的介绍的 JUNIT 的基本使用有点老了,完全忽略吧。 重构前先为需要重构的功能构建好测试用列,在重构中,每次变动都需要进行测试,以确保重构没有给程序带来什么BUG。这个很重要。 大型重构 大型重构的重要性:大型重构没有那些小动作那样立竿见影的效果,不过它可以帮助我们解决那些堆积了很久,影响范围又很大的问题。 Tease Apart Inheritance (梳理并分解继承体系) 用于处理混乱的继承体系——这种继承体系往往以一种令人迷惑的方式组合了数个不同方面的变化( variations )。 某个继承体系( inheritance hierarchy )同时承担两项责任。 建立两个继承体系,并通过委托关系( delegation )让其中一个可以调用另一个。 Convert Procedural Design to Object (将过程化设计转化为对象设计) 可以帮助你解决一个「古典」问题:如何处理程序性代码( procedural code )? 你手上有一些代码,以传统的过程化风格( procedural style )写就。 将数据记录( data records )变成对象,将行为分开,并将行为移入相关对象之中。 Separate Domain from Presentation (将领域和表述 / 显示分离) 将业务逻辑( business logic )与用户界面( user interface )隔离开来。...

July 29, 2013

《重构》学习笔记-代码的坏味道

代码的坏味道 … 老外没有艺术细胞,作为一名大师级人物,好歹给起个好听点的名称。向金庸老人家学习下,让我们也感染下艺术气息。 我认为吗,坏味道就是对一段问题代码的感觉,从感性慢慢分析到理性。这种感觉需要在实践中培养。观看这里的介绍只能有个大概的理解方向,只有在反复在实际的代码中去体会,才能运用自如。 我也是爱国人士,也很不喜欢英语,不过毕竟都是老外的东西,为了避免一些名词的混淆,我还是用英语加翻译的方式。 一、 重复代码( Duplicated Code ) 很直观的一个问题,就算新手也很快能看出。如果是同一个类里面有重复代码,使用 Extract Method (提炼函数)把重复的给提取出来;如果重复代码分别在一个类的两个子类中,则先提取代码,然后使用 Pull Up Method (函数上移)把提取的函数放到 superclass 中;如果在好不相干的两个类中,则考虑使用 Extract Class (提炼类)把重复代码独立成一个类,也可以把函数放在其中一个类中,另一个应用这个之,看实际情况了。 二、 过长函数( Long Method ) 看 50 行的 20 个函数比看一千行的一个函数强多了,所以么函数不宜过长,或者说就应该短, java 在调用函数时候的开销很小,一般不会产生性能问题。我也讨厌那些长函数,看到后面逻辑都乱了,本人见过两千行的函数,唉,一半注解一半代码。 99% 的场合只需要使用 Extract Method (提炼函数)。如果函数内有大量的参数和临时变量,可以尝试 Extract Method (提炼函数)把那些参数和临时变量当作参数,运用 Replace Temp With Query (以查询取代临时变量)来消除暂时元素。 Introduce Parameter Object (引入参数对象)和 Preserve Whole Object (保持对象完整)则可以把过长的参数变简洁。如果做完上述发现还是有太多参数和变量,可以使用杀手锏: Replace Method With Method Object (以函数对象取代函数)。条件和循环常常是提取的信号,可以使用 Decompose Conditional (分解条件式)来处理条件式。循环则可以提炼一个独立的函数。 三、 过长类( Large Class ) 这种可以使用 Extract Class (提炼类)提炼出内容有相关性的。如果类里面有数个变量有着一样的前缀或后缀,用 Extract Subclass (提炼子类)会比较简单。如果是 GUI 类,可以把数据和行为移到单独的 domain 对象中去,运用 Duplicate Observed Data (复制被监视数据)同步数据。...

July 29, 2013

《重构》学习笔记-重构原则

码农真得很辛苦,每天除了要下地编码之外,还需要挑灯夜战,学习专业知识,唉。不抱怨了,抱怨都是那些自暴自弃的人愤世嫉俗的。最近看《重构》一书,话说是一本很多人推荐看的好书,封面上还写着“从初级程序员到编程高手的秘籍”。好吧,我承认是初级程序员。所以我看了。 第一章 与其他书不同,第一章是一个例子。很多书,包括大学教材啊,技术教材都是以要讲的内容的定义和一些学习的重要意义之类的做第一章,而此书却给了一个系统的小部分代码来做重构的小例子。这样写的原因作者说了,不过对于我们这种应试教育下出生的人来说有点小小的不习惯。 public String statement() { double totalAmount = 0; //总消费余额 int frequentRenterPoints = 0; //常客积点 Enumeration rentals = _rentals.elements(); String result = "Rental Record for " + getName() + "\n"; while(rentals.hasMoreElements()) { double thisAmount = 0; //取得一笔租借记录 Rental each = (Rental) rentals.nextElement(); //determine amounts for each line switch(each.getDaysRented() > 2) { //取得影片租价格 case Movie.REGULAR: //普通片 thisAmount += 2; if (each.getDaysRented() > 2) thisAmount += (each.getDaysRented() - 2)*1.5; break; case Movie....

July 28, 2013