Legacy code example

Software concepts are often easiest to explain through code, and this one is no exception. We have seen and worked with the Tic-Tac-Toe application (see Chapter 3, Red-Green-Refactor – From Failure Through Success until Perfection). The following code performs position validation:

public class TicTacToe { 

public void validatePosition(int x, int y) { if (x < 1 || x > 3) { throw new RuntimeException("X is outside board"); } if (y < 1 || y > 3) { throw new RuntimeException("Y is outside board"); } } }

The specification that corresponds with this code is as follows:

public class TicTacToeSpec { 
@Rule public ExpectedException exception = ExpectedException.none();
private TicTacToe ticTacToe; @Before public final void before() { ticTacToe = new TicTacToe(); } @Test public void whenXOutsideBoardThenRuntimeException() { exception.expect(RuntimeException.class); ticTacToe.validatePosition(5, 2); } @Test public void whenYOutsideBoardThenRuntimeException() { exception.expect(RuntimeException.class); ticTacToe.validatePosition(2, 5); } }

The JaCoCo report indicates that everything is covered (except the last line, the method's closing bracket):

As we believe we have good coverage, we can perform an automatic and safe refactor (fragment):

public class TicTacToe { 
 
  public void validatePosition(int x, int y) { 
    if (isOutsideTheBoard(x)) { 
      throw new RuntimeException("X is outside board"); 
    } 
    if (isOutsideTheBoard(y)) { 
      throw new RuntimeException("Y is outside board"); 
    } 
  } 
 
  private boolean isOutsideTheBoard(final int position) { 
    return position < 1 || position > 3; 
  } 
} 

This code should be ready, as the tests are successful and it has very good test coverage.

Maybe you have already realized as much, but there is a catch. The message in the RuntimeException block is not checked for correctness; even the code coverage shows it as covering all the branches in that line.

What is coverage all about? 
Coverage is a measure used to describe the degree to which the source code of a program is tested by a particular test suite. Source: http://en.wikipedia.org/wiki/Code_coverage.

Let's imagine a single end-to-end test that covers an easy part of the code. This test will get you a high coverage percentage, but not much security, as there are many other parts that are still not covered.

We have already introduced legacy code in our codebase—the exception messages. There might be nothing wrong with this as long as this is not an expected behavior—no one should depend on exception messages, not programmers to debug their programs, or logs, or even users. Those parts of the program that are not covered by tests are likely to suffer regressions in the near future. This might be fine if you accept the risk. Maybe the exception type and the line number are enough.

We have decided to remove the exception message, as it is not tested:

public class TicTacToe { 
 
  public void validatePosition(int x, int y) { 
    if (isOutsideTheBoard(x)) { 
      throw new RuntimeException(""); 
    } 
    if (isOutsideTheBoard(y)) { 
      throw new RuntimeException(""); 
    } 
  } 
 
  private boolean isOutsideTheBoard(final int position) { 
    return position < 1 || position > 3; 
  } 
} 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.62.168