重构zhang.docx
- 文档编号:2138764
- 上传时间:2022-10-27
- 格式:DOCX
- 页数:11
- 大小:23.64KB
重构zhang.docx
《重构zhang.docx》由会员分享,可在线阅读,更多相关《重构zhang.docx(11页珍藏版)》请在冰豆网上搜索。
重构zhang
重构(Refacting)
什么是重构?
代码写好之后,对它进行重新设计,但并不改变原有代
的逻辑(可以包括对方法名,变量名,常量的抽取和优化)
2、进行重构的时候,我们需要依赖测试,让它告诉我们是否引入了臭虫。
好的测试是重构的根本。
3、重构的节奏:
测试、小修改、测试、小修改、……
4、“两顶帽子”:
使用重构技术开发软件时,你把自己的时间分配给两种截然不同的行为:
“添加新功能”和“重构”。
添加新功能时,你不以你更改修改既有代码,只管添加新功能。
通过测试,你可以衡量自己的工作进度。
重构时你就不能再添加功能,只管改进程序结构。
此时你不应该添加任何测试(除非发现先前遗漏的任何东西),只在绝对必要时(用以处理接口变化)才修改测试。
5、何时重构?
三次法则,第一次做某件事时只管去做;第二次做类似的事会产生反感,但无论如何还是做了;第三次再做类似的事,你就应该重构。
1)添加功能时一并重构;2)修补错误时一并重构;3)复审代码时一并重构。
6、重构的难题:
数据库;修改接口;难以通过重构手法完成的设计改动。
7、何时不该重构?
重写而非重构的一个清楚讯号就是:
现有代码根本不能正常工作。
如果项目已近最后期限,你也应该避免重构。
-------------------------------------------------------------------------------
8、“臭味条款”—KentBeck
1)DuplicatedCode(重复代码)
2)LongMethod(过长函数)
3)LargeClass(过大类)
4)LongParameterList(过长参数列)
5)DivergentChange(发散式变化)——过耦合
6)ShotgunSurgery(散弹式修改)——过度的分散与过耦合相反
7)FeatureEnvy(依恋情节)——函数对某个class的兴趣高过对自己所处的hostclass的兴趣。
症状:
某个函数为了计算某值,从另一个对象那调用机会半打的取值函数。
疗法:
把这个函数移动到另一个地点。
8)DataClumps(数据泥团)——症状:
总是绑在一起出现的数据,很多地方可以看到相同的三或四笔数据项:
两个classes内的相同值域、许多函数签名式中的相同参数。
疗法:
把这些数据放进属于它们自己的对象中。
9)PrimitiveObsession(基本型别偏执)——两种数据:
结构型别和基本型别。
充分利用“对象”的价值,它模糊了横亘于基本数据和体积较大的classes之间界限。
例如以class表示字符串和日期。
10)SwitchStatements(switch惊悚现身)——面向对象程序的一个最明显特征就是:
少用switch语句。
多态的概念可以为此带来优雅的解决办法。
11)ParallelInheritanceHierarchies(平行继承体系)——每当为某个class增加一个subclass,必须也为另一个class相应增加一个subclass。
12)LazyClass(冗赘类)——如果一个class的所得不值其身价,他就应该消失。
13)SpeculativeGenerality(夸夸其谈未来性)——以为“总有一天需要做这事”并因而企图以各式各样的挂钩和特殊情况来处理一些非必要的事情。
14)TemporaryField(令人迷惑的暂时值域)——对象内某个instance变量仅为某种特定情势而设。
15)MessageChains(过度耦合的消息链)——用户向一个对象所求另一个对象,然后再向后者所求另一个对象,然后……这就是消息链。
16)MiddleMan(中间转手人)——某个class接口有一般的函数都委托给其他class,这样就是过度运用。
17)InappropriateIntimacy(狎昵关系)——两个类之间过分亲密
18)AlternativeClasseswithDifferentInterfaces(异曲同工的类)——两个函数做同样的事情,却有着不同的签名式。
19)IncompleteLibraryClass(不完美的程序库类)
20)DataClass(纯稚的数据类)——只含有一些值域以及访问值域的方法
21)RefusedBequest(被拒绝的遗赠)——子类应该集成弗雷的函数和数据。
但如果他们不想或不需要继承。
22)Comments(过多的注释)
23)如何学习?
1)随时挑一个目标;2)没有把握就停下来:
你无法证明自己所做的一切能够保持程序原本的语义,此时就应该停下来;学习原路返回;二重奏:
结对编程。
24)大规模的重构只会带来灾难。
25)永远不要忘记“两顶帽子”。
1.尽量消除重复的代码,将它们合而为一
根据重复的代码出现在不同的地方,分别采取不同的重构的策略:
在同一个Class的不同地方:
通过采用重构工具提供的ExtractMethod功能提炼出重复的代码,然后在这些地方调用上述提炼出方法。
在不同Subclasses中:
通过ExtractMethod提炼出重复的代码,然后通过PullUpMethod将该方法移动到上级的Superclass内。
在没有关系的Classes中:
通过对其中一个使用ExtractClass将重复的代码提炼到一个新类中,然后在另一个Class中调用生成的新类,消除重复的代码。
2.拆解过长的函数
过长的函数在我们的日常代码中经常可见,在C#中常通过#region#endregion区隔为不同的功能区域。
重构策略:
通过ExtractMethod将过长的函数按照功能的不同进行适当拆解为小的函数,并且给这些小函数一个好名字。
通过名字来了解函数提供的功能,提高代码的理解性。
3.拆解过大的类
过大的类也经常见到,特别是类中含有大量的成员变量。
重构策略:
通过ExtractClass将一些相关成员变量移植到新的Class中,如Employee类,一般会包含有联系方式的相关属性(电话,Mobile,地址,Zip等等),则可以将这些移植到新的EmployeeContact类中。
4.过长的参数列
过长的参数列的主要问题是难以理解,并且难以维护。
如果要增加新的参数或者删除某一参数,易造成参数前后不一致。
重构策略:
如果可以通过向已存在的对象查询获取参数,则可通过ReplaceParameterwithMethod,移除参数列,通过在函数内部向上述已存在的对象查询来获取参数。
如果参数列中若干参数是已存在对象的属性,则可通过PreserveWholeObject将这些参赛替换为一个完整对象,这样不仅提高代码的可读性,同时已易于代码今后的维护。
另外,还可以将若干不相关的参数,使用IntroduceParameterObject来创建一个新的参数类。
不过,我个人觉得如果这些情况过多的话,会产生很多莫名其妙的参数类了,反而降低代码的可读性。
5.DivergentChange(发散式变化)
现象:
当某个Class因为外部条件的变化或者客户提出新的功能要求等时,每次修改要求我们更新Class中不同的方法。
不过这种情况只有在事后才能觉察到,因为修改都是在事后发生的么(废话)。
重构策略:
将每次因同一条件变化,而需要同时修改的若干方法通过ExtractClass将它们提炼到一个新Class中。
实现目标是:
每次变化需要修改的方法都在单一的Class中,并且这个新的Class内所有的方法都应该与这个变化相关。
6.ShotgunSurgery(霰弹式修改)
现象:
当外部条件发生变化时,每次需要修改多个Class来适应这些变化,影响到很多地方。
就像霰弹一样,发散到多个地方。
重构策略:
使用MoveMethod和MoveField将Class中需要修改的方法及成员变量移植到同一个Class中。
如果没有合适的Class,则创建一个新Class。
实现目标是,将需要修改的地方集中到一个Class中进行处理。
比较DivergentChange(发散式变化)和ShotgunSurgery(霰弹式修改):
前者指一个Class受到多种外部变化的影响。
而后者指一种变化需要影响到多个Class需要修改。
都是需要修理的对象。
7.FeatureEnvy(依恋情结)
现象:
Class中某些方法“身在曹营心在汉”,没有安心使用Class中的成员变量,而需要大量访问另外Class中的成员变量。
这样就违反了对象技术的基本定义:
将数据和操作行为(方法)包装在一起。
重构策略:
使用MoveMethod将这些方法移动到对应的Class中,以化解其“相思之苦”,让其牵手。
8.DataClumps(数据泥团)
现象:
指一些相同数据项目(DataItems),如Class成员变量和方法中参数列表等,在多个Class中多次出现,并且这些数据项目有其内在的联系。
重构策略:
通过使用IntroduceParameterObject(创建新的参数对象取代这些参数)或PreserveWholeObject(使用已存在的对象取代这些参数),实现使用对象代替Class成员变量和方法中参数列表,清除数据泥团,使代码简洁,也提高维护性和易读性。
9.PrimitiveObsession(基本型偏执狂)
现象:
在Class中看到大量的基本型数据项目(DataItem),如Employee类中有大量的数据成员,Employee#,FirstName,MiddleName,LastName,Address,State,City,Street,Zip,OfficePhone,CellPhone,Email……等等。
重构策略:
使用ExtractClass(提炼新类)或PreserveWholeObject(使用已存在的对象取代这些参数),实现使用对象代替基本型数据项目(DataItem)。
如上述Employee类中就可分别提炼出EmployeeName和EmployeeContact两个新类。
10.SwitchStatements(Switch语句)
现象:
同样的Switch语句出现在不同的方法或不同的Class中,这样当需要增加新的CASE分支或者修改CASE分支内语句时,就必须找到所有的地方,然后进行修改。
这样,就比较麻烦了。
重构策略:
(1)首先采用ExtractMethod将Switch语句提炼到一个独立的函数。
(2)然后以MoveMethod搬移到需要多态性(Polymorphism)的Superclass里面或者是构建一个新的Superclass。
(3)进一步使用ReplaceTypeCodewithSubclasses或者ReplaceTypeCodewithState/Strategy。
这步就比较麻烦些,不过记住如下基本规则:
这里一般有3个Class分别为SourceClass、Superclass和Subclass。
SourceClass:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- zhang