Lecture28
Upcoming SlideShare
Loading in...5
×
 

Lecture28

on

  • 897 views

 

Statistics

Views

Total Views
897
Views on SlideShare
897
Embed Views
0

Actions

Likes
0
Downloads
17
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Lecture28 Lecture28 Presentation Transcript

  • Goals of Lecture • Cover Refactoring Lecture 28: Refactoring – Background – Examples Kenneth M. Anderson Object-Oriented Analysis and Design CSCI 6448 - Spring Semester, 2001 April 26, 2001 © Kenneth M. Anderson, 2001 2 What is Refactoring (Very) Simple Example • Consolidate Duplicate Conditional Fragments (page 243); This • Refactoring is the process of changing a if (isSpecialDeal()) { software system such that total = price * 0.95; send() – the external behavior of the system does not } else { total = price * 0.98; change send() } – but the internal structure of the system is • becomes this improved if (isSpecialDeal()) { total = price * 0.95; • This is sometimes called } else { total = price * 0.98; – “Improving the design after it has been written” } send(); April 26, 2001 © Kenneth M. Anderson, 2001 3 April 26, 2001 © Kenneth M. Anderson, 2001 4
  • Refactoring is thus Dangerous! Refactoring is Useful Too • Manager’s point-of-view • Essentially, it is acknowledging the fact that it will be difficult to get a design right the first time – If my programmers spend time “cleaning up the – and as a program’s requirements change, the design may need to code” then that’s less time implementing change required functionality (and my schedule is • refactoring provides techniques for evolving the design in small incremental steps slipping as it is!) • Benefits • To address this concern – Often code size is reduced after a refactoring – Confusing structures are transformed into simpler structures – Refactoring needs to be systematic, incremental, • which are easier to maintain and understand and safe April 26, 2001 © Kenneth M. Anderson, 2001 5 April 26, 2001 © Kenneth M. Anderson, 2001 6 A “cookbook” can be useful Principles in Refactoring • New Book • Fowler’s definition – Refactoring: Improving the Design of Existing – Refactoring (noun) Code • a change made to the internal structure of software • by Martin Fowler (and Kent Beck, John Brant, to make it easier to understand and cheaper to William Opdyke, and Don Roberts) modify without changing its observable behavior • Similar to the Gang of Four’s Design – Refactoring (verb) Patterns • to restructure software by applying a series of refactorings without changing its observable – Provides “refactoring patterns” behavior April 26, 2001 © Kenneth M. Anderson, 2001 7 April 26, 2001 © Kenneth M. Anderson, 2001 8
  • Principles, continued Principles, continued • The purpose of refactoring is • When you systematically apply refactoring, – to make software easier to understand and you wear two hats modify – adding function • contrast this with performance optimization • functionality is added to the system without spending any time cleaning the code – again functionality is not changed, only internal structure; however performance optimizations – refactoring often involve making code harder to understand • no functionality is added, but the code is cleaned up, made easier to understand and modify, and (but faster!) sometimes is reduced in size April 26, 2001 © Kenneth M. Anderson, 2001 9 April 26, 2001 © Kenneth M. Anderson, 2001 10 Principles, continued Why should you refactor? • How do you make refactoring safe? • Refactoring improves the design of software – without refactoring, a design will “decay” as people make changes – First, use refactoring “patterns” to a software system • Fowler’s book assigns “names” to refactorings in the same way • Refactoring makes software easier to understand that the GoF’s book assigned names to patterns – because structure is improved, duplicated code is eliminated, etc. – Second, test constantly! • Refactoring helps you find bugs • This ties into the extreme programming paradigm, you write – Refactoring promotes a deep understanding of the code at hand, tests before you write code, after you refactor code, you run the and this understanding aids the programmer in finding bugs and tests and make sure they all still pass anticipating potential bugs – if a test fails, the refactoring broke something, but you know • Refactoring helps you program faster about it right away and can fix the problem before you move on – because a good design enables progress April 26, 2001 © Kenneth M. Anderson, 2001 11 April 26, 2001 © Kenneth M. Anderson, 2001 12
  • When should you refactor? Problems with Refactoring • The Rule of Three • Databases – Three strikes and you refactor – Business applications are often tightly coupled – refers to duplication of code to underlying databases • code is easy to change; databases are not • Refactor when you add function – Changing Interfaces – to make it easier to add the function • Some refactorings require that interfaces be changed – or to clean things up after the function is added – Design Changes that are difficult to refactor • Refactor when you need to fix a bug • This is why Extreme Programming says that • Refactor as you do a code review software engineers need to have “courage”! April 26, 2001 © Kenneth M. Anderson, 2001 13 April 26, 2001 © Kenneth M. Anderson, 2001 14 Refactoring: Where to Start? Bad Smells in Code • How do you identify code that needs to be • Duplicated Code refactored? – bad because if you modify one instance of – Fowler uses an olfactory analogy (attributed to duplicated code but not the others, you have Kent Beck) introduced a bug! – Look for “Bad Smells” in Code • Long Method • A very valuable chapter in Fowler’s book – long methods are more difficult to understand; • It presents examples of “bad smells” and then performance concerns with respect to lots of suggests refactoring techniques to apply short methods are largely obsolete April 26, 2001 © Kenneth M. Anderson, 2001 15 April 26, 2001 © Kenneth M. Anderson, 2001 16
  • Bad Smells in Code Bad Smells in Code • Large Class • Shotgun Surgery – Large classes try to do too much, which reduces – a change requires lots of little changes in a lot of cohesion different classes • Long Parameter List • Feature Envy – hard to understand, can become inconsistent – A method requires lots of information from some other • Divergent Change class (move it closer!) – Deals with cohesion; symptom: one type of change • Data Clumps requires changing one subset of methods; another type – attributes that clump together but are not part of the of change requires changing another subset same class April 26, 2001 © Kenneth M. Anderson, 2001 17 April 26, 2001 © Kenneth M. Anderson, 2001 18 Bad Smells in Code Bad Smells in Code • Primitive Obsession • Lazy Class – characterized by a reluctance to use classes instead of – A class that no longer “pays its way” primitive data types • e.g. may be a class that was downsized by refactoring, or represented planned functionality that did not pan out • Switch Statements – Switch statements are often duplicated in code; they can • Speculative Generality typically be replaced by use of polymorphism (let OO – “Oh I think we need the ability to do this kind of thing do your selection for you!) someday” • Parallel Inheritance Hierarchies • Temporary Field – Similar to Shotgun Surgery; each time I add a subclass – An attribute of an object is only set in certain to one hierarchy, I need to do it for all related circumstances; but an object should need all of its hierarchies attributes April 26, 2001 © Kenneth M. Anderson, 2001 19 April 26, 2001 © Kenneth M. Anderson, 2001 20
  • Bad Smells in Code Bad Smells in Code • Message Chains • Alternative Classes with Different – a client asks an object for another object and then asks Interfaces that object for another object etc. Bad because client depends on the structure of the navigation – Symptom: Two or more methods do the same • Middle Man thing but have different signature for what they – If a class is delegating more than half of its do responsibilities to another class, do you really need it? • Incomplete Library Class • Inappropriate Intimacy – Pairs of classes that know too much about each other’s – A framework class doesn’t do everything you private details need April 26, 2001 © Kenneth M. Anderson, 2001 21 April 26, 2001 © Kenneth M. Anderson, 2001 22 Bad Smells in Code The Catalog • Data Class • The refactoring book has 72 refactoring – These are classes that have fields, getting and setting patterns! methods for the fields, and nothing else; they are dumb data holders, but objects should be about data AND – I’m only going to cover a few of the more process common ones, including • Refused Bequest • Extract Method – A subclass ignores most of the functionality provided • Replace Temp with Query by its superclass • Move Method • Comments (!) • Replace Conditional with Polymorphism – Comments are sometimes used to hide bad code • Introduce Null Object April 26, 2001 © Kenneth M. Anderson, 2001 23 April 26, 2001 © Kenneth M. Anderson, 2001 24
  • Extract Method Extract Method, continued void printOwing(double amount) { • You have a code fragment that can be printBanner() //print details grouped together System.out.println(“name: ” + _name); System.out.println(“amount: ” + amount); • Turn the fragment into a method whose } ============================================= name explains the purpose of the fragment void printOwing(double amount) { printBanner() printDetails(amount) • Example, next slide } void printDetails(double amount) { System.out.println(“name: ” + _name); System.out.println(“amount: ” + amount); } April 26, 2001 © Kenneth M. Anderson, 2001 25 April 26, 2001 © Kenneth M. Anderson, 2001 26 Replace Temp with Query, Replace Temp with Query continued double basePrice = _quantity * _itemPrice • You are using a temporary variable to hold if (basePrice > 1000) return basePrice * 0.95; the result of an expression else return basePrice * 0.98; • Extract the expression into a method; ============================== if (basePrice() > 1000) Replace all references to the temp with the return basePrice() * 0.95; else expression. The new method can then be return basePrice() * 0.98; … used in other methods double basePrice() { return _quantity * _itemPrice; • Example, next slide } April 26, 2001 © Kenneth M. Anderson, 2001 27 April 26, 2001 © Kenneth M. Anderson, 2001 28
  • Replace Conditional with Move Method Polymorphism • A method is, or will be, using or used by • You have a conditional that chooses more features of another class than the class different behavior depending on the type of on which it is defined an object • Create a new method with a similar body in • Move each leg of the conditional to an the class it uses most. Either turn the old overriding method in a subclass. Make the method into a simple delegation, or remove original method abstract it altogether April 26, 2001 © Kenneth M. Anderson, 2001 29 April 26, 2001 © Kenneth M. Anderson, 2001 30 Replace Conditional with Replace Conditional with Polymorphism, continued Polymorphism, continued double getSpeed() { Bird switch (_type) { case EUROPEAN: return getBaseSpeed(); getSpeed() case AFRICAN: return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts; case NORWEGIAN_BLUE: European African Norwegian Blue return (_isNailed) ? 0 : getBaseSpeed(_voltage); } getSpeed() getSpeed() getSpeed() throw new RuntimeException(“Unreachable”) } April 26, 2001 © Kenneth M. Anderson, 2001 31 April 26, 2001 © Kenneth M. Anderson, 2001 32
  • Introduce Null Object Introduce Null Object if (customer.isNull()) { • Repeated checks for a null value name = “occupant” } else { • Replace the null value with a null object name = customer.getName() } if (customer == null) { Customer =========================== name = “occupant” public class nullCustomer { } else { getName() public String getName() { return “occupant”;} name = customer.getName() } } =========================== if (customer == null) { customer.getName(); … Null Customer The conditional goes away entirely!! getName() April 26, 2001 © Kenneth M. Anderson, 2001 33 April 26, 2001 © Kenneth M. Anderson, 2001 34