《改善既有的代码-重构(ppt).ppt》由会员分享,可在线阅读,更多相关《改善既有的代码-重构(ppt).ppt(42页珍藏版)》请在三一办公上搜索。
1、重构技术,邱百超badqiu(a),讲解内容,重构介绍重构原则代码的坏味道重构技巧重构工具使用实例Q&A,名言,任何一个傻瓜都能写出计算机可以理解的程序,只有写出人类容易理解的程序才是优秀的程序员 Martin Fowler,什么是重构,Refactoring是对软件内部结构的一种调整,目的是在不改变外部行为的前提下,提高其可理解性,降低其修改成本。,为什么重构,改进软件的设计。程序员对代码所做的为了满足短期利益代码改动,或再没有完全清楚增个架构下的改动,都很容易是代码失去它的清晰结构,偏离需求或设计。而这些改动的积累很容易使代码偏离它原先设计的初衷而变得不可立即和无法维护。Refactori
2、ng则帮助重新组织代码,重新清晰的体现结构和进一步改进设计。,为什么重构,提高代码质量,更易被理解容易理解的代码可以很容易的维护和做进一步的开发。即使对写这些代码的程序员本身,容易理解代码也可以帮助容易地做修改。程序代码也是文档。而代码首先是写给人看的,让后才是给计算机看的。,为什么重构,Refactoring帮助尽早的发现错(Bugs)Refactoring是一个code review和反馈的过程。在另一个时段重新审视自己或别人代码,可以更容易的发现问题和加深对代码的理解。Refactoring是一个良好的软件开发习惯。,为什么重构,Refactoring可以提高开发速度Refactorin
3、g对设计和代码的改进,都可以有效的提高开发速度。好的设计和代码质量实体提高开发速度的关键。在一个有缺陷的设计和混乱代码基础上的开发,即使表面上进度较快,但本质是试延后对设计缺陷的发现和对错误的修改,也就是延后了开发风险,最终要在开发的后期付出更多的时间和代价。项目的维护成本远高于开发成本.,何时重构?,添加新功能时一并重构为了增加一个新的功能,程序员需要首先读懂现有的代码。修补错误时一并重构为了修复一个Bug,程序员需要读懂现有的代码。Code Review时一并重构,何时不该重构?,代码太混乱,设计完全错误。与其Refactor,不如重写。明天是DeadLine永远不要做Last-Minut
4、e-Change。推迟Refactoring,但不可以忽略,即使进入Production的代码都正确的运行。Refactoring的工作量显著的影响最后期限一个Task的计划是天,如果为了Refactoring,需要更多的时间(天或更多)。推迟Refactoring,同步可以忽略。可以把这个Refactoring作为一个新的Task,或者安排在Refactoring的Iteration中完成。,两顶帽子,重构与添加新功能添加新功能时,你不应该修改既有代码,只管添加新功能。重构时你就不能再添加功能,只管改进程序结构。此外你不应该添加任何测试(除非发现有先前遗漏的东西)两顶“帽子”可同时进行,一会
5、重构,一会添加新功能。,重构与设计,重构可以从很大程度上去扶助设计,通常情况下我们的设计不是能贯穿我们软件开发的全过程的,在这个过程中,我们的需求变更的可能性非常大,当需求变了,设计也得变,但是我们已有的实现怎么办?全部废除?显然不能!这时候就要依靠重构来解决这种矛盾。,重构与性能,关于重构,有一个常被提出的问题:它对程序的性能将造成怎样的影响?为了让软件易于理解,你常会作出一些使程序运行变慢的修改。这是个重要的问题。我并不赞成为了提高设计的纯洁性或把希望寄托于更快的硬件身上,而忽略了程序性能。已经有很多软件因为速度太慢而被用户拒绝,日益提高的机器速度亦只不过略微放宽了速度方面的限制而已。但是
6、,换个角度说,虽然重构必然会使软件运行更慢,但它也使软件的性能优化更易进行。关键在于自己的理解,当你拥有了重构的经验,你也就有能力在重构的基础上来改进程序的性能。,重构与模式,那么真正要实现重构时,我们有哪些具体的方法呢?可以这样说,重构的准则由很多条,见重构这本书。但它不是最终的标准,因为你要是完全按照它的标准来执行,那你也就等于不会重构,重构是一种武器,而真正运用武器的高手是没有武器胜有武器。只有根据实际的需要,凭借一定的思想,才能实现符合实际的重构,我们不能被一些固定的模式套牢了,这样你的程序会很僵化。究竟如何把握这个度,需要大家去总结。,重构与思想,要想实现一个好的重构,不是重构本身,
7、而是我们在写代码的时候,思想当中时刻有它的位置存在!非常重要!如果你本身就没想着要去重构,那么就是有再好的模式供你调用又怎么样?就是有了好的模式,你不能根据实际的需要去融会贯通,那你做出来的重构有意义么?,应用范围,代码重构网页重构设计重构.,Refactoring的流程,流程1读懂代码(包括测试例子代码)Refactoring运行所有的Unit Tests流程2读懂代码应用重构工具进行重构(如Eclipse),代码坏味道,重复的代码(Duplicated Code)过长的函数(Long Method)过大类(Large Class)过长的参数列(Long Parameter List)发散式
8、变化(Divergent Change)霰弹式修改(Shotgun Surgery)依恋情结(Feature Envy)数据泥团(Data Clumps)基本型别偏执(Primitive Obsession)Switch语句(Swtich Statements)平行继承体系(Parallel Inheritance Hierarchies)冗赘类(Lazy Class),夸夸其谈未来性(Speculative Generality)令人迷惑的暂时值域(Temporary Field)过度遇合的消息链(Message Chains)中间转手人(Middle Man)狎昵关系(Inappropri
9、ate Intimacy)异曲同工的类(Alternative Classes with Different Interfaces)不完善的程序库类(Incomplete Library Class)纯粹的数据类(Data Class)被拒绝的遗赠(Refused Bequest)过多的注释(Comments),重构技巧,重新组织你的函数在对象之间搬移特性重新组织数据简化条件表达式简化函数调用处理概括关系,Extract Methods(提炼函数1),String name=request.getParameter(Name);if(name!=null if(age!=null&age.le
10、ngth()0).,String name=request.getParameter(Name);if(!isNullOrEmpty(name).String age=request.getParameter(Age);if(!isNullOrEmpty(age).private boolean isNullOrEmpty(final String string)if(string!=null,Extract Methods(提炼函数:清除注释),void printOwing()/print bannerSystem.out.println(“*”);System.out.println(“
11、Banner”);System.out.println(“*”);/print detailsSystem.out.println(name:+_name);System.out.println(amount+getOutstanding();,void printOwing()printBanner();printDetails(getOutstanding();void printBanner()System.out.println(“*”);System.out.println(“Banner”);System.out.println(“*”);void printDetails(dou
12、ble outstanding)System.out.println(name:+_name);System.out.println(amount+outstanding);,Inline Method(将函数内联化),Inline Temp(将临时变量内联化),Replace Temp with Query(以查询取代临时变量),double basePrice=_quantity*_itemPrice;if(basePrice 1000)return basePrice*0.95;elsereturn basePrice*0.98;,if(basePrice()1000)return ba
13、sePrice()*0.95;elsereturn basePrice()*0.98;.double basePrice()return _quantity*_itemPrice;,Introduce Explaining Variable(引入解释性变量),boolean isMacOs=platform.toUpperCase().indexOf(MAC)-1;boolean isIEBrowser=browser.toUpperCase().indexOf(IE)-1;boolean wasResized=resize 0;if(isMacOs&isIEBrowser&wasInitia
14、lized()&wasResized)/do something,if(platform.toUpperCase().indexOf(MAC)-1)&(browser.toUpperCase().indexOf(IE)-1)&wasInitialized()&resize 0)/do something,Split Temporary Variable(剖解临时变量),double temp=2*(_height+_width);System.out.println(temp);temp=_height*_width;System.out.println(temp);,double perim
15、eter=2*(_height+_width);System.out.println(perimeter);double area=_height*_width;System.out.println(area);,Remove Assignments to Parameters(移除对参数的赋值),Replace Method with Method Object(以函数对象取代函数),Substitute Algorithm(替换算法),Replace Nested Conditional with Guard Clauses,double getPayAmount()double resu
16、lt;if(_isDead)result=deadAmount();else if(_isSeparated)result=separatedAmount();else if(_isRetired)result=retiredAmount();else result=normalPayAmount();return result;,double getPayAmount()if(_isDead)return deadAmount();if(_isSeparated)return separatedAmount();if(_isRetired)return retiredAmount();ret
17、urn normalPayAmount();,Split Loop-1,void printValues()double averageAge=0;double totalSalary=0;for(int i=0;i people.length;i+)averageAge+=peoplei.age;totalSalary+=peoplei.salary;averageAge=averageAge/people.length;System.out.println(averageAge);System.out.println(totalSalary);,void printValues()doub
18、le totalSalary=0;for(int i=0;i people.length;i+)totalSalary+=peoplei.salary;double averageAge=0;for(int i=0;i people.length;i+)averageAge+=peoplei.age;averageAge=averageAge/people.length;System.out.println(averageAge);System.out.println(totalSalary);,Split Loop-2,void printValues()System.out.println
19、(averageAge();System.out.println(totalSalary();private double averageAge()double result=0;for(int i=0;i people.length;i+)result+=peoplei.age;return result/people.length;private double totalSalary()double result=0;for(int i=0;i people.length;i+)result+=peoplei.salary;return result;,简化条件表达式,分解表达式,if(d
20、ate.before(SUMMER_START)|date.after(SUMMER_END)charge=quantity*_winterRate+_winterServiceCharge;elsecharge=quantity*_summerRate,if(notSummer(date)charge=winterCharge(quantity);elsecharge=summerCharge(quantity);,Remove Double Negative,if(!item.isNotFound()if(item.isFound(),在对象之间搬移特性,搬移函数(Move Method)搬移值域(Move Field)提炼类(Extract Class)将类内联化(Inline Class)隐藏委托关系(Hide Delegate)移除中间人(Remove Middle Man)引入外加函数(Introduce Foreign Method)引入本地扩展(Introduce Local Extension),重构工具,Java:EclipseC#:Visual Studio 插件:ReSharper C+:?,演示Eclipse重构的使用,参考,重构:改善即有代码的设计-Martin Fowler,Q&A,谢谢!,