《Refactoring重构》由会员分享,可在线阅读,更多相关《Refactoring重构(25页珍藏版)》请在金锄头文库上搜索。
1、 Copyright 2002 Chinaxp. All rights reservedRefactoring(重构)黄海波 & 陶万山 With contribution by 劳晖www.chinaxp.org Copyright 2002 Chinaxp. All rights reserved什么是RefactoringRefactoring是对已经完成的代码进行改进的过程。在不对代码的外部行为进行改动的情况下,对代码内部的结构进行优化。Refactoring是严谨地对完成的代码进行清理的从而减少出错的一种方法。Refactoring的实质是对完成代码的设计进行改进。Refactori
2、ng是XP项目中每天的例行练习。Refactoring必须和Test-Driven Design and Development伴随进行。 Copyright 2002 Chinaxp. All rights reserved为什么要Refactoring?Refactoring的目的:1.改进软件的设计。程序员对代码所做的为了满足短期利益代码改动,或再没有完全清楚增个架构下的改动,都很容易是代码失去它的清晰结构,偏离需求或设计。而这些改动的积累很容易使代码偏离它原先设计的初衷而变得不可立即和无法维护。Refactoring则帮助重新组织代码,重新清晰的体现结构和进一步改进设计。 Copyri
3、ght 2002 Chinaxp. All rights reserved为什么要Refactoring?Refactoring的目的:2.提高代码质量,可维护性。容易理解的代码可以很容易的维护和做进一步的开发。即使对写这些代码的程序员本身,容易理解代码也可以帮助容易地做修改。程序代码也是文档。而代码首先是写给人看的,让后才是给计算机看的。 Copyright 2002 Chinaxp. All rights reserved为什么要Refactoring?Refactoring的目的:3.Refactoring帮助尽早的发现错误(Defects)Refactoring是一个code revi
4、ew和反馈的过程。在另一个时段重新审视自己或别人代码,可以更容易的发现问题和加深对代码的理解。Refactoring是一个良好的软件开发习惯。 Copyright 2002 Chinaxp. All rights reserved为什么要Refactoring?Refactoring的目的:. Refactoring可以提高提高开发速度Refactoring对设计和代码的改进,都可以有效的提高开发速度。好的设计和代码质量实体提高开发速度的关键。在一个有缺陷的设计和混乱代码基础上的开发,即使表面上进度较快,但本质是试延后对设计缺陷的发现和对错误的修改,也就是延后了开发风险,最终要在开发的后期付出
5、更多的时间和代价。 Copyright 2002 Chinaxp. All rights reservedRefactoring和传统流程在传统的流程中,分为设计和编码两个阶段。设计阶段(概要设计,详细设计)在编码阶段(先设计,后编码)之前。在传统的过程中,设计是一个很严谨和占用大量时间的阶段(比如一个项目6个月,4个月需求分析和设计),从设计阶段获得的几乎不会变化的详细设计文档,然后程序员对这些详细设计进行实现。现实:1.程序员需要改动代码来迎合需求的改变。2.程序员需要改动代码来能满足实际中性能的要求3.程序员没能理解和按设计实现4.程序员为了赶DeadLine对代码做的Quick-and
6、-Ugly修改5.结果:代码从设计偏离,设计变的过时 Copyright 2002 Chinaxp. All rights reservedRefactoring和敏捷流程Refactoring表现敏捷方法的设计哲学:软件开发是一个进化的过程。过去的传统的设计方法则专著于软件的设计阶段,力求整体设计的完美和详细,从而防止开发过程的后期出现没由预见到的情况而危害软件的质量和进度。敏捷方法则专注于当前的设计的完美,不过分考虑将来设计,依赖目前的好的设计和代码来应付将来可能出现的需求和情况。而Refactoring就是敏捷方法的实现其设计哲学的工具。 Copyright 2002 Chinaxp.
7、All rights reserved什么时候适合做Refactoring?在开始增加一个新的功能之前为了增加一个新的功能,程序员需要首先读懂现有的代码。在修复一个错误的时候为了修复一个Bug,程序员需要读懂现有的代码。在做Code Review的时候 Copyright 2002 Chinaxp. All rights reserved什么时候不适合做Refactoring?代码太混乱,设计完全错误与其Refactor,不如重新开始。明天是DeadLine永远不要做Last-Minute-Change。推迟Refactoring,但不可以忽略,即使进入Production的代码都正确的运行。
8、Refactoring的工作量显著的影响Estimate一个Task的estimate是天,如果为了Refactoring,需要更多的时间( 天或更多)。推迟Refactoring,同步可以忽略。可以把这个Refactoring作为一个新的Task,或者安排在Refactoring的Iteration中完成。 Copyright 2002 Chinaxp. All rights reservedRefactoring的流程读懂代码(包括测试例子代码)Refactoring运行所有的Unit Tests Copyright 2002 Chinaxp. All rights reservedBad
9、 SmellsDuplicated CodeLong MethodLarge ClassLong Parameter ListDivergent ChangeShortgun SurgeryFeature EnvyData ClumpsPrimitive ObsessionSwitch StatementsParallel Inheritance HierarchiesLazy ClassSpeculative GeneralityTemporary FieldMessage ChainsMiddle ManInappropriate IntimacyAlternative Classes w
10、ith Different InterfacesIncomplete Library ClassData ClassRefused BequestComments Copyright 2002 Chinaxp. All rights reservedRefactoring之Extract Methodsvoid printOwing() /print bannerSystem.out.println(“*”);System.out.println(“Banner”);System.out.println(“*”);/print detailsSystem.out.println (name:
11、+ _name); System.out.println (amount + getOutstanding(); void printOwing() printBanner(); printDetails(getOutstanding(); Void printBanner() /print banner System.out.println(“*”); System.out.println(“Banner”); System.out.println(“*”);void printDetails (double outstanding) System.out.println (name: +
12、_name); System.out.println (amount + outstanding); Copyright 2002 Chinaxp. All rights reservedRefactoring之Extract Methods一个复杂些和现实些的例子String name = request.getParameter(Name);if( name != null & name.length() 0 ).String age = request.getParameter(Age);if( age != null & age.length() 0 ).String name = r
13、equest.getParameter(Name);if( !isNullOrEmpty( name ) ) .String age = request.getParameter(Age);if( !isNullOrEmpty( age ) ) .private boolean isNullOrEmpty( final String string ) if( string != null & string.length() 0 ) return true; else return false; Copyright 2002 Chinaxp. All rights reservedRefacto
14、ring之Inline Method如果一个Method中的逻辑太简单,则把其中的代码移到调用它的代码,取消这个Method。int getRating() return (moreThanFiveLateDeliveries() ? 2 : 1; boolean moreThanFiveLateDeliveries() return _numberOfLateDeliveries 5; int getRating() return (_numberOfLateDeliveries 5) ? 2 : 1; Copyright 2002 Chinaxp. All rights reservedR
15、efactoring之Inline Tempdouble basePrice = anOrder.basePrice(); return (basePrice 1000) ;return (anOrder.basePrice() 1000) ; Copyright 2002 Chinaxp. All rights reservedRefactoring之Replace Temp with Query double basePrice = _quantity * _itemPrice; if (basePrice 1000) return basePrice * 0.95; else retur
16、n basePrice * 0.98; if (basePrice() 1000) return basePrice() * 0.95; else return basePrice() * 0.98; double basePrice() return _quantity * _itemPrice; Copyright 2002 Chinaxp. All rights reservedRefactoring之Introduce Explaining Variable if ( (platform.toUpperCase().indexOf(MAC) -1) & (browser.toUpper
17、Case().indexOf(IE) -1) & wasInitialized() & resize 0 ) / do something final boolean isMacOs = atform.toUpperCase().indexOf(MAC) -1; final boolean isIEBrowser = browser.toUpperCase().indexOf(IE) -1; final boolean wasResized = resize 0; if (isMacOs & isIEBrowser & wasInitialized() & wasResized) / do s
18、omething Copyright 2002 Chinaxp. All rights reservedRefactoring之Introduce Explaining Variabledouble temp = 2 * (_height + _width); System.out.println (temp); temp = _height * _width; System.out.println (temp); final double perimeter = 2 * (_height + _width);System.out.println (perimeter); final doub
19、le area = _height * _width; System.out.println (area); Copyright 2002 Chinaxp. All rights reservedRefactoring之Remove Assignments to Parametersint discount (int inputVal, int quantity, int yearToDate) if (inputVal 50) inputVal -= 2; int discount (int inputVal, int quantity, int yearToDate) int result
20、 = inputVal; if (inputVal 50) result -= 2; 如果参数是Object,容易误赋值。采用final来防止误用参数 Copyright 2002 Chinaxp. All rights reservedRefactoring之Replace Method with Method ObjectclassOrder.doubleprice()doubleprimaryBasePrice;doublesecondaryBasePrice;doubletertiaryBasePrice;/longcomputation;.或者可以采用static method Co
21、pyright 2002 Chinaxp. All rights reservedRefactoring之Replace Method with Method ObjectString foundPerson(String people) for (int i = 0; i people.length; i+) if (peoplei.equals (Don) return Don; if (peoplei.equals (John) return John; if (peoplei.equals (Kent) return Kent; return ; StringfoundPerson(S
22、tringpeople)Listcandidates=Arrays.asList(newStringDon,John,Kent);for(inti=0;ipeople.length;i+)if(candidates.contains(peoplei)returnpeoplei;return; Copyright 2002 Chinaxp. All rights reserved更多的R Copyright 2002 Chinaxp. All rights reservedXP中的Refactoring在XP的日常工作中,Refactoring通常在每个Pair完成Task后做Code Review的时候进行。Tips:不要在刚完成代码的后马上进行。不要在电脑屏幕前进行。Pair独自进行Review Copyright 2002 Chinaxp. All rights reservedReferenceRefactoring:Improve the design of existing code Martin FowlerR