Challenges


Challenges

Exercise 1 Small Steps.

Pick a refactoring and identify a place where the approach builds in small steps even though larger steps could work.

See Appendix A for solutions.

Exercise 2 Simple Design.
  1. Justify each of Beck's rules for simple design.

  2. Why are these rules in priority order? Can you find an example where communication overrides avoidance of duplication?

See Appendix A for solutions.



Conclusion

As you use refactorings, and as you develop new ones, use them in such a way that the system moves from good state to good state. Prefer a small steps but safer approach to a fast but not always safe approach when you refactor. Keep the refactoring cycle in mind.


Chapter 3. Measured Smells

The smells in this chapter are similar. They're dead easy to detect. They're objective (once you decide on a way to count and a maximum acceptable score). They're odious.

And, they're common.

You can think of these smells as being caught by a software metric. Each metric tends to catch different aspects of why code isn't as good as it could be. Some metrics measure variants of code length; others try to measure the connections between methods or objects; others measure a distance from an ideal.

Most metrics seem to correlate with length, so I tend to worry about size first (usually noticeable as a Large Class or Long Method). But if a metric is easy to compute, I'll use it as an indicator that some section of code deserves a closer look.

Metrics are indicators, not absolutes. It's very easy to get into the trap of making numbers without addressing the total complexity. So don't refactor just for a better number; make sure it really improves your code.


Smells Covered

  • Comments

  • Long Method

  • Large Class

  • Long Parameter List


Comments

Symptoms

  • Comment symbols ( // or /* ) appear in the code. (Some IDEs help by color coding different types of comments.)

Causes

Comments may be present for the best of reasons: The author realizes that something isn't as clear as it could be and adds a comment.

Some comments are particularly helpful:

  • Those that tell why something is done a particular way (or why it wasn't)

  • Those that cite algorithms that are not obvious (where a simpler algorithm won't do)

Other comments can be reflected just as well in the code itself. For example, the goal of a routine can often be communicated as well through the routine's name as it can through a comment.

What to Do

  • When a comment explains a block of code, you can often use Extract Method to pull the block out into a separate method. The comment will often suggest a name for the new method.

  • When a comment explains what a method does (better than the method's name!), use Rename Method using the comment as the basis of the new name.

  • When a comment explains preconditions, consider using Introduce Assertion to replace the comment with code.

Payoff

Improves communication. May expose duplication.

Contraindications

Don't delete comments that are pulling their own weight.

EXERCISE 3 Comments.

Consider this code. (Online at www.xp123.com/rwb )

Matcher.java

 public class Matcher {
    public Matcher() {}
    public boolean match(int[] expected, int[] actual,
        int clipLimit, int delta)
    {

        // Clip "too-large" values
        for (int i = 0; i < actual.length; i++)
            if (actual[i] > clipLimit)
                actual[i] = clipLimit;

        // Check for length differences
        if (actual.length != expected.length)
            return false;

        // Check that each entry within expected +/- delta
        for (int i = 0; i < actual.length; i++)
            if (Math.abs(expected[i] - actual[i]) > delta)
                return false;

        return true;
    }
} 

MatcherTest.java

 import junit.framework.TestCase;

public class MatcherTest extends TestCase {
    public MatcherTest(String name) {super(name);}

    public void testMatch() {
        Matcher matcher = new Matcher();

        int[] expected = new int[] {10, 50, 30, 98};
        int clipLimit = 100;
        int delta = 5;

        int[] actual = new int[] {12, 55, 25, 110};

        assertTrue(matcher.match(expected, actual, clipLimit, delta));

        actual = new int[] {10, 60, 30, 98};
        assertTrue(!matcher.match(expected, actual, clipLimit, delta));
          actual = new int[] {10, 50, 30};
          assertTrue(!matcher.match(expected, actual, clipLimit, delta));
          }
} 
  1. Use Extract Method to make the comments in match() redundant.

  2. Can everything important about the code be communicated using the code alone? Or do comments have a place?

  3. Find some code you wrote recently. Odds are good that you commented it. Can you eliminate the need for some of those comments by making the code reflect your intentions more directly?

See Appendix A for solutions.