Attualmente sto leggendo Building Maintainable Software di Joost Visser e alcune delle linee guida di manutenzione che raccomandano includono: A) ogni unità / metodo dovrebbe essere breve (meno di 15 linee per metodo) e B) i metodi dovrebbero avere un basso < a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity" title="Cyclomatic_complexity"> complessità ciclomatica . Suggerisce che entrambe queste linee guida aiutano con i test.
L'esempio che segue è tratto dal libro che spiega come avrebbero rifattorizzato un metodo complesso per ridurre la complessità ciclomatica per metodo.
Prima:
public static int calculateDepth(BinaryTreeNode<Integer> t, int n) {
int depth = 0;
if (t.getValue() == n) {
return depth;
} else {
if (n < t.getValue()) {
BinaryTreeNode<Integer> left = t.getLeft();
if (left == null) {
throw new TreeException("Value not found in tree!");
} else {
return 1 + calculateDepth(left, n);
}
} else {
BinaryTreeNode<Integer> right = t.getRight();
if (right == null) {
throw new TreeException("Value not found in tree!");
} else {
return 1 + calculateDepth(right, n);
}
}
}
}
Dopo:
public static int calculateDepth(BinaryTreeNode<Integer> t, int n) {
int depth = 0;
if (t.getValue() == n)
return depth;
else
return traverseByValue(t, n);
}
private static int traverseByValue(BinaryTreeNode<Integer> t, int n) {
BinaryTreeNode<Integer> childNode = getChildNode(t, n);
if (childNode == null) {
throw new TreeException("Value not found in tree!");
} else {
return 1 + calculateDepth(childNode, n);
}
}
private static BinaryTreeNode<Integer> getChildNode(
BinaryTreeNode<Integer> t, int n) {
if (n < t.getValue()) {
return t.getLeft();
} else {
return t.getRight();
}
}
Nella loro giustificazione dichiarano (sottolineatura mia):
Argomento:
“Replacing one method with McCabe 15 by three methods with McCabe 5 each means that overall McCabe is still 15 (and therefore, there are 15 control ow branches overall). So nothing is gained.”
Argomento del contatore:
Of course, you will not decrease the overall McCabe complexity of a system by refactoring a method into several new methods. But from a maintainability perspective, there is an advantage to doing so: it will become easier to test and understand the code that was written. So, as we already mentioned, newly written unit tests allow you to more easily identify the root cause of your failing tests.
Domanda: come è più facile testare?
In base alle risposte a questa domanda, < a href="https://stackoverflow.com/questions/1583363/how-to-unit-test-private-methods-in-bdd-tdd"> questa domanda, questo domanda, questo domanda e this blog non dovremmo testare direttamente i metodi privati. Il che significa che dobbiamo testarli tramite i metodi pubblici che li usano. Quindi, tornando all'esempio nel libro, se stiamo testando i metodi privati tramite il metodo pubblico, allora come fa l'unità a migliorare le funzionalità o a cambiare per quello?