В настоящее время я читаю и работаю над «Чистым кодом: Справочник по мастерству гибкого программного обеспечения» Роберта Мартина. Автор говорит о том, как функция должна делать только одну вещь и, следовательно, быть относительно короткой. Конкретно Мартин пишет:
Это означает, что блоки внутри операторов if, операторов else, операторов while и т. Д. Должны быть длиной в одну строку. Вероятно, эта строка должна быть вызовом функции. Это не только уменьшает объем включаемой функции, но также добавляет документальное значение, поскольку вызываемая внутри блока функция может иметь приятное описательное имя.
Это также подразумевает, что функции не должны быть достаточно большими, чтобы содержать вложенные структуры. Следовательно, уровень отступа функции не должен быть больше одного или двух. Это, конечно, облегчает чтение и понимание функций
Это имеет смысл, но, кажется, вступает в противоречие с примерами того, что я вижу как чистый код. Возьмите следующий метод для примера:
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
}
}
Этот код взят из репозитория исходного кода Apache Commons по адресу: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/primes/SmallPrimes.java
Метод выглядит очень читабельным для меня. Для реализаций алгоритма, подобных этой (реализация вероятностного критерия простоты Миллера-Рабина), подходит ли сохранить код как есть и все еще считать его «чистым», как определено в книге? Или даже что-то уже столь же читаемое, как эта выгода от извлечения методов, делающих алгоритм по существу последовательным вызовом функций, которые «делают только одну вещь»? Одним из быстрых примеров извлечения метода может быть перемещение первых трех операторов if в такую функцию:
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;
}
Примечание. Этот вопрос отличается от возможного дубликата (хотя этот вопрос и мне полезен), потому что я пытаюсь определить, понимаю ли я намерение автора Чистого кода и приведу конкретный пример, чтобы сделать вещи более бетон.