Refactoring IV - PowerPoint PPT Presentation

1 / 24
About This Presentation
Title:

Refactoring IV

Description:

Parallel inheritance hierarchies can't make just one subclass ... If you try to make things too general, you may have unnecessary code that just gets in the way ... – PowerPoint PPT presentation

Number of Views:46
Avg rating:3.0/5.0
Slides: 25
Provided by: DavidMa6
Category:
Tags: make | refactoring

less

Transcript and Presenter's Notes

Title: Refactoring IV


1
Refactoring IV
2
Previously discussed bad smells
  • Duplicated code and other forms of redundancy
  • Long method use short methods that delegate
    work
  • Large class trying to do too much
  • Long parameter list hard to use and remember
  • Divergent change changes in one class for
    different reasons
  • Shotgun surgery a change requires little
    changes all over
  • Feature envy method uses too much from some
    other class
  • Data clumps variables that frequently occur
    together
  • Primitive obsession being afraid of making
    small objects
  • Switch statements probably should use
    polymorphism instead

3
More bad smells
  • Parallel inheritance hierarchies cant make
    just one subclass
  • Lazy class too few responsibilities
  • Speculative generality code that isnt needed
  • Temporary field an object doesnt use all its
    variables
  • Message chains asking for objects to ask for
    objects
  • Middle man too much responsibility passed along
  • Inappropriate intimacy classes accessing each
    other too much
  • Alternative classes with different interfaces
    similar work but with different signatures
  • Incomplete library class inadequate for reuse
  • Data class just data, maybe getters and setters
  • Refused bequest subclass dont use much of
    their inheritance
  • Comments when used as a substitute for good code

4
Parallel inheritance hierarchies
  • When you make a subclass of one class, you have
    to make a corresponding subclass of another class
  • General strategy Use Move Method and Move Field
    to make instances of one hierarchy refer to
    instances of the other

5
Lazy class
  • Small classes are fine, but sometimes a class
    just doesnt do enough
  • If a class is very similar to its superclass, you
    can try to use Collapse Hierarchy to merge the
    two classes
  • Eliminate the subclass by using Pull Up Field and
    Pull Up Method or,
  • Eliminate the superclass by using Push Down Field
    and Push Down Method
  • If a class just isnt doing very much, move all
    its features into another class with Move Field
    and Move Method

6
Speculative generality
  • One of the principles of Extreme Programming (XP)
    is that you shouldnt write code until you need
    it
  • XP assumes that code will change frequently, and
    tries to make change as fast and easy as possible
  • If you try to make things too general, you may
    have unnecessary code that just gets in the way
  • If the only users of a class or method are test
    cases, the code should be thrown away
  • Since I hate to throw away good code, I usually
    move unused code to a discards directory

7
Temporary field
  • We expect an object to use all its fields
  • Its confusing when an instance variable is used
    only in certain cases
  • Use Extract Class to create a home for these
    variables
  • Eliminate conditional code with Introduce Null
    Object
  • Sometimes programmers will add instance variables
    to avoid long parameter lists between
    communicating methods
  • Use Extract Class to create a new method object

8
Message 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 object
  • Often, but not always, these are getter methods
  • Message chains can be abbreviated or eliminated
    by Hide Delegate
  • As an example of Hide Delegate, we can introduce
    the following method into foos class
  • BazObject getBaz() return bar.getBaz()
  • And then we can just call BazObject b
    foo.getBaz()

9
Middle man
  • Delegationproviding methods to call methods in
    another classis often useful for hiding internal
    details
  • ExampleBazObject getBaz() return
    bar.getBaz()
  • However, too much delegation isnt good
  • You can
  • Use Remove Middle Man and talk to the object that
    really knows what is going on
  • Use Inline Method to absorb a few small methods
    into the caller
  • Use Replace Delegation With Inheritance to turn
    the middle man into a subclass of the real object

10
Inappropriate intimacy
  • Classes may make too much use of each others
    fields and methods
  • Use Move Method and Move Field to reduce the
    association
  • Try to Change Bidirectional Association to
    Unidirectional
  • The idea here is to take the class that is less
    dependent on the other class and remove the
    remaining dependencies
  • If the classes have common needs, try Extract
    Class
  • Use Hide Delegate to let another class act as a
    middle man
  • If a subclass knows too much about its
    superclass, use Replace Inheritance With
    Delegation (see later comments on Refused Bequest)

11
Replace Inheritance With Delegation
  • Sometimes a subclass inherits more from its
    superclass than you want it to have
  • Example 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

12
Alternative classes, different interfaces
  • You end up with two essentially equivalent
    classes (example Javas Enumeration and Iterator
    classes)
  • Java cant eliminate Enumeration because that
    would break old code
  • Even in this situation, the functionality can be
    moved into a single class
  • Use Rename Method on methods that do the same
    thing but have different signatures
  • Use Move Method until classes are doing the same
    things
  • You may want to use Extract Superclass

13
Incomplete library class
  • Library classes (such as those supplied by Sun)
    dont always do everything we want them to do
  • Its usually impossible to modify these library
    classes
  • Use Introduce Foreign Method
  • Write the method you want, as if it were in the
    library class
  • Make an instance of the library class the first
    parameter
  • Add 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
    Date(arg.getYear(), arg.getMonth(),
    arg getDate() 1)

14
Data class
  • Classes that just hold data, and maybe setters
    and getters for that data, are undesirable
  • If a field is public, use Encapsulate Method to
    make it private and add setters and getters (if
    it isnt too late)
  • If a method returns a collection, use Encapsulate
    Collection
  • Make the method return a read-only view
    (java.util.Collections supplies methods such as
    unmodifiableSet(Set) and unmodifiableMap(Map))
  • Provide add and remove methods as appropriate
  • Try to use Move Method to move the setters and
    getters to the class that needs them

15
Refused bequest
  • Subclasses may inherit unwanted methods from
    their superclasses
  • This suggests that the hierarchy may be wrong
  • Create a new subclass and use Push Down Method
    and Push Down Field on the unused methods
  • Fowler feels that this isnt a severe problem,
    unless the subclass is reusing behavior but not
    the interface
  • In a few places, Suns packages override an
    inherited method with one that just throws an
    UnsupportedOperationException
  • A better solution is to Replace Inheritance With
    Delegation

16
Comments
  • Fowler says comments often are used as a
    deodorant
  • If you need a comment to explain what a block of
    code does, use Extract Method
  • If you need a comment to explain what a method
    does, use Rename Method
  • If you need to describe the required state of the
    system, use Introduce Assertion
  • This should not discourage the use of comments
    (especially javadoc comments)the point is that
    code should be self-explanatory, so that comments
    are not necessary

17
Advice from Kent Beck
  • Stopping is the strongest move in the
    refactorers repertoire.
  • The idea is to take small goals, refactor in
    small steps, so that you can quit in a stable
    state, having made progress
  • Somewhere your code smells bad. Resolve to get
    rid of the problem. Then march toward that goal.
  • Stop when you are unsure
  • If the code is already better, go ahead and
    release it
  • If you arent sure of your changes, discard them
    and go back to the previous stable state
  • Backtrack. If the code quits working, and you
    havent tested in a while, dont debugthrow away
    the changes since the last working tests
  • Emotionally difficult, but rewriting is faster
    and easier than debugging
  • Work with someone. There are many advantages to
    working in pairs.

18
Soundbites I
  • When you find you have to add a feature to a
    program, and the programs code is not structured
    in a convenient way to add the feature, first
    refactor the program to make it easy to add the
    feature, then add the feature
  • Before you start refactoring, check that you have
    a solid suite of tests. These tests must be
    self-checking.
  • Refactoring changes the programs in small steps.
    If you make a mistake, it is easy to find the bug.

19
Soundbites II
  • Any fool can write code that a computer can
    understand. Good programmers write code that
    humans can understand.
  • Refactoring (noun) a change made to the internal
    structure of software to make it easier to
    understand and cheaper to modify without changing
    the observable behavior of the software.
  • Refactor (verb) to restructure software by
    applying a series of refactorings without
    changing the observable behavior of the software.

20
Soundbites III
  • Three strikes and you refactor.
  • The first time you do something, you just do it.
    The second time you do something similar, you
    wince at the duplication, but you do the
    duplicate thing anyway. The third time you do
    something similar, you refactor.
  • Dont publish interfaces prematurely. Modify your
    code ownership policies to smooth refactoring.
  • When you feel the need to write a comment, first
    try to refactor the code so that any comment
    becomes superfluous.

21
Soundbites IV
  • Make sure all tests are fully automatic and that
    they check their own results.
  • A suite of tests is a powerful bug detector that
    decapitates the time it takes to find bugs.
  • Run your tests frequently. Localize tests
    whenever you compileevery test at least every
    day.
  • When you get a bug report, start by writing a
    unit test that exposes the bug.

22
Soundbites V
  • It is better to write and run incomplete tests
    than not to run complete tests.
  • Think of the boundary conditions under which
    things might go wrong and concentrate your tests
    there.
  • Dont forget to test that exceptions are raised
    when things are expected to go wrong.
  • Dont let the fear that testing cant catch all
    bugs stop you from writing the tests that will
    catch most bugs.

23
Conclusions
  • A couple of the more important goals of Agile
    Programming (including XP) are to
  • Keep code flexible and easily changed
  • Avoid long debugging sessions
  • Always have something that works
  • Refactoring depends heavily on
  • Taking small steps
  • Having a fully automated test suite that you use
    frequently

24
The End
Write a Comment
User Comments (0)
About PowerShow.com