Code Smells and Refactoring - Asistente

Embed Size (px)

DESCRIPTION

Code Smells and Re-factoring in Test Driven Development

Citation preview

  • 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.