Refactoring III Jan 13 2019 General philosophy A refactoring is just a way of rearranging code The notion of bad smells is a way of helping us recognize when we have a problem Refactorings are used to solve problems If there s no problem you shouldn t refactor Familiarity with bad smells also helps us avoid them in the first place Refactorings are mostly pretty obvious Most 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 it Duplicated code Martin 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 needed We 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 slower Is 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 Hoare Rules 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 Wulf Very few programs actually need to be faster The only two examples I can think of are game graphics and Blackboard Donald 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 doing Long methods Another bad smell is the overly long method Almost always you can fix long methods by applying Extract Method Find parts of the method that seem to perform a single task and make them into a new method Potential problem You may end up with lots of parameters and temporary variables Temporaries Consider Replace Temp With Query Parameters Try Introduce Parameter Object and Preserve Whole Object If all else fails use Replace Method With Method Object Temporary variables According 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 variable Solution Use the Replace Temp With Query refactoring Replace Temp With Query Create a method to compute or access the temporary variable Example 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 list You may have a group of parameters that go naturally together If so make them into an object Example 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 Object Problem You have a method that requires a long parameter list If you are passing in multiple values from the same object pass the object in instead Example 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 object Create a new class named after the method Give the new class the following fields A final field to hold the object that the method originally came from A field for each temporary variable and parameter in the method Write a constructor that takes as parameters the original object and the parameters of the original method Copy the original method into the new class If you need anything from the original object you have a reference to it All the old local variables are now fields of the object This makes it easy to decompose the long method into as many methods as you want Long parameter list Long parameter lists are difficult to understand difficult to remember and make it harder to format your code nicely We ve already discussed some solutions such as Introduce Parameter Object Another solution which we won t go into in detail is called Replace Parameter With Method The idea is that you shouldn t pass a parameter into a method if the method has enough information to compute the parameter for itself Large class Classes can get overly large Too many instance variables More than a couple dozen methods Seemingly unrelated methods in the same class Possible refactorings are Extract Class and Extract Subclass A related refactoring Extract Interface can be helpful in determining how to break up a large class Extract Class Extract Class is used when you decide to break one class into two classes Classes tend to grow and get more and more data Good signs Useful tests A subset of the data and a subset of the methods seem to go together A subset of the data seems to be interdependent 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 move Extract Subclass Extract Subclass is used when some behaviors of a class are used for certain instances but not others If you have a type code that is used to distinguish between types of objects this suggests that a subclass may be appropriate The type code can be eliminated when you create the subclass Extract Subclass should not be used when the instances vary in more than one respect The basic steps are Define the subclass provide constructors and use Push Down Method and Push Down Field refactorings We won t go into the details of these refactorings Extract Interface Extract Interface is used when two or more classes share a related set of behaviors For example you might provide two or more types of services to your customers with similar but separate billing needs This suggests a Billable interface I hire J K landscaping to do routine mowing and yard clearing they also remove fallen trees but bill the job differently Java s Collections make heavy use of interfaces as you have to do similar things add remove
View Full Document