refactoring-4 by SanjuDudeja


More Info
									Refactoring IV

       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
       More bad smells
   Parallel inheritance hierarchies — can’t make just one subclass
   Lazy class — too few responsibilities
   Speculative generality — code that isn’t needed
   Temporary field — an object doesn’t 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 don’t use much of their inheritance
   Comments — when used as a substitute for good code
      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
        Lazy class
   Small classes are fine, but sometimes a class just
    doesn’t 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
       If a class just isn’t doing very much, move all its features into
        another class with Move Field and Move Method
        Speculative generality
   One of the principles of Extreme Programming (XP) is
    that you shouldn’t 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
        Temporary field
   We expect an object to use all its fields
   It’s 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
       Use Extract Class to create a new method object
        Message chains
   A message chain is a sequence such as
    BazObject 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
       As 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 man
   Delegation—providing methods to call methods in
    another class—is often useful for hiding internal details
       Example:
      BazObject getBaz() { return bar.getBaz(); }
   However, too much delegation isn’t 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
       Use Replace Delegation With Inheritance to turn the middle
        man into a subclass of the real object
        Inappropriate intimacy
   Classes may make too much use of each other’s 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)
       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 {...}
        class Sub { // class name should also be changed
            Super s = new Super();
            int foo() { return; } // delegate to s
            void bar() {; }       // delegate to s
            int baz() {...} // new method
        Alternative classes, different interfaces
   You end up with two essentially equivalent classes
    (example: Java’s Enumeration and Iterator classes)
       Java can’t 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
   You may want to use Extract Superclass
        Incomplete library class
   Library classes (such as those supplied by Sun) don’t always do
    everything we want them to do
       It’s 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);
        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 isn’t 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
        Refused bequest
   Subclasses may inherit unwanted methods from their
       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 isn’t a severe problem, unless the
        subclass is reusing behavior but not the interface
            In a few places, Sun’s packages override an inherited method with one
             that just throws an UnsupportedOperationException
            A better solution is to Replace Inheritance With Delegation
   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
        Advice from Kent Beck
   “Stopping is the strongest move in the refactorer’s 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 aren’t sure of your changes, discard them and go back to the
        previous stable state
   Backtrack. If the code quits working, and you haven’t tested in a
    while, don’t debug—throw 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
       Soundbites I
   When you find you have to add a feature to a program,
    and the program’s 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.
      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.
        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.”

   Don’t 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
       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
    compile—every test at least every day.

   When you get a bug report, start by writing a unit test
    that exposes the bug.
       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.

   Don’t forget to test that exceptions are raised when
    things are expected to go wrong.

   Don’t let the fear that testing can’t catch all bugs stop
    you from writing the tests that will catch most bugs.
   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
The End

To top