Problemi nell'afferrare come appare il codice pulito nella vita reale

9

Attualmente sto leggendo e lavorando con "Clean Code: Un manuale di abilità software agile" di Robert C. Martin. L'autore parla di come una funzione dovrebbe fare solo una cosa, e quindi essere relativamente breve. Nello specifico, Martin scrive:

This implies that the blocks within if statements, else statements, while statements, and so on should be one line long. Probably that line should be a function call. Not only does this keep the enclosing function small, but it also adds documentary value because the function called within the block can have a nicely descriptive name.

This also implies that functions should not be large enough to hold nested structures. Therefore, the indent level of a function should not be greater than one or two. This, of course, makes the functions easier to read and understand

Questo ha senso, ma sembra in conflitto con esempi di ciò che vedo come codice pulito. Ad esempio, segui il seguente metodo:

    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
    }
}

Questo codice è preso dal repository del codice sorgente Apache Commons su: link

Il metodo mi sembra molto leggibile. Per implementazioni algoritmiche come questa (implementazione del test di prim'ordine Probabilistic di Miller-Rabin), è appropriato mantenere il codice così com'è e considerarlo ancora "pulito", come definito nel libro? O sarebbe persino già qualcosa di già leggibile come questo vantaggio dall'estrazione di metodi per rendere l'algoritmo essenzialmente una serie di chiamate a funzioni che "fanno una cosa sola"? Un rapido esempio di un'estrazione del metodo potrebbe spostare le prime tre istruzioni if in una funzione come:

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: questa domanda è diversa dal possibile duplicato (anche se questa domanda è utile anche a me), perché sto cercando di determinare se sto capendo l'intenzione dell'autore di Pulisci codice e Sto fornendo un esempio specifico per rendere le cose più concrete.

    
posta 1west 11.08.2017 - 18:24
fonte

1 risposta

17

"Il codice pulito" non è fine a se stesso, è un mezzo per un fine. Lo scopo principale di ridefinire le funzioni più grandi in quelle più piccole e ripulire il codice in altri modi è quello di mantenere il codice evolutivo e mantenibile.

Quando si sceglie un algoritmo matematico molto specifico come il primo test "Miller-Rabin" da un libro di testo, la maggior parte dei programmatori non vuole evolversi. Il loro obiettivo standard è di trasferirlo correttamente dallo pseudo codice del libro di testo nel linguaggio di programmazione del loro ambiente. A tale scopo, consiglierei di seguire il libro di testo il più vicino possibile, che in genere significa non refactoring.

Tuttavia, per qualcuno che lavora come matematico in quel campo che sta cercando di lavorare su quell'algoritmo e lo ha modificato o migliorato, IMHO suddividendo questa funzione in più piccoli, ben denominati, o sostituendo il gruppo di "numeri magici" chiamati costanti, può aiutare a modificare il codice più facilmente come per qualsiasi altro tipo di codice.

    
risposta data 11.08.2017 - 18:50
fonte

Leggi altre domande sui tag