Code Smells and Refactoring - Asistente
-
Upload
ricardo-ighighi -
Category
Documents
-
view
48 -
download
0
description
Transcript of Code Smells and Refactoring - Asistente
-
Code Smells
and
Refactoring
-
Technical Debt
A. "Ward" Cunningham (creador de la primera Wiki y uno de los pioneros en Design Pattern y
Extreme Programming) encontr conexiones entre el software y las finanzas.
Puedes encontrar esas conexiones? :
Software Dejar o aplazar el diseo. (Technical Debt) Mejorar el diseo, preservando el comportamiento de la aplicacin. (Refactoring) Desarrollo lento debido a problemas en el diseo. (Code Smells)
Finanzas Pagar los intereses. Tomar dinero prestado. Amortizar la deuda original.
B. Hay buenas razones para tomar una deuda financiera.
Nombra al menos 2 buenas razones o circunstancias para tomar una deuda tcnica.
C. Si utilizas una tarjeta de crdito. Cul es la mejor manera de pagar la deuda?
a) Pagar todo el balance en el mes.
b) Pagar cada mes una parte considerable hasta completar toda la deuda.
c) Esperar varios meses hasta pagar.
D. Acumular deuda financiera lleva a la bancarrota.
Nombra al menos 2 problemas que trae acumular deuda tcnica.
-
Code Smells
Long Method Los mtodos cortos son ms fciles de leer, entender y atacar. Refactoriza
mtodos largos en varios ms cortos de ser posible.
Dead Code Eliminar sin piedad el cdigo que no est siendo utilizado. Es por eso que
tenemos Source Control Systems.
Long Parameter List La mayor cantidad de parmetros que tiene un mtodo origina una mayor
complejidad. Limita el nmero de parmetros que necesitas en un mtodo, o usa
un objeto que combine los parmetros.
Duplicated code Cdigo duplicado es la perdicin en el desarrollo de software. Remueve el cdigo
duplicado apenas sea posible. Tambin deberas estar atento a casos sutiles de
duplicacin.
Data Clumps Si siempre ves los mismos datos dando vueltas juntos, quizs deberan
pertenecer a una sola unidad. Considera juntar datos relacionados en una clase.
Primitive Obsession No utilices variables de tipos de datos primitivos como un pobre sustituto de una
clase. Si tu tipo de dato es lo suficientemente complejo, escribe una clase que lo
represente.
Refused Bequest Si heredas de una clase, pero nunca usas ninguna de las funcionalidades
heredadas, en realidad deberas estar usando herencia?
Switch Statements Este smell existe cuando el mismo switch (o cadena de "ifelse ifelse if") est duplicado a lo largo del sistema. Esta duplicacin revela la falta de orientacin a
objetos y pierde la oportunidad de confiar en la elegancia del polimorfismo.
Shotgun Surgery Si un cambio en una clase requiere varios cambios en cascada en clases
relacionadas, considere refactorizar de manera que el cambio este limitado a una
sola clase.
Lazy Class
Las clases deben tener su propio peso. Cada clase adicional incrementa la
complejidad del proyecto. Si tienes una clase que no est haciendo lo suficiente
para sustentarse por ella misma, puede ser absorbida o combinada en otra
clase?
Indecent Exposure Ten cuidado con las clases que innecesariamente exponen su interior. Refactoriza
agresivamente las clases para minimizar la parte pblica. Debes tener una razn
para cada item que haces pblico. Sino lo tienes, escndelo.
Feature Envy Mtodos que hacen uso intensivo de otra clase quizs pertenezcan a otra clase.
Considera mover este mtodo a la clase a la cual le tiene envidia.
Speculative Generality Escribe cdigo para resolver los problemas que conoces hoy y preocpate de los
problemas de maana cuando se materialicen. Todo el mundo se pierde en el
what if. You Aren't Gonna Need It" (Principio YAGNI)
Divergent Change
Si, a travs del tiempo, realizas cambios a una clase que toca completamente
diferentes partes de la clase, quizs contenga mucha funcionalidad no
relacionada. Considera aislar las partes que cambian en otra clase.
Comments
Hay una delgada lnea entre los comentarios que iluminan y los que oscurecen.
Los comentarios son innecesarios? Explican el por qu y no el qu? Puedes refactorizar el cdigo de forma que los comentarios no sean requeridos? Y
recuerda, ests escribiendo comentarios para personas y no mquinas.
www.codinghorror.com/blog/2006/05/code-smells.html
-
Atributos de Calidad
Claridad
Cualquier persona puede escribir cdigo que una mquina pueda entender, pero solo un buen programador escribe cdigo que otra persona entienda.
Libre de Duplicados
Un programa debe expresar cada idea una vez y solo una vez. El cdigo no debe ser idntico a otro ni expresar el mismo comportamiento.
Poco Acoplamiento
Componentes poco acoplados pueden cambiarse sin impactar otros componentes.
Encapsulamiento El cdigo est debidamente encapsulado y no expone datos o comportamiento que debera ser invisible.
Simple
El cdigo refleja el camino ms corto a la solucin y no agrega complejidad de manera innecesaria. El cdigo simple es ms fcil de mantener y evolucionar.
Alta Cohesin Mtodos hacen solo una nica cosa y las clases solo tiene una nica responsabilidad.
-
Extract Method
You have a code fragment that can be grouped together. Turn the fragment into a method whose name explains the purpose of the method.
void printOwing() {
printBanner();
//print details
System.out.println ("name: " + _name);
System.out.println ("amount " + getOutstanding());
}
void printOwing() {
printBanner();
printDetails(getOutstanding());
}
void printDetails (double outstanding) {
System.out.println ("name: " + _name);
System.out.println ("amount " + outstanding);
}
Extract Class
You have one class doing work that should be done by two. Create a new class and move the relevant fields and methods from the old class into the new class.
-
Extract Sub Class
A class has features that are used only in some instances. Create a subclass for that subset of features.
Introduce Explaining Variable
You have a complicated expression. Put the result of the expression, or parts of the expression, in a temporary variable with a name that explains the purpose.
if ((platform.toUpperCase().indexOf("MAC") > -1) &&
(browser.toUpperCase().indexOf("IE") > -1) &&
wasInitialized() && resize > 0 ) {
// do something
}
final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
final boolean wasResized = resize > 0;
if (isMacOs && isIEBrowser && wasInitialized() && wasResized) {
// do something
}
-
Collapse Hierarchy
A superclass and subclass are not very different. Merge them together.
Introduce Parameter Object
You have a group of parameters that naturally go together. Replace them with an object.
Rename
The name of a method does not reveal its purpose. Change the name of the method.
-
Replace Conditional with Polymorphism
You have a conditional that chooses different behavior depending on the type of an object. Move each leg of the conditional to an overriding method in a subclass. Make the original method abstract.
double getSpeed() {
switch (_type) {
case EUROPEAN:
return getBaseSpeed();
case AFRICAN:
return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts;
case NORWEGIAN_BLUE:
return (_isNailed) ? 0 : getBaseSpeed(_voltage);
}
throw new RuntimeException ("Should be unreachable");
}
Encapsulate Collection
A method returns a collection. Make it return a read-only view and provide add/remove methods.
-
Push Down Field/Method
Behavior on a superclass is relevant only for some of its subclasses. Move it to those subclasses.
Pull Up Field/Method
You have methods with identical results on subclasses. Move them to the superclass.
Inline Class
A class isn't doing very much. Move all its features into another class and delete it.
-
Inline Method
A methods body is just as clear as its name. Put the methods body into the body of its callers and remove the method.
int getRating() {
return (moreThanFiveLateDeliveries()) ? 2 : 1;
}
boolean moreThanFiveLateDeliveries() {
return _numberOfLateDeliveries > 5;
}
int getRating() {
return (_numberOfLateDeliveries > 5) ? 2 : 1;
}
Inline Temp
You have a temp that is assigned to once with a simple expression, and the temp is getting in the way of other refactorings. Replace all references to that temp with the expression.
double basePrice = anOrder.basePrice();
return (basePrice > 1000)
return (anOrder.basePrice() > 1000)
Move Method
A method is, or will be, using or used by more features of another class than the class on which it is defined. Create a new method with a similar body in the class it uses most. Either turn the old method into a simple delegation, or remove
it altogether.
-
Code Smell Donde se Encuentra (Class.Method) Refactoring
Long Method
Primitive Obsession
Long Parameter List
Dataclums
Switch Statements
Refused Bequest
Divergent Change
Lazy Class
Duplicate Code
Speculative Generality
Feature Envy
Indecent Exposure (Inappropriate Intimacy)
Comments
-
MANUAL REFACTORINGS
Extract Method Step by Step
Create a new method, and name it after the intention of the method (name it by what it
does, not by how it does it).
If the code you want to extract is very simple, such as a single message or function call, you should
extract it if the name of the new method will reveal the intention of the code in a better way. If you
cant come up with a more meaningful name, dont extract the code.
Copy the extracted code from the source method into the new target method.
Scan the extracted code for references to any variables that are local in scope to the source
method. These are local variables and parameters to the method.
See whether any temporary variables are used only within this extracted code. If so, declare
them in the target method as temporary variables.
Look to see whether any of these local-scope variables are modified by the extracted code. If
one variable is modified, see whether you can treat the extracted code as a query and assign
the result to the variable concerned.
Pass into the target method as parameters local-scope variables that are read from the
extracted code.
Compile when you have dealt with all the locally-scoped variables.
Replace the extracted code in the source method with a call to the target method.
If you have moved any temporary variables over to the target method, look to see whether they
were declared outside of the extracted code. If so, you can now remove the declaration.
Compile and test.
-
Inverse Refactorings
A continuacin se muestra una lista de refctorings. Al lado de cada refactoring, escribe el nombre
del refactoring que revierte su cambio.
Refactoring Inverse
Collapse Hierarchy
Extract Method
Inline Class
Rename Method
Inline Temp
Pull Up Method
-
SmellstoRefactoringsQuickReferenceGuide
FFowler,Martin.Refactoring:ImprovingtheDesignofExistingCode.KKerievsky,Joshua.RefactoringtoPatterns. Adaptedfromhttp://industriallogic.com/papers/smellstorefactorings.pdf
Smell Description Refactoring
AlternativeClasseswithDifferentInterfaces
Occurswhentheinterfacesoftwoclassesaredifferentandyettheclassesarequitesimilar.Ifyoucanfindthesimilaritiesbetweenthetwoclasses,youcanoftenrefactortheclassestomakethemshareacommoninterface[F85,K43]
UnifyInterfaceswithAdapter[K247]RenameMethod[F273]MoveMethod[F142]
CombinatorialExplosionAsubtleformofduplication,thissmellexistswhennumerouspiecesofcodedothesamethingusingdifferentcombinationsofdataorbehavior.[K45]
ReplaceImplicitLanguagewithInterpreter[K269]
Comments(a.k.a.Deodorant)
Whenyoufeellikewritingacomment,firsttry"torefactorsothatthecommentbecomessuperfluous"[F87]
RenameMethod[F273]ExtractMethod[F110]IntroduceAssertion[F267]
ConditionalComplexityConditionallogicisinnocentinitsinfancy,whenitssimpletounderstandandcontainedwithinafewlinesofcode.Unfortunately,itrarelyageswell.Youimplementseveralnewfeaturesandsuddenlyyourconditionallogicbecomescomplicatedandexpansive.[K41]
IntroduceNullObject[F260,K301]MoveEmbellishmenttoDecorator[K144]ReplaceConditionalLogicwithStrategy[K129]ReplaceStateAlteringConditionalswithState[K166]
DataClassClassesthathavefields,gettingandsettingmethodsforthefields,andnothingelse.Suchclassesaredumbdataholdersandarealmostcertainlybeingmanipulatedinfartoomuchdetailbyotherclasses.[F86]
MoveMethod[F142]EncapsulateField[F206]EncapsulateCollection[F208]
DataClumpsBunchesofdatathatthathangaroundtogetherreallyoughttobemadeintotheirownobject.Agoodtestistoconsiderdeletingoneofthedatavalues:ifyoudidthis,wouldtheothersmakeanysense?Iftheydon't,it'sasuresignthatyouhaveanobjectthat'sdyingtobeborn.[F81]
ExtractClass[F149]PreserveWholeObject[F288]IntroduceParameterObject[F295]
DivergentChangeOccurswhenoneclassiscommonlychangedindifferentwaysfordifferentreasons.Separatingthesedivergentresponsibilitiesdecreasesthechancethatonechangecouldaffectanotherandlowermaintenancecosts.[F79]
ExtractClass[F149]
DuplicatedCodeDuplicatedcodeisthemostpervasiveandpungentsmellinsoftware.Ittendstobeeitherexplicitorsubtle.Explicitduplicationexistsinidenticalcode,whilesubtleduplicationexistsinstructuresorprocessingstepsthatareoutwardlydifferent,yetessentiallythesame.[F76,K39]
ChainConstructors[K340]ExtractComposite[K214]ExtractMethod[F110]ExtractClass[F149]FormTemplateMethod[F345,K205]IntroduceNullObject[F260,K301]IntroducePolymorphicCreationwithFactoryMethod[K88]PullUpMethod[F322]PullUpField[F320]ReplaceOne/ManyDistinctionswithComposite[K224]SubstituteAlgorithm[F139]UnifyInterfaceswithAdapter[K247]
FeatureEnvyDataandbehaviorthatactsonthatdatabelongtogether.Whenamethodmakestoomanycallstootherclassestoobtaindataorfunctionality,FeatureEnvyisintheair.[F80]
ExtractMethod[F110]MoveMethod[F142]MoveField[F146]
Freeloader(a.k.a.LazyClass)
Aclassthatisntdoingenoughtopayforitselfshouldbeeliminated.[F83,K43]CollapseHierarchy[F344]InlineClass[F154]InlineSingleton[K114]
InappropriateIntimacy
Sometimesclassesbecomefartoointimateandspendtoomuchtimedelvingintoeachothersprivateparts.Wemaynotbeprudeswhenitcomestopeople,butwethinkourclassesshouldfollowstrict,puritanrules.Overintimateclassesneedtobebrokenupasloverswereinancientdays.[F85]
MoveMethod[F142]MoveField[F146]ChangeBidirectionalAssociationtoUnidirectionalAssociation[F200]ExtractClass[F149]HideDelegate[F157]ReplaceInheritancewithDelegation[F352]
-
SmellstoRefactoringsQuickReferenceGuide
FFowler,Martin.Refactoring:ImprovingtheDesignofExistingCode.KKerievsky,Joshua.RefactoringtoPatterns. Adaptedfromhttp://industriallogic.com/papers/smellstorefactorings.pdf
Smell Description Refactoring
IncompleteLibraryClassOccurswhenresponsibilitiesemergeinourcodethatclearlyshouldbemovedtoalibraryclass,butweareunableorunwillingtomodifythelibraryclasstoacceptthesenewresponsibilities.[F86]
IntroduceForeignMethod[F162]
IntroduceLocalExtension[F164]
IndecentExposure
ThissmellindicatesthelackofwhatDavidParnassofamouslytermedinformationhiding[Parnas].Thesmelloccurswhenmethodsorclassesthatoughtnottobevisibletoclientsarepubliclyvisibletothem.Exposingsuchcodemeansthatclientsknowaboutcodethatisunimportantoronlyindirectlyimportant.Thiscontributestothecomplexityofadesign.[K42]
EncapsulateClasseswithFactory[K80]
LargeClassFowlerandBecknotethatthepresenceoftoomanyinstancevariablesusuallyindicatesthataclassistryingtodotoomuch.Ingeneral,largeclassestypicallycontaintoomanyresponsibilities.[F78,K44]
ExtractClass[F149]ExtractSubclass[F330]ExtractInterface[F341]ReplaceDataValuewithObject[F175]ReplaceConditionalDispatcherwithCommand[K191]ReplaceImplicitLanguagewithInterpreter[K269]ReplaceStateAlteringConditionalswithState[K166]
LongMethod
Intheirdescriptionofthissmell,FowlerandBeckexplainseveralgoodreasonswhyshortmethodsaresuperiortolongmethods.Aprincipalreasoninvolvesthesharingoflogic.Twolongmethodsmayverywellcontainduplicatedcode.Yetifyoubreakthosemethodsintosmallermethods,youcanoftenfindwaysforthetwotosharelogic.FowlerandBeckalsodescribehowsmallmethodshelpexplaincode.Ifyoudontunderstandwhatachunkofcodedoesandyouextractthatcodetoasmall,wellnamedmethod,itwillbeeasiertounderstandtheoriginalcode.Systemsthathaveamajorityofsmallmethodstendtobeeasiertoextendandmaintainbecausetheyreeasiertounderstandandcontainlessduplication.[F76,K40]
ExtractMethod[F110]ComposeMethod[K123]IntroduceParameterObject[F295]MoveAccumulationtoCollectingParameter[K313]MoveAccumulationtoVisitor[K320]DecomposeConditional[F238]PreserveWholeObject[F288]ReplaceConditionalDispatcherwithCommand[K191]ReplaceConditionalLogicwithStrategy[K129]ReplaceMethodwithMethodObject[F135]ReplaceTempwithQuery[F120]
LongParameterListLonglistsofparametersinamethod,thoughcommoninproceduralcode,aredifficulttounderstandandlikelytobevolatile.Considerwhichobjectsthismethodreallyneedstodoitsjobitsokaytomakethemethodtodosomeworktotrackdownthedataitneeds.[F78]
ReplaceParameterwithMethod[F292]IntroduceParameterObject[F295]PreserveWholeObject[F288]
MessageChainsOccurwhenyouseealongsequenceofmethodcallsortemporaryvariablestogetsomedata.Thischainmakesthecodedependentontherelationshipsbetweenmanypotentiallyunrelatedobjects.[F84]
HideDelegate[F157]ExtractMethod[F110]MoveMethod[F142]
MiddleManDelegationisgood,andoneofthekeyfundamentalfeaturesofobjects.Buttoomuchofagoodthingcanleadtoobjectsthataddnovalue,simplypassingmessagesontoanotherobject.[F85]
RemoveMiddleMan[F160]InlineMethod[F117]ReplaceDelegationwithInheritance[F355]
OddballSolutionWhenaproblemissolvedonewaythroughoutasystemandthesameproblemissolvedanotherwayinthesamesystem,oneofthesolutionsistheoddballorinconsistentsolution.Thepresenceofthissmellusuallyindicatessubtlyduplicatedcode.[K45]
UnifyInterfaceswithAdapter[K247]
ParallelInheritanceHierarchies
ThisisreallyaspecialcaseofShotgunSurgeryeverytimeyoumakeasubclassofoneclass,youhavetomakeasubclassofanother.[F83]
MoveMethod[F142]MoveField[F146]
-
SmellstoRefactoringsQuickReferenceGuide
FFowler,Martin.Refactoring:ImprovingtheDesignofExistingCode.KKerievsky,Joshua.RefactoringtoPatterns. Adaptedfromhttp://industriallogic.com/papers/smellstorefactorings.pdf
Smell Description Refactoring
PrimitiveObsession
Primitives,whichincludeintegers,Strings,doubles,arraysandotherlowlevellanguageelements,aregenericbecausemanypeopleusethem.Classes,ontheotherhand,maybeasspecificasyouneedthemtobe,sinceyoucreatethemforspecificpurposes.Inmanycases,classesprovideasimplerandmorenaturalwaytomodelthingsthanprimitives.Inaddition,onceyoucreateaclass,youlloftendiscoverhowothercodeinasystembelongsinthatclass.FowlerandBeckexplainhowprimitiveobsessionmanifestsitselfwhencodereliestoomuchonprimitives.Thistypicallyoccurswhenyouhaventyetseenhowahigherlevelabstractioncanclarifyorsimplifyyourcode.[F81,K41]
ReplaceDataValuewithObject[F175]EncapsulateCompositewithBuilder[K96]IntroduceParameterObject[F295]ExtractClass[F149]MoveEmbellishmenttoDecorator[K144]ReplaceConditionalLogicwithStrategy[K129]ReplaceImplicitLanguagewithInterpreter[K269]ReplaceImplicitTreewithComposite[K178]ReplaceStateAlteringConditionalswithState[K166]ReplaceTypeCodewithClass[F218,K286]ReplaceTypeCodewithState/Strategy[F227]ReplaceTypeCodewithSubclasses[F223]ReplaceArrayWithObject[F186]
RefusedBequestThissmellresultsfrominheritingcodeyoudon'twant.Insteadoftoleratingtheinheritance,youwritecodetorefusethe"bequest"whichleadstougly,confusingcode,tosaytheleast.[F87]
PushDownField[F329]PushDownMethod[F322]ReplaceInheritancewithDelegation[F352]
ShotgunSurgeryThissmellisevidentwhenyoumustchangelotsofpiecesofcodeindifferentplacessimplytoaddaneworextendedpieceofbehavior.[F80]
MoveMethod[F142]MoveField[F146]InlineClass[F154]
SolutionSprawl
Whencodeand/ordatausedinperformingaresponsibilitybecomessprawledacrossnumerousclasses,solutionsprawlisintheair.Thissmelloftenresultsfromquicklyaddingafeaturetoasystemwithoutspendingenoughtimesimplifyingandconsolidatingthedesigntobestaccommodatethefeature.[K43]
MoveCreationKnowledgetoFactory[K68]
SpeculativeGeneralityThisodorexistswhenyouhavegenericorabstractcodethatisntactuallyneededtoday.Suchcodeoftenexiststosupportfuturebehavior,whichmayormaynotbenecessaryinthefuture.[F83]
CollapseHierarchy[F344]RenameMethod[F273]RemoveParameter[F277]InlineClass[F154]
SwitchStatementThissmellexistswhenthesameswitchstatement(orifelseifelseifstatement)isduplicatedacrossasystem.Suchduplicatedcoderevealsalackofobjectorientationandamissedopportunitytorelyontheeleganceofpolymorphism.[F82,K44]
MoveAccumulationtoVisitor[K320]ReplaceConditionalDispatcherwithCommand[K191]ReplaceConditionalwithPolymorphism[F255]ReplaceTypeCodewithSubclasses[F223]ReplaceTypeCodewithState/Strategy[F227]ReplaceParameterwithExplicitMethods[F285]IntroduceNullObject[F260,K301]
TemporaryFieldObjectssometimescontainfieldsthatdon'tseemtobeneededallthetime.Therestofthetime,thefieldisemptyorcontainsirrelevantdata,whichisdifficulttounderstand.ThisisoftenanalternativetoLongParameterList.[F84]
ExtractClass[F149]
IntroduceNullObject[F260,K301]
-
Feedback en Cuatro Cuadrantes
1. Mis sentimientos sobre lo que acabo de aprender son:
2. Los conceptos ms importantes que aprend son:
3. Lo que planeo hacer con lo que aprend es:
4. Un comentario final, sugerencia o pregunta que an tengo es:
Nombre, email y retrato (o autorretrato). Todo opcional.