重构-改善既有代码的设计总结
软件开发中的代码重构和优化

软件开发中的代码重构和优化代码重构和优化在软件开发中扮演着非常重要的角色。
代码重构指的是通过调整代码结构、优化算法、增加注释等手段,提高代码的可读性、可维护性、可扩展性和可重用性,而代码优化则是指通过优化算法、减少资源占用、提高代码执行效率等手段,使得程序更加高效。
代码重构的目的是使得代码更易于理解和维护。
当代码的结构杂乱、设计不合理时,理解代码的逻辑和意图会变得非常困难。
而重构可以通过重组代码结构、提取通用模块、优化命名等方式,使得代码变得更加清晰和易读。
通过重构,不仅可以加快开发效率,还能够降低维护成本。
在进行代码重构时,我们首先需要对代码进行分析和评估。
通过代码静态分析工具和性能分析工具,可以找出代码中的问题和瓶颈,找出需要重构的部分。
同时,对于一些重复的代码块,可以提取到函数或类中,以提高代码的可重用性。
在重构的过程中,我们还需要充分运用面向对象的设计原则,比如单一职责原则、开闭原则、依赖倒置原则等,使得代码更加符合良好的设计原则。
代码优化的目的是提高程序的性能和效率。
在进行代码优化时,我们首先需要对程序进行性能测试和分析,找出性能瓶颈。
然后针对性地进行优化,比如通过改进算法、减少内存消耗、优化数据库查询等手段,提高程序执行的效率和响应速度。
同时,还需要对程序进行多线程、异步等技术的应用,以充分利用计算资源。
代码优化需要综合考虑时间复杂度、空间复杂度、计算资源占用等因素,以达到最佳的优化效果。
代码重构和优化需要在合适的时机进行。
在项目初期,我们应该注重代码的可读性和易扩展性,通过良好的设计和结构,尽量避免代码重构和优化带来的额外工作量。
而在项目后期,随着代码规模的增大和功能的完善,我们可以逐渐进行代码重构和优化,以提高程序的性能和可维护性。
总之,代码重构和优化是软件开发中不可缺少的环节。
通过良好的代码重构和优化,可以提高代码的可读性、可维护性和可扩展性,提高程序的性能和效率,降低项目的维护成本。
重构-改善既有代码的设计:编写代码22宗罪(三)

重构-改善既有代码的设计:编写代码22宗罪(三)1 Duplicated Code重复代码不同的地方出现相同的程序结构:如果你在一个以上的地点看到相同的程序结构,那么可以肯定:设法将它们和而为一,程序会变得更好。
最常见的“重复代码”就是一个类内的两个函数含有相同的表达式。
另一种常见情况就是两个互为兄弟的子类内含有相同的表达式。
1)同一个类的2个函数含有相同的表达式,这时可以采用Extract Method(提炼函数)提炼出重复的代码,然后让这2个地点都调用被提炼出来的那段代码。
2)两个互为兄弟的子类内含相同表达式,只需对2个类都是用Extract Method(提炼函数),然后对被提炼出来的函数是用Pull Up Method (方法上移),将它推入超类。
如果代码之间只是类似,并非完全相同,那么就得运用Extract Method(提炼函数将相似部分和差异部分隔开,构成单独一个的函数。
然后你可能发现可以运用Form Template Method (塑造模板函数)获得一个Template Method设计模式。
如果有些函数以不同的算法做相同的事,你可以选择其中较清晰地一个,并是用Substitute Algorithm (替换算法)将其他函数的算法替换掉。
如果2个毫不相关的类出现重复代码,你应该考虑对其中一个运用Extract Class (提炼类),将重复代码提炼到一个独立类中,然后在另一个类内使用这个新类。
但是,重复代码所在的函数可能只应该属于某个类,另一个类只能调用它,抑或这个函数可能属于第三个类,而另2个类应该引用这第三个类。
你必须决定这个函数放在哪儿最合适,并确保它被安置后就不会再在其他任何地方出现。
函数中的代码行数原则上不要多于100行:我们遵循这样一条原则:每当感觉需要以注释开说明点什么的时候,我们就需要把说明的东西写进一个独立的函数中,并以其用途(而非实现手法)命名。
90%的场合里,要把函数变小,只需使用Extract Method(提炼函数) ,找到函数中适合集中在一起的部分,将它们提炼出来形成新函数。
重构-改善既有代码的设计 读书笔记

重构-改善既有代码的设计重构,第一个案例重构原则何为重构1. 名词:对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本2. 动词:使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构和性能优化形成对比都不改变组件的行为,只改变内部结构目的不同,重构的目的是使软件更容易被理解两顶帽子来回换,但是尽量不同时做添加新功能重构为何重构重构改进软件设计防止程序的设计逐渐腐败变质消除重复,让所有的事物和行为在代码中只表述一次,这正是软件设计的根本重构是软件更容易理解研究理解别人的代码的时候,也可以尝试重构,Ralph Johnson把这种“早期重构”描述为“擦掉窗户上的污垢,使你看得更远”重构帮助找到bug重构能帮助写出更健壮的代码最终,重构提高编程速度何时重构随时随地,不需要专门重构,重构是因为你想做别的什么事,而重构可以帮助你把那些事情做好三次法则第三次做类似的事情,就应该重构添加功能时重构修补错误是重构复审代码时重构重构的难题数据库修改接口难以通过重构的手法完成的改动何时不该重构既有代码太混乱,重构它还不如重新写一个来得简单重构之前,代码必须保证能够在大部分情况下正常运作,否则就重写可以先重构为封装良好的小型组件,然后就可以逐一对组件作出重构或者重建项目已经接近最后期限,避免重构如果最后你没有足够的时间,通常就表示你其实早就该进行重构重构与设计有了设计,我可以更快的思考,但是其中充满小漏洞极限编程的支持者极力支持使用重构取代预先设计,CRC卡重构与性能首先写出可调的软件,然后调整它以求获得足够的速度在性能优化阶段,首先要度量重构起源何处Ward CunninghamKent BeckRalph JohnsonBill OpdykeJohn BrantDon Roberts代码的坏味道重复代码(Duplicated Code)同一个类两个函数互为兄弟的子类只是类似,并非完全相同两个不相干的类出现重复Extract Method, Pull Up Method, Form Template Method, Template Method, Substitute Algorithm, Extract Class过长函数(Long method)间接层所能带来的全部利益--解释能力,共享能力,选择能力--都是由小型函数支持的每当感觉需要以注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途(而非实现手法)命名条件表达式和循环常常也是提炼的信号Extract Method, Replace Temp with Query, Introduce Parameter Object, Preserve Whole Object, Replace Method with Method Object, Decompose Conditional过大的类(Large Class)先确定客户端如何使用它们,然后运用Extract Interface为每一种使用方式提炼出一个接口。
重构,改善既有代码的设计--总结篇

重构,改善既有代码的设计--总结篇重构,改善既有代码的设计--第⼀章感悟⼀、书中经典句⼦1.重构之前,⾸先检查⾃⼰是否有⼀套可靠的测试机制。
这些测试必须有⾃我检验能⼒。
2.⾯对长长的函数,需要分解,代码块越⼩越好管理。
⼆、⾃⼰总结的句⼦1.修改长长的函数,找到变的参数和不变的参数,变的参数保留,不变的参数传⼊新函数。
2.重构的时候使⽤快捷键重构之后,需要检查⽅法⾥⾯的参数,参数如果是不变的值如a=1;,直接在⽅法⾥⾯去定义就⾏了,这样就省去了传值的过程,效率更⾼。
3.在重构函数之后,若函数的参数不属于当前类,并且函数中没使⽤当前类,需要把⽅法移动到参数所属的类去;如:A类⾥⾯的⽅法DoSomething(B b){b.getLabel(){}//do many things};需要移动到B类中去,4.重构之后需要检查下被重构的函数被多少个地⽅使⽤,保证⽆错5.对于接受⼀个⽅法返回值的参数如var a=B.getA();在这⾥a是完全没有必要的,可以直接把它给删除,在使⽤到a的地⽅替换为B.getA()6.为了使得⽅法看起来更加简洁,可以把⽅法中的变量和使⽤到变量的逻辑给抽取出来,形成⼀个⽅法,删除变量之后再使⽤到变量的地⽅⽤⽅法替代。
7.在switch语句,最好不要在另⼀个对象的基础上运⽤switch语句。
如果不得不使⽤,也应该在对象⾃⼰的数据上使⽤,⽽不是别⼈的数据上使⽤。
⽐如:A类中的⽅法MethodA()中的switch⾥⾯使⽤的都是B类对象引⽤的数据如:case B.NUMBER;则需要把该⽅法转移到B类中去,以减少没必要的引⽤。
重构,改善既有代码的设计--第⼆章感悟⼀、摘取章句1.改进设计的重要⽅向是消除重复代码。
2.⼒求代码容易理解3.早起重构被描述为“擦掉窗户上的污垢,使你看得更远。
”⼆、何时重构1.在给软件添加功能的时候重构2.修补错误时候重构:在重构中来找出系统的bug3.复审代码时候重构4.个⼈觉得在功能完成之后顺便重构会更好,因为在那个时候对代码还是很熟悉,还有可以在重构的时候去发现开发过程中遗留下来的bug重构,改善既有代码的设计--第四章感悟1.类应该包含它们的测试代码。
如何改善代码的设计 - 读《重构》读书笔记

一提词器文档如何改善代码的设计- 读《重构》这本书在五年前读了一次,当时读完觉得自己的水平上了一个台阶,然后开始在生产项目中实践。
当时的项目是一堆没人维护的遗留代码,每当要做个新功能时,我都会重构(更准确的说法是重写)下与新功能相关的逻辑,因为没有测试用例的支撑,经常会因为改出问题导致自己加班。
当时我从这种修改代码的过程中找到了编程的乐趣,那是一种畅快淋漓的感觉,重构后的代码似乎也成了体现我个人编程水平的象征。
随着写的代码越来越多,维护项目中的这些代码耗费了我太多的时间,想写新的功能时发现自己无法抽身出来。
我渐渐地感觉到代码成了一种负债,写的越多负债越多,我被自己的写的代码给困住了。
近期重读《重构》这本书,深感以前的我在重构方面至少犯了三个错误。
1重构前没写单元测试。
这样的重构很容易给自己挖坑,本想改个函数名,结果却捅了个蚂蜂窝。
每次重构都觉得不踏实,生怕改错了什么地方2添加新特性和重构同时进行,最后一起测试。
这样容易搞混原有功能与新特性。
一起测试意味着没有单独对重构的代码进行小范围的测试,让代码集成测试起来复杂3为了重构而重构。
很多时候重构成了一种强迫症,还美其名曰说自己有代码洁癖代码不仅仅是写完就好了,还需要维护。
维护说白了就是让代容易理解,让代码易于扩展修改成本低。
容易理解的代码可以很方便的交接出去给其它同事维护,难理解的代码就只能砸在自己手里。
一旦有缺陷或者新功能,修改成本低易扩展的代码可以让你很快就完成需求,收获同事的佩服,早点下班。
让代码易于维护就得借助重构来完成。
近些年在项目中逐渐被“剥夺”了写代码的权利,看代码和定位问题的时间超过了写代码,从工作中得到的乐趣少了很多。
希望重拾重构,从编程中找回那久违的畅快淋漓。
摘录关于重构1什么是重构?○不改变软件可观察行为的前提下,提高可理解,降低软件维护成本2为什么重构?○可以改进软件设计。
代码被阅读和被修改的次数远远多于它被编写的次数○可以使软件更容易理解。
重构改善既有代码的设计

重构改善既有代码的设计最近接⼿⼀个项⽬,源代码的架构和许多设计都有坏的味道。
想要重构,但是⾃⼰并没有⾜够的底⽓.⼀、重构的纠结:(1)现有代码可⽤,你重构后是否会⽐现在更有效率;(2)项⽬进度⽐较紧,你是否要抽出时间做这种没有KPI的⼯作;(3)你重构后,别⼈需要重新阅读你的源代码,给同事带来了重新学习代码的⼯作量;(4)项⽬是否能够持续,如果没有需求,不⽤了,你还重构什么?(5)你是否要在这个公司待很久,等重构完后,你可能都不在了。
⼆、如果不重构,确实会给开发带来很⼤困难:原代码就像是⼀个打满了补丁的棉袄,它可以保暖,但是很难定位到哪⾥漏风,即使定位到了,不过是新打些补丁,但是缝缝补补的⼯作可能没有尽头。
(1)修改很耗精⼒;(2)BUG花样迭出(3)扩展性差,持续开发跟进需求很难;(4)应变能⼒差,牵⼀发动全⾝。
重构或不重构,这是个问题,直到看了《重构改善既有代码的设计》,给了我很⼤启发。
粗略看了⼀遍,道理明⽩了⼀些,我之前的想法应该叫做重写⽽不是重构。
重构是逐步改善的过程,是重写与打补丁的中间选项。
当然看完书之后,我还是选择了重写,因为项⽬还不是很⼤,重写做起来⼯作量更⼩⼀些。
重构的核⼼还是使代码尽量遵循设计模式的六⼤原则:(1)单⼀职责原则(2)⾥⽒替换原则(3)依赖倒置原则(4)接⼝隔离原则(5)迪⽶特法则(6)开闭原则重构中⽤到的⽅法,是写代码过程中很好的参照。
⽅法都写在2-13章的⽬录⾥了,意思⽐较明显,闲来的时候看看,也⼤有裨益。
第2章重构原则2.1何谓重构532.2为何重构552.3何时重构572.4怎么对经理说602.5重构的难题622.6重构与设计662.7重构与性能692.8重构起源何处71第3章代码的坏味道3.1 DuplicatedCode(重复代码)763.2 LongMethod(过长函数)763.3 LargeClass(过⼤的类)783.4 LongParameterList(过长参数列)783.5 DivergentChange(发散式变化)793.6 ShotgunSurgery(霰弹式修改)803.7 FeatureEnvy(依恋情结)803.8 DataClumps(数据泥团)813.9 PrimitiveObsession(基本类型偏执)813.10 SwitchStatements(switch惊悚现⾝)823.11 ParallelInheritanceHierarchies(平⾏继承体系)833.12 LazyClass(冗赘类)833.13 SpeculativeGenerality(夸夸其谈未来性)833.14 TemporaryField(令⼈迷惑的暂时字段)843.15 MessageChains(过度耦合的消息链)843.16 MiddleMan(中间⼈)853.17 InappropriateIntimacy(狎昵关系)853.18 AlternativeClasseswithDifferentInterfaces(异曲同⼯的类)853.19 IncompleteLibraryClass(不完美的库类)863.20 DataClass(纯稚的数据类)863.21 RefusedBequest(被拒绝的遗赠)873.22 Comments(过多的注释)87第4章构筑测试体系4.1⾃测试代码的价值894.2 JUnit测试框架914.3添加更多测试97第5章重构列表5.1重构的记录格式1035.2寻找引⽤点1055.3这些重构⼿法有多成熟106第6章重新组织函数6.1 ExtractMethod(提炼函数)1106.2 InlineMethod(内联函数)1176.3 InlineTemp(内联临时变量)1196.4 ReplaceTempwithQuery(以查询取代临时变量)1206.5 IntroduceExplainingVariable(引⼊解释性变量)1246.6 SplitTemporaryVariable(分解临时变量)1286.7 RemoveAssignmentstoParameters(移除对参数的赋值)1316.8 ReplaceMethodwithMethodObject(以函数对象取代函数)1356.9 SubstituteAlgorithm(替换算法)139第7章在对象之间搬移特性7.1 MoveMethod(搬移函数)1427.2 MoveField(搬移字段)1467.3 ExtractClass(提炼类)1497.4 InlineClass(将类内联化)1547.5 HideDelegate(隐藏“委托关系”)1577.6 RemoveMiddleMan(移除中间⼈)1607.7 IntroduceForeignMethod(引⼊外加函数)1627.8 IntroduceLocalExtension(引⼊本地扩展)164第8章重新组织数据8.1 SelfEncapsulateField(⾃封装字段)1718.2 ReplaceDataValuewithObject(以对象取代数据值)1758.3 ChangeValuetoReference(将值对象改为引⽤对象)1798.4 ChangeReferencetoValue(将引⽤对象改为值对象)1838.5 ReplaceArraywithObject(以对象取代数组)1868.6 DuplicateObservedData(复制“被监视数据”)1898.7 ChangeUnidirectionalAssociationtoBidirectional(将单向关联改为双向关联)197 8.8 ChangeBidirectionalAssociationtoUnidirectional(将双向关联改为单向关联)200 8.9 ReplaceMagicNumberwithSymbolicConstant(以字⾯常量取代魔法数)2048.10 EncapsulateField(封装字段)2068.11 EncapsulateCollection(封装集合)2088.12 ReplaceRecordwithDataClass(以数据类取代记录)2178.13 ReplaceTypeCodewithClass(以类取代类型码)2188.14 ReplaceTypeCodewithSubclasses(以⼦类取代类型码)2238.15 ReplaceTypeCodewithState/Strategy(以State/Strategy取代类型码)2278.16 ReplaceSubclasswithFields(以字段取代⼦类)232第9章简化条件表达式9.1 DecomposeConditional(分解条件表达式)2389.2 ConsolidateConditionalExpression(合并条件表达式)2409.3 ConsolidateDuplicateConditionalFragments(合并重复的条件⽚段)2439.4 RemoveControlFlag(移除控制标记)2459.5 ReplaceNestedConditionalwithGuardClauses(以卫语句取代嵌套条件表达式)250 9.6 ReplaceConditionalwithPolymorphism(以多态取代条件表达式)2559.7 IntroduceNullObject(引⼊Null对象)2609.8 IntroduceAssertion(引⼊断⾔)267第10章简化函数调⽤10.1 RenameMethod(函数改名)27310.2 AddParameter(添加参数)27510.3 RemoveParameter(移除参数)27710.4 SeparateQueryfromModifier(将查询函数和修改函数分离)27910.5 ParameterizeMethod(令函数携带参数)28310.6 ReplaceParameterwithExplicitMethods(以明确函数取代参数)28510.7 PreserveWholeObject(保持对象完整)28810.8 ReplaceParameterwithMethods(以函数取代参数)29210.9 IntroduceParameterObject(引⼊参数对象)29510.10 RemoveSettingMethod(移除设值函数)30010.11 HideMethod(隐藏函数)30310.12 ReplaceConstructorwithFactoryMethod(以⼯⼚函数取代构造函数)30410.13 EncapsulateDowncast(封装向下转型)30810.14 ReplaceErrorCodewithException(以异常取代错误码)31010.15 ReplaceExceptionwithTest(以测试取代异常)315第11章处理概括关系11.1 PullUpField(字段上移)32011.2 PullUpMethod(函数上移)32211.3 PullUpConstructorBody(构造函数本体上移)32511.4 PushDownMethod(函数下移)32811.5 PushDownField(字段下移)32911.6 ExtractSubclass(提炼⼦类)33011.7 Extract Superclass (提炼超类) 33611.8 Extract Interface (提炼接⼝) 34111.9 Collapse Hierarchy (折叠继承体系)34411.10 FormTemplateMethod(塑造模板函数)34511.11 Replace Inheritance with Delegation(以委托取代继承)35211.12 Replace Delegation with Inheritance (以继承取代委托)355第12章⼤型重构12.1 Tease Apart Inheritance (梳理并分解继承体系)36212.2 Convert Procedural Design to Objects (将过程化设计转化为对象设计)368 12.3 Separate Domain from Presentation (将领域和表述/显⽰分离)37012.4 Extract Hierarchy (提炼继承体系)375。
代码重构与优化改善既有代码的质量与可读性

代码重构与优化改善既有代码的质量与可读性代码重构与优化:改善既有代码的质量与可读性代码重构与优化是软件开发过程中非常重要的环节,它旨在改善既有代码的质量和可读性,从而提高软件的可维护性和可扩展性。
本文将探讨代码重构与优化的概念、目的、方法以及效益等方面内容,帮助读者更好地理解并应用于实际开发中。
一、概念和目的代码重构是指在不改变代码外在行为的情况下,通过调整代码内部结构,使得代码更易于理解、修改和扩展的过程。
它是一种对代码进行有目标性的修改的过程,以消除代码中的重复、提取通用的模块或函数、简化复杂的逻辑结构等方式来改进代码质量。
而代码优化则是为了提高代码的执行效率而进行的修改,以减少程序运行的时间或空间消耗。
代码重构与优化的目的在于改善代码的可维护性、可读性和可扩展性。
良好的代码结构和清晰的代码逻辑能够使得代码更易于理解和修改,减少出错的可能性。
而对于代码的优化,则可以提高程序的执行效率,降低系统资源的占用,提升用户体验。
二、常用的代码重构技术1. 提取函数:将重复的代码块提取成函数,减少代码冗余。
2. 合并函数:将功能相似的函数合并成一个,减少函数数量和复杂度。
3. 重命名变量和函数:使用有意义的命名,提高代码的可读性。
4. 删除冗余代码:删除未使用的变量、函数和注释等冗余代码,减少代码的臃肿。
5. 拆分长函数:将过长的函数拆分成多个小函数,提高代码的可读性和可维护性。
6. 消除魔术数字:将代码中的魔术数字提取为常量或变量,增加代码的可维护性。
7. 使用设计模式:应用合适的设计模式来改善代码结构,提高代码的可读性和可扩展性。
8. 更新注释:及时更新代码注释,保持代码文档的准确性和完整性。
三、代码优化的常用策略1. 选择合适的数据结构和算法:根据具体问题的特点,选择最合适的数据结构和算法,以提高程序的运行效率。
2. 减少循环的次数和嵌套层次:避免不必要的循环和嵌套,以减少程序执行的时间消耗。
3. 使用缓存:对频繁访问的变量或计算结果进行缓存,减少系统资源的占用。
《重构—改善既有代码设计》——第二章重构原则——学习笔记

《重构—改善既有代码设计》——第⼆章重构原则——学习笔记1:什么是重构?重构是⼀个过程:在不改变代码外在⾏为的前提下,对代码做出修改,以改进程序内部结构。
本质上说,重构就是【在代码写好之后改进它的设计】2:为什么要对项⽬进⾏重构呢?重构对软件开发有什么好处,为什么要重构呢,打个贴切的⽐⽅:我平时⽐较懒散,屋⼦⾥⾯的东西都是随⼿乱放,时间长了,屋⼦⾥⾯就乱七⼋糟了。
有时候到了⾃⼰也忍⽆可忍的时候,我就要⼤动⼲⼽了,把该放哪⼉的东西都整理到哪⼉,该扔掉的东西全部扔掉。
⼀个项⽬也是如此,有时候可能是设计不到位;有时候可能是经过多⼈的修改,代码凌乱不堪;甚⾄有些地⽅都是在堆砌代码;可能有些新⼿写的代码或是⾃⼰以前写的代码,让你看不下去了…。
于是你挥动⼤斧对项⽬进⾏劈砍⼀番。
重构的好处⽤⾃⼰的话简单的概括为: 改善软件设计、提⾼代码质量、提⾼程序可读性、减少错误、使以后功能扩展更容易。
【重构改进软件设计】⼤家可能都有亲⾝体会,⼀个项⽬的代码质量往往有可能会随着时间的推移变得越来糟糕,代码愈来愈雍窘,越来越难以理解它的本意。
添加新功能越来越难。
这⾥⾯的原因是多⽅⾯的,重构可以减少代码量,使以后的维护,开发更⽅便【重构使软件更容易理解】重构整理过后的代码,确实让你更容易理解【重构有助于你找到BUG】重构的时候,你必须去阅读代码,分析、理解逻辑,这样你就很可能发现⼀些逻辑或是简单的错误。
⽽且重构的时候都要做⼀些必须的测试,也是有助于找到⼀些潜藏的错误的。
【重构有助于提⾼你的编程速度】这个没有亲⾝体验过的⼈,估计只有⼀个形象的感受。
我曾经参与到⼀个项⽬⾥⾯,那个项⽬简直到了你恨不得推翻它重写的地步。
函数雍窘超长;代码到处堆砌;没⽤分层;逻辑耦合;通篇没啥注释。
有时候你为了了解这个函数的功能,都要花费⼤量的时间和功夫。
⽤同事的话说:“对这些代码望⽽⽣畏”。
你想这样⼀个代码质量低劣的项⽬,做功能扩展、维护不拖累你的编程速度才怪。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
重构-改善既有代码的设计总结(JAVA)
重构目的:
1.改变既有代码的架构,使架构更加清晰。
2.提取相同的代码,提高代码的复用率,减小项目本身的大小。
3.改善代码的逻辑,使代码更加精炼和高效,进而纵向效率。
重构注意事项
1.测试,一定要编写单元测试(JUnit),修改任何一个变量,方法,类或者接口都必须需要测试。
2.编写代码之前,一定要整理好重构的思路和步骤,按照思路和步骤编写代码和测试相应的代码。
3.动机,确定自己重构的动机,重构完成后检查重构的效果(是否达到预期的效果)。
重构原则:
1:DRY(Don't repeat yourself)
即不要写重复的代码,而是用“abstraction”类来抽象公有的东西。
如果你需要多次用到一个硬编码值,那么可以设为公共常量;如果你要在两个以上的地方使用一个代码块,那么可以将它设为一个独立的方法。
SOLID设计原则的优点是易于维护,但要注意,不要滥用,duplicate 不是针对代码,而是针对功能。
这意味着,即使用公共代码来验证OrderID和SSN,二者也不会是相同的。
使用公共代码来实现两个不同的功能,其实就是近似地把这两个功能永远捆绑到了一起,如果OrderID改变了其格式,SSN验证代码也会中断。
因此要慎用这种组合,不要随意捆绑类似但不相关的功能。
2:封装变化
在软件领域中唯一不变的就是“Change”,因此封装你认为或猜测未来将发生变化的代码。
OOPS设计模式的优点在于易于测试和维护封装的代码。
如果你使用Java编码,可以默认私有化变量和方法,并逐步增加访问权限,比如从private 到protected和not public.有几种Java设计模式也使用封装,比如Factory设计模式是封装“对象创建”,其灵活性使得之后引进新代码不会对现有的代码造成影响。
3:开闭原则
即对扩展开放,对修改关闭。
这是另一种非常棒的设计原则,可以防止其他人更改已经测试好的代码。
理论上,可以在不修改原有的模块的基础上,扩展功能。
这也是开闭原则的宗旨。
4:单一职责原则
类被修改的几率很大,因此应该专注于单一的功能。
如果你把多个功能放在同一个类中,功能之间就形成了关联,改变其中一个功能,有可能中止另一个功
能,这时就需要新一轮的测试来避免可能出现的问题。
5:依赖注入或倒置原则
这个设计原则的亮点在于任何被DI框架注入的类很容易用mock对象进行测试和维护,因为对象创建代码集中在框架中,客户端代码也不混乱。
有很多方式可以实现依赖倒置,比如像AspectJ等的AOP(Aspect Oriented programming)框架使用的字节码技术,或Spring框架使用的代理等。
6:优先利用组合而非继承
如果可能的话,优先利用组合而不是继承。
一些人可能会质疑,但我发现,组合比继承灵活得多。
组合允许在运行期间通过设置类的属性来改变类的行为,也可以通过使用接口来组合一个类,它提供了更高的灵活性,并可以随时实现。
《Effective Java》也推荐此原则。
7:里氏代换原则(LSP)
根据该原则,子类必须能够替换掉它们的基类,也就是说使用基类的方法或函数能够顺利地引用子类对象。
LSP原则与单一职责原则和接口分离原则密切相关,如果一个类比子类具备更多功能,很有可能某些功能会失效,这就违反了LSP原则。
为了遵循该设计原则,派生类或子类必须增强功能。
8:接口分离原则
采用多个与特定客户类有关的接口比采用一个通用的涵盖多个业务方法的接口要好。
设计接口很棘手,因为一旦释放接口,你就无法在不中断执行的情况下改变它。
在Java中,该原则的另一个优势在于,在任何类使用接口之前,接口不利于实现所有的方法,所以单一的功能意味着更少的实现方法。
9:针对接口编程,而不是针对实现编程
该原则可以使代码更加灵活,以便可以在任何接口实现中使用。
因此,在Java 中最好使用变量接口类型、方法返回类型、方法参数类型等。
《Effective Java》和《head first design pattern》书中也有提到。
10:委托原则
该原则最典型的例子是Java中的equals() 和hashCode() 方法。
为了平等地比较两个对象,我们用类本身而不是客户端类来做比较。
这个设计原则的好处是没有重复的代码,而且很容易对其进行修改。
总之,希望这些面向对象的设计原则能帮助你写出更灵活更好的代码。
理论是第一步,更重要的是需要开发者在实践中去运用和体会。
重构方法措施:
1.添加参数。
2.将双向关联改成单向。
3.将单向关联改成双向。
4.将引用对象改成值对象。
5.将值对象改成引用对象。
6.合并继承层次。
7.合并条件语句。
8.分解条件语句。
9.合并重复的条件判断。
10.用多态代替条件语句。
11.用守卫语句代替嵌套条件语句。
12.将过程式设计转换成面向对象。
13.重复被观察的数据。
14.封装集合。
15.封装向下转型。
16.封装字段。
17.移动字段。
18.上移字段。
19.下移字段。
20.自封字段。
21.提取类。
22.提取继承层次。
23.提取接口。
24.提取方法。
25.移动方法。
26.上移方法。
27.下移方法。
28.提取子类。
29.提取超类。
30.形成模板方法。
31.隐藏委托类。
32.隐藏方法。
33.内联类。
34.内联方法。
35.内联临时变量。
36.引入断言。
37.引入解释性变量。
38.引入外加方法。
39.引入本地扩展类。
40.引入null对象。
41.引入参数对象。
42.参数化方法。
43.保持对象完整。
44.上移构造器主体。
45.去除参数赋值。
46.去除控制标志。
47.去除中间人。
48.去除参数。
49.去除设置方法。
50.重命名参数。
51.用对象代替数组。
52.用工厂方法代替构造器。
53.用对象代替数据值。
54.用继承代替委托。
55.用异常代替错误码。
56.用测试代替异常。
57.用委托代替继承。
58.用字面常量代替魔数。
59.用方法对象代替方法。
60.用显示方法代替参数。
61.用方法代替参数。
62.用数据类代替参数。
63.用字段代替子类。
64.用查询方法代替临时变量。
65.用类代替类型码。
66.用State/Strategy代替类型码。
67.用子类代替类型码。
68.将领域逻辑与表现分离。
69.将查询方法和修改方法分离。
70.分离临时变量。
71.替换方法。
72.分解继承层次。
Eclipse重构
作用域功能快捷键
全局撤销重构Alt+Shift+Z
全局抽取方法Alt+Shift+M
全局抽取局部变量Alt+Shift+L
全局内联Alt+Shift+I
全局移动Alt+Shift+V
全局重命名Alt+Shift+R
全局重做Alt+Shift+Y。