1 / 19

Refactoring II

Refactoring II. Books I. Design Patterns is the classic book by “the Gang of Four”: Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides Basically a catalog of program organizations Reading it is rather like reading a dictionary

erik
Download Presentation

Refactoring II

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Refactoring II

  2. Books I • Design Patterns is the classic book by “the Gang of Four”: Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides • Basically a catalog of program organizations • Reading it is rather like reading a dictionary • Although equally applicable to Java, the examples are in C++ • Head First Design Patterns by Elizabeth Freeman • Fun, irreverent, and entertaining • IMHO the best book for developing an understanding of what design patterns are all about

  3. Books II AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis by William J. Brown, Raphael C. Malveau, Hays W. "Skip" McCormick, Thomas J. Mowbray • Describes bad patterns and how to fix them • More fun to read than the Gang of Four book • Refactoring: Improving the Design of Existing Code by Martin Fowler, with contributions from Kent Beck and others • Very clear, plenty of useful ideas, very readable • Much of this lecture will be based on this book

  4. Design Patterns and Refactoring • Design Patterns describe good solutions to common (or at least, not extremely rare) design problems • Design Patterns are always specified in UML • Model-View-Controller is a very common Design Pattern • An Antipattern is a common, but poor, Design Pattern • Antipatterns can be refactored into better designs • Refactoring is rearranging existing code while maintaining the same functionality • Refactoring is usually done in terms of applying some Design Pattern

  5. Example: Card cardId:int -copy:boolean=false «constructor» Card(int id) +isKind(desiredKind:int) +isSharable():boolean +toString():String Name of the class Variables [optional] Methods UML review I • Key: • + means public visibility • # means protected visibility • - means private visibility • <blank> means default (package) visibility • static variables are underlined

  6. A B C D Factory Product A B creates 1..4 Class Ccontains 1 to 4 objectsof class D Other kinds ofrelations Class Bextendsclass A Class Bimplementsinterface A UML review II

  7. Bad smells • Where did this term come from? • “If it stinks, change it.” --Grandma Beck, discussing child-rearing philosophy • The basic idea is that there are things in code that cause problems • Duplicated code • Long methods • Etc. • A common reason for refactoring is that you need to add features that don’t fit well with the existing design • Any time you change working code, you run the risk of breaking it • A good test suite makes refactoring much easier and safer

  8. Some time ago I was working on code to evaluate expressions Expressions can be parsed into a tree structure Now what? You could walk the tree and, at each node, use a switch statement to do the right thing Adding a new operator requires modifying existing code I “discovered” a better solution + 2 * Command lhs:Command rhs:Commandvalue:int 5 x 0..2 Tree for 2 + 5 * x evaluate():int An example

  9. class Add implements Command { int evaluate( ) { int v1 = lhs.evaluate().value; int v2 = rhs.evaluate().value; value = v1 + v2; return value; }} To evaluate the entire tree, evaluate the root node To add an operator, add another class that extends Command This is just a rough description; there are a lot of other details to consider Some operands are unary You have to look up the values of variables Etc. Command lhs:Command rhs:Commandvalue:int 0..2 evaluate():int Using my “Command” pattern

  10. Duplicated code I • If the same code fragment occurs in more than one place within a single class, you can use Extract Method • Turn the fragment into a method whose name explains the purpose of the method • Any local variables that the method requires can be passed as parameters (if there aren’t too many of them!) • If the method changes a local variable, see whether it makes sense to return that as the value of the method (possibly changing the name of the method to indicate this) • If the method changes two or more variables, you need other refactorings to fix this problem

  11. Duplicated code II • If the same code fragment occurs in sibling classes, you can use Extract Method in both classes, then use Pull Up Method • Use ExtractMethod in each class • Be sure the code is identical • If necessary, adjust the method signatures to be identical • Copy the extracted method to the common superclass • Delete one subclass method • Compile and test • Delete the other subclass method • Compile and test

  12. Duplicated code III • If the same code fragment occurs in unrelated classes, you can use Extract Method in one class, then: • Use this class as a component in the other class, or • Invoke the method from the other class, or • Move the method to a third class and refer to it from both of the original classes • In any case, you need to decide where the method makes most sense, and put it there • Eclipse has an Extract method... command that does most of this work for you

  13. Duplicated code IV • If almost the same code fragment occurs in sibling classes, use Extract Method to separate the similar bits from the different bits, and use Form Template Method • I’ll give an example in a moment

  14. The Template Method • Template Methods lead to an inverted control structure • A superclass calls methods in its subclass • Template methods are so fundamental that they can be found in almost every abstract class • Template Method uses inheritance • A similar pattern, Strategy Pattern, uses delegation rather than inheritance

  15. Fish <<abstract>>move() BigFish LittleFish move() move() Big fish and little fish • The scenario: “big fish” and “little fish” move around in an “ocean” • Fish move about randomly • A big fish can move to where a little fish is (and eat it) • A little fish will not move to where a big fish is • Here’s the initial code (before refactoring):

  16. The move() method • General outline of the method: • public void move() {choose a random direction; // same for both find the location in that direction;// same for bothcheck if it’s ok to move there; // differentif it’s ok, make the move;// same for both} • To do the Form Template Method: • Extract the check on whether it’s ok to move • In the Fish class, put the actual (template) move() method • Create an abstract okToMove() method in the Fish class • Implement okToMove() in each subclass

  17. <<abstract>>Fish Fish move() <<abstract>>okToMove(locn):boolean <<abstract>>move() BigFish BigFish LittleFish BigFish okToMove(locn):boolean move() okToMove(locn):boolean move() The Fish refactoring • Note how this works: When a BigFish tries to move, it uses the move() method in Fish • But the move() method in Fish uses the okToMove(locn) method in BigFish • And similarly for LittleFish

  18. The resultant code • In Fish: • public void move() {choose a random direction; // same for both find the location in that direction;// same for bothcheck if it’s ok to move there; // same for bothif it’s ok, make the move;// same for both} • abstract boolean okToMove(locn); • In BigFish and in LittleFish: • boolean okToMove(locn) {code for this kind of fish}

  19. To be continued...

More Related