Refactoring IIIGeneral philosophyDuplicated codeMaking code fasterLong methodsTemporary variablesReplace Temp With QueryIntroduce Parameter ObjectPreserve Whole ObjectReplace Method With Method ObjectLong parameter listLarge classExtract ClassExtract SubclassExtract InterfaceFeature envyPrimitive ObsessionMore bad smells, IMore bad smells, IITesting for nullThat’s all for now...Jan 13, 2019Refactoring IIIGeneral philosophyA refactoring is just a way of rearranging codeRefactorings are used to solve problemsIf there’s no problem, you shouldn’t refactorThe notion of “bad smells” is a way of helping us recognize when we have a problemFamiliarity with bad smells also helps us avoid them in the first placeRefactorings are mostly pretty obviousMost of the value in discussing them is just to bring them into our “conscious toolbox”Refactorings have names in order to crystallize the idea and help us remember itDuplicated codeMartin Fowler refers to duplicated code as “Number one in the stink parade”The usual solution is to apply Extract Method: Create a single method from the repeated code, and use it wherever neededWe’ve discussed some of the details of this (adding a parameter list, etc.)This adds the overhead of method calls, thus the code gets a bit slowerIs this a problem?Making code faster“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.” -- Tony HoareRules of Optimization: Rule 1: Don't do it. Rule 2 (for experts only): Don't do it yet. -- M.A. Jackson“More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason--including blind stupidity.” -- W.A. WulfVery few programs actually need to be fasterThe only two examples I can think of are game graphics and BlackboardDonald E. Knuth pointed out (in 1970) that it is essentially impossible to predict where the bottlenecks are in a program--you need to use a profiler to actually measure what the code is doingLong methodsAnother “bad smell” is the overly long methodAlmost always, you can fix long methods by applying Extract MethodFind parts of the method that seem to perform a single task, and make them into a new methodPotential problem: You may end up with lots of parameters and temporary variablesTemporaries: Consider Replace Temp With QueryParameters: Try Introduce Parameter Object and Preserve Whole ObjectIf all else fails, use Replace Method With Method ObjectTemporary variablesAccording to Fowler, temporary variables “tend to encourage longer methods, because that’s the only way you can get at the temp.”If the code fragment you want to extract into a method contains references to temporary variables whose scope overlaps the fragment, you have to somehow provide access to that temporary variableSolution: Use the Replace Temp With Query refactoringReplace Temp With QueryCreate a method to compute or access the temporary variableExample (from Fowler):Replace: double basePrice = quantity * itemPrice; if (basePrice > 1000) return basePrice * 0.95; else return basePrice * 0.98;with: if (basePrice () > 1000) return basePrice() * 0.95; else return basePrice() * 0.98; ... double basePrice() { return quantity * itemPrice; }Introduce Parameter Object Problem: You have a method that requires a long parameter listYou may have a group of parameters that go naturally togetherIf so, make them into an objectExample: Replace public void marry(String name, int age, boolean gender, String name2, int age2, boolean gender2) {...}with public void marry(Person person1, Person person2) {...}Preserve Whole ObjectProblem: You have a method that requires a long parameter listIf you are passing in multiple values from the same object, pass the object in insteadExample: Replace sendBill(customer.name, customer.address, customer.order, amount);with sendBill(customer, amount);Replace Method With Method Object If: you have a long method that uses local variables, and you can’t use Extract Method,Then: turn the method itself into a objectCreate a new class, named after the methodGive the new class the following fields:A final field to hold the object that the method originally came fromA field for each temporary variable and parameter in the methodWrite a constructor that takes as parameters the original object and the parameters of the original methodCopy the original method into the new classIf you need anything from the original object, you have a reference to itAll the old local variables are now fields of the objectThis makes it easy to decompose the long method into as many methods as you wantLong parameter listLong parameter lists are difficult to understand, difficult to remember, and make it harder to format your code nicelyWe’ve already discussed some solutions, such as Introduce Parameter ObjectAnother solution, which we won’t go into in detail, is called Replace Parameter With MethodThe idea is that you shouldn’t pass a parameter into a method if the method has enough information to compute the parameter for itselfLarge classClasses can get overly largeToo many instance variablesMore than a couple dozen methodsSeemingly unrelated methods in the same classPossible refactorings are Extract Class and Extract SubclassA related refactoring, Extract Interface, can be helpful in determining how to break up a large classExtract ClassExtract Class is used when you decide to break one class into two classesClasses tend to grow, and get more and more dataGood signs:A subset of the data and a subset of the methods seem to go togetherA subset of the data seems to be interdependentUseful tests:If you removed a method or a particular piece of data, what other fields and methods would become nonsense?How is the class subtyped?The actual refactoring technique involves creating a new (empty) class, and repeatedly moving fields and methods into it, compiling and testing after each moveExtract SubclassExtract Subclass is used when some behaviors of a class are used for certain instances, but not othersIf you have a “type code” that is used to distinguish between types of objects, this suggests that a subclass may be
View Full Document