Refactoring IVPreviously discussed bad smellsMore bad smellsParallel inheritance hierarchiesLazy classSpeculative generalityTemporary fieldMessage chainsMiddle manInappropriate intimacyReplace Inheritance With DelegationAlternative classes, different interfacesIncomplete library classData classRefused bequestCommentsAdvice from Kent BeckSoundbites ISoundbites IISoundbites IIISoundbites IVSoundbites VConclusionsThe EndJan 14, 2019Refactoring IVPreviously discussed bad smellsDuplicated code — and other forms of redundancyLong method — use short methods that delegate workLarge class — trying to do too muchLong parameter list — hard to use and rememberDivergent change — changes in one class for different reasonsShotgun surgery — a change requires little changes all overFeature envy — method uses too much from some other classData clumps — variables that frequently occur togetherPrimitive obsession — being afraid of making “small” objectsSwitch statements — probably should use polymorphism insteadMore bad smellsParallel inheritance hierarchies — can’t make just one subclassLazy class — too few responsibilitiesSpeculative generality — code that isn’t neededTemporary field — an object doesn’t use all its variablesMessage chains — asking for objects to ask for objectsMiddle man — too much responsibility passed alongInappropriate intimacy — classes accessing each other too muchAlternative classes with different interfaces — similar work but with different signaturesIncomplete library class — inadequate for reuseData class — just data, maybe getters and settersRefused bequest — subclass don’t use much of their inheritanceComments — when used as a substitute for good codeParallel inheritance hierarchies When you make a subclass of one class, you have to make a corresponding subclass of another classGeneral strategy: Use Move Method and Move Field to make instances of one hierarchy refer to instances of the otherLazy classSmall classes are fine, but sometimes a class just doesn’t do enoughIf a class is very similar to its superclass, you can try to use Collapse Hierarchy to merge the two classesEliminate the subclass by using Pull Up Field and Pull Up Method; or,Eliminate the superclass by using Push Down Field and Push Down MethodIf a class just isn’t doing very much, move all its features into another class with Move Field and Move MethodSpeculative generality One of the principles of Extreme Programming (XP) is that you shouldn’t write code until you need itXP assumes that code will change frequently, and tries to make change as fast and easy as possibleIf you try to make things too general, you may have unnecessary code that just gets in the wayIf the only users of a class or method are test cases, the code should be thrown awaySince I hate to throw away good code, I usually move unused code to a discards directoryTemporary field We expect an object to use all its fieldsIt’s confusing when an instance variable is used only in certain cases Use Extract Class to create a home for these variablesEliminate conditional code with Introduce Null ObjectSometimes programmers will add instance variables to avoid long parameter lists between communicating methodsUse Extract Class to create a new method objectMessage chains A message chain is a sequence such asBazObject b =foo.getBar().getBaz()Here we are asking foo for a bar object so that we can ask it for a baz objectOften, but not always, these are getter methodsMessage chains can be abbreviated or eliminated by Hide DelegateAs an example of Hide Delegate, we can introduce the following method into foo’s class:BazObject getBaz() { return bar.getBaz(); }And then we can just call BazObject b = foo.getBaz();Middle manDelegation—providing methods to call methods in another class—is often useful for hiding internal detailsExample:BazObject getBaz() { return bar.getBaz(); }However, too much delegation isn’t goodYou can:Use Remove Middle Man and talk to the object that really knows what is going onUse Inline Method to absorb a few small methods into the callerUse Replace Delegation With Inheritance to turn the middle man into a subclass of the real objectInappropriate intimacyClasses may make too much use of each other’s fields and methodsUse Move Method and Move Field to reduce the associationTry to Change Bidirectional Association to UnidirectionalThe idea here is to take the class that is less dependent on the other class and remove the remaining dependenciesIf the classes have common needs, try Extract ClassUse Hide Delegate to let another class act as a middle manIf a subclass knows too much about its superclass, use Replace Inheritance With Delegation (see later comments on Refused Bequest)Replace Inheritance With DelegationSometimes a subclass inherits more from its superclass than you want it to haveExample: Suppose class Sub extends Super, inherits desired methods int foo() and void bar(), along with other methods it does not want, and adds method int baz()Replace class Sub extends Super {...}with class Sub { // class name should also be changed Super s = new Super(); int foo() { return s.foo(); } // delegate to s void bar() { s.bar(); } // delegate to s int baz() {...} // new method }Alternative classes, different interfacesYou end up with two essentially equivalent classes (example: Java’s Enumeration and Iterator classes)Java can’t eliminate Enumeration because that would break old codeEven in this situation, the functionality can be moved into a single classUse Rename Method on methods that do the same thing but have different signaturesUse Move Method until classes are doing the same thingsYou may want to use Extract SuperclassIncomplete library class Library classes (such as those supplied by Sun) don’t always do everything we want them to doIt’s usually impossible to modify these library classesUse Introduce Foreign Method:Write the method you want, as if it were in the library classMake an instance of the library class the first parameterAdd a comment that describes the method as a “foreign method”Example:private static Date nextDay(Date arg) { // foreign method, should be in Date return new
View Full Document