Atualmente, estou lendo e trabalhando em "Código Limpo: Um Manual de Artesanato em Software Ágil", de Robert C. Martin. O autor fala sobre como uma função deve fazer apenas uma coisa e, portanto, é relativamente curta. Martin escreve especificamente:
Isso implica que os blocos dentro de instruções if, else, while e etc. devem ter uma linha. Provavelmente essa linha deve ser uma chamada de função. Isso não apenas mantém a função anexa pequena, mas também agrega valor documental, porque a função chamada dentro do bloco pode ter um nome bem descritivo.
Isso também implica que as funções não devem ser grandes o suficiente para conter estruturas aninhadas. Portanto, o nível de recuo de uma função não deve ser maior que um ou dois. Isso, é claro, facilita as funções de ler e entender
Isso faz sentido, mas parece entrar em conflito com exemplos do que eu vejo como código limpo. Pegue o seguinte método, por exemplo:
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
}
}
Este código foi retirado do repositório de código-fonte do Apache Commons em: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/primes/SmallPrimes.java
O método parece muito legível para mim. Para implementações de algoritmos como este (implementação do Teste Probabilístico de Miller-Rabin), é adequado manter o código como está e ainda o considerar 'limpo', conforme definido no livro? Ou mesmo algo já tão legível como esse se beneficiaria da extração de métodos para tornar o algoritmo essencialmente uma série que chama funções que "fazem apenas uma coisa"? Um exemplo rápido de uma extração de método pode ser mover as três primeiras instruções if para uma função como:
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;
}
Nota: Essa pergunta é diferente da duplicata possível (embora também seja útil para mim), porque estou tentando determinar se estou entendendo a intenção do autor do Código Limpo e estou fornecendo um exemplo específico para tornar as coisas mais fáceis. concreto.