Clean Code
JUnit Internals
-
This chapter looks to critique a part of the JUnit implementation and improve upon it
-
JUnit is a test automation framework for Java
-
Listing 15-1 looks at ComparisonCompactorTest.java
- The test suite covers every line of code or bit of functionality on ComparisonCompactor
- Implies confidence in the code working and has been carefully refined by the developers
-
Listing 15-2 looks at the implementation of ComparisonCompactor
- Overall, clean and formatted code
- Clear separation of variables, public and private methods
- Highly cohesive methods
- Few minor issues with naming and long expressions, as well as random "+ 1"s
-
Boy Scout Rule tells us to leave the code cleaner than when we found it
- Remove "f" prefix from variables
- Issues with compact function
- Unencapsulated conditional statement which doesn't convey clear intentions
- Ambiguous variable names expected and actual exists as a member variable but also local variable, they represent different things
public String compact(String message) { if (expected == null || actual == null || areStringsEqual()) return Assert.format(message, expected, actual); findCommonPrefix(); findCommonSuffix(); String expected = compactString(this.expected); String actual = compactString(this.actual); return Assert.format(message, expected, actual); }
public String compact(String message) { if (shouldNotCompact()) return Assert.format(message, expected, actual); findCommonPrefix(); findCommonSuffix(); String compactExpected = compactString(expected); String compactActual = compactString(actual); return Assert.format(message, compactExpected, compactActual); } private boolean shouldNotCompact() { return expected == null || actual == null || areStringsEqual(); }
- Can also invert the conditional to handle the negative case last
public String compact(String message) { if (canBeCompacted()) { findCommonPrefix(); findCommonSuffix(); String compactExpected = compactString(expected); String compactActual = compactString(actual); return Assert.format(message, compactExpected, compactActual); } else { return Assert.format(message, expected, actual); } } private boolean canBeCompacted() { return expected != null && actual != null && !areStringsEqual(); }
- Need to change function name, it might not compact the message if canBeCompacted returns false
- Since the string returns a formatted string after possibly compacting, the name should be formatCompactedComparison
- Compacting logic in if should be extracted to another function, de-coupling the formatting and compacting tasks
public String compact(String message) { if (canBeCompacted()) { compactExpectedAndActual(); return Assert.format(message, compactExpected, compactActual); } else { return Assert.format(message, expected, actual); } } private void compactExpectedAndActual() { findCommonPrefix(); findCommonSuffix(); compactExpected = compactString(expected); compactActual = compactString(actual); return Assert.format(message, compactExpected, compactActual); }
- The prefix and suffix functions aren't consistent with the other two compact functions in returning variables
- Modify the find functions to return the prefix and suffix values, also do a bit of variable renaming within them
- The mentioned "+1"s are a result of suffixIndex and prefixIndex not being 0-based index, just change initialisation value from 1 to 0
-
Following the Boy Scout Rule, the module has been improved despite it being in an already clean state
- Essentially, no module can't be improved further