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.
quelle
Antworten:
"Clean Code" ist kein Selbstzweck, sondern ein Mittel zum Zweck. Der Hauptzweck der Umgestaltung größerer Funktionen in kleinere und der Bereinigung des Codes auf andere Weise besteht darin, den Code entwicklungsfähig und wartbar zu halten.
Wenn die meisten Programmierer einen so spezifischen mathematischen Algorithmus wie den "Miller-Rabin" -Primetest aus einem Lehrbuch auswählen, möchten sie ihn nicht weiterentwickeln. Ihr Standardziel ist es, es vom Pseudocode des Lehrbuchs korrekt in die Programmiersprache ihrer Umgebung zu übertragen. Zu diesem Zweck würde ich empfehlen, das Lehrbuch so genau wie möglich zu befolgen, was normalerweise bedeutet, nicht umzugestalten.
Für jemanden, der als Mathematiker auf diesem Gebiet arbeitet und versucht, an diesem Algorithmus zu arbeiten und ihn zu ändern oder zu verbessern, kann IMHO diese Funktion in kleinere, gut benannte aufteilen oder die Gruppe der "magischen Zahlen" durch benannte Konstanten ersetzen helfen dabei, Änderungen am Code wie bei jeder anderen Art von Code zu vereinfachen.
quelle