Je lis et travaille actuellement sur "Clean Code: A Handbook of Agile Software Craftsmanship" de Robert C. Martin. L'auteur explique comment une fonction doit faire une seule chose, et donc être relativement courte. Plus précisément, Martin écrit:
Cela implique que les blocs contenus dans les instructions if, les instructions else, les instructions while, etc. doivent être d'une ligne. Cette ligne devrait probablement être un appel de fonction. Non seulement cela maintient la fonction englobante petite, mais cela ajoute également une valeur documentaire car la fonction appelée dans le bloc peut avoir un nom bien descriptif.
Cela implique également que les fonctions ne doivent pas être suffisamment grandes pour contenir des structures imbriquées. Par conséquent, le niveau de retrait d'une fonction ne doit pas être supérieur à un ou deux. Ceci, bien sûr, rend les fonctions plus faciles à lire et à comprendre
Cela a du sens, mais semble entrer en conflit avec des exemples de ce que je considère comme du code propre. Prenons par exemple la méthode suivante:
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
}
}
Ce code est extrait du référentiel de code source d'Apache Commons à l' adresse : https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/primes/SmallPrimes.java
La méthode me semble très lisible. Pour les implémentations d'algorithmes comme celle-ci (implémentation du test de probabilité probabiliste de Miller-Rabin), est-il approprié de conserver le code tel quel et de le considérer comme `` propre '', tel que défini dans le livre? Ou serait-ce même quelque chose de déjà aussi lisible que cela tirerait de l'extraction de méthodes pour faire de l'algorithme essentiellement une série d'appels à des fonctions qui "ne font qu'une chose"? Un exemple rapide d'une extraction de méthode pourrait être de déplacer les trois premières instructions if vers une fonction comme:
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;
}
Remarque: Cette question est différente du doublon possible (bien que cette question me soit également utile), car j'essaie de déterminer si je comprends l'intention de l'auteur de Clean Code et je fournis un exemple spécifique pour rendre les choses plus béton.
la source
Réponses:
Le «code propre» n'est pas une fin en soi, c'est un moyen pour une fin. Le principal objectif de la refonte de fonctions plus grandes en fonctions plus petites et de nettoyer le code d'autres manières est de maintenir le code évolutif et maintenable.
En choisissant un algorithme mathématique très spécifique comme le test principal "Miller-Rabin" dans un manuel, la plupart des programmeurs ne veulent pas le faire évoluer. Leur objectif standard est de le transférer correctement du pseudo-code du manuel dans le langage de programmation de leur environnement. À cette fin, je recommanderais de suivre le manuel le plus près possible, ce qui signifie généralement de ne pas refactoriser.
Cependant, pour quelqu'un qui travaille en tant que mathématicien dans ce domaine qui essaie de travailler sur cet algorithme et de le changer ou de l'améliorer, à mon humble avis, diviser cette fonction en plus petites et bien nommées, ou remplacer le groupe de "nombres magiques" par des constantes nommées, peut aider à apporter des modifications au code plus facilement comme pour tout autre type de code.
la source