Ich lese und arbeite gerade an "Clean Code: Ein Handbuch für agile Software-Handwerkskunst" von Robert C. Martin. Der Autor spricht darüber, wie eine Funktion nur eines tun und daher relativ kurz sein soll. Insbesondere schreibt Martin:
Dies bedeutet, dass die Blöcke in if-Anweisungen, else-Anweisungen, while-Anweisungen usw. eine Zeile lang sein sollten. Wahrscheinlich sollte diese Zeile ein Funktionsaufruf sein. Dies hält nicht nur die umschließende Funktion klein, sondern erhöht auch den Dokumentationswert, da die innerhalb des Blocks aufgerufene Funktion einen gut beschreibenden Namen haben kann.
Dies bedeutet auch, dass Funktionen nicht groß genug sein sollten, um verschachtelte Strukturen aufzunehmen. Daher sollte der Einzugspegel einer Funktion nicht größer als eins oder zwei sein. Dies erleichtert natürlich das Lesen und Verstehen der Funktionen
Dies ist sinnvoll, scheint jedoch im Widerspruch zu Beispielen zu stehen, die ich als sauberen Code betrachte. Nehmen Sie zum Beispiel die folgende Methode:
public static boolean millerRabinPrimeTest(final int n) {
final int nMinus1 = n - 1;
final int s = Integer.numberOfTrailingZeros(nMinus1);
final int r = nMinus1 >> s;
//r must be odd, it is not checked here
int t = 1;
if (n >= 2047) {
t = 2;
}
if (n >= 1373653) {
t = 3;
}
if (n >= 25326001) {
t = 4;
} // works up to 3.2 billion, int range stops at 2.7 so we are safe :-)
BigInteger br = BigInteger.valueOf(r);
BigInteger bn = BigInteger.valueOf(n);
for (int i = 0; i < t; i++) {
BigInteger a = BigInteger.valueOf(SmallPrimes.PRIMES[i]);
BigInteger bPow = a.modPow(br, bn);
int y = bPow.intValue();
if ((1 != y) && (y != nMinus1)) {
int j = 1;
while ((j <= s - 1) && (nMinus1 != y)) {
long square = ((long) y) * y;
y = (int) (square % n);
if (1 == y) {
return false;
} // definitely composite
j++;
}
if (nMinus1 != y) {
return false;
} // definitely composite
}
}
return true; // definitely prime
}
}
Dieser Code stammt aus dem Apache Commons-Quellcode-Repo unter: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/primes/SmallPrimes.java
Die Methode sieht für mich sehr lesbar aus. Ist es für Algorithmus-Implementierungen wie diese (Implementierung des Miller-Rabin Probabilistic Primality Test) geeignet, den Code unverändert zu lassen und ihn dennoch als "sauber" zu betrachten, wie im Buch definiert? Oder würde sogar etwas bereits so Lesbares wie dieses davon profitieren, Methoden zu extrahieren, um den Algorithmus im Wesentlichen zu einer Reihe von Aufrufen von Funktionen zu machen, die "nur eine Sache tun"? Ein schnelles Beispiel für eine Methodenextraktion könnte darin bestehen, die ersten drei if-Anweisungen in eine Funktion wie die folgende zu verschieben:
private static int getTValue(int n)
{
int t = 1;
if (n >= 2047) {
t = 2;
}
if (n >= 1373653) {
t = 3;
}
if (n >= 25326001) {
t = 4;
}
return t;
}
Hinweis: Diese Frage unterscheidet sich von dem möglichen Duplikat (obwohl diese Frage auch für mich hilfreich ist), da ich versuche festzustellen, ob ich die Absicht des Autors von Clean Code verstehe, und ein spezifisches Beispiel gebe, um die Dinge zu verbessern Beton.