Complessità ciclica quando si chiama lo stesso metodo più volte

12

Grazie a una domanda su Code Review Sono entrato in un piccolo disaccordo (che essenzialmente è un'opportunità per imparare qualcosa) su cosa sia esattamente la complessità ciclomatica per il codice sottostante.

public static void main(String[] args) {
    try {
        thro();
        thro();
        thro();
        thro();
        thro();
        thro();
        thro();
    }
    catch (NullPointerException e) {
    }
}

private static Random random = new Random();

public static void thro() throws NullPointerException {
    if (random.nextBoolean())
        throw new NullPointerException();
    System.out.println("No crash this time");
}

Quando si scrive questo codice in Eclipse e si utilizza il plug-in per le metriche di Eclipse , mi viene detto che la complessità ciclica di McCabe per il metodo principale è 2, e per il metodo thro dice 2.

Tuttavia, qualcun altro mi dice che la complessità di chiamare thro più volte è number of calls * method complexity , e quindi afferma che la complessità del metodo principale è 7 * 2 = 14.

Misuriamo cose diverse? Possiamo essere entrambi corretti? O qual è la reale complessità ciclomatica qui?

    
posta Simon Forsberg 29.11.2013 - 15:44
fonte

2 risposte

9

Quando ho capito bene, la Cyclomatic Complexity di main è 8 - questo è il numero di linearmente indipendenti percorsi attraverso il codice. O ottieni un'eccezione su una delle sette linee, o nessuna, ma mai più di una. Ciascuno di questi possibili "punti di eccezione" corrisponde esattamente a un percorso diverso attraverso il codice.

Credo che quando McCabe ha inventato quella metrica, non aveva in mente linguaggi di programmazione con la gestione delle eccezioni in mente.

    
risposta data 29.11.2013 - 16:20
fonte
5

Essendo "l'altro ragazzo", risponderò qui, e sii preciso su ciò che dico (che non ero particolarmente preciso con gli altri tipi di forma).

Usando l'esempio di codice sopra, calcolo la complessità ciclomatica come 8, e ho commenti nel codice per mostrare come lo calcolo. Per descrivere i percorsi considererò un ciclo riuscito attraverso tutti il thro() chiama il "percorso" del codice "principale" (o "CP = 1"):

public static void main(String[] args) {
  try {
             // This is the 'main' Code Path: CP = 1
    thro();  // this has a branch, can succeed CP=1 or throw CP=2
    thro();  // this has a branch, can succeed CP=1 or throw CP=3
    thro();  // this has a branch, can succeed CP=1 or throw CP=4
    thro();  // this has a branch, can succeed CP=1 or throw CP=5
    thro();  // this has a branch, can succeed CP=1 or throw CP=6
    thro();  // this has a branch, can succeed CP=1 or throw CP=7
    thro();  // this has a branch, can succeed CP=1 or throw CP=8
  }
  catch (NullPointerException e) {
  }
}

Quindi, conto 8 percorsi di codice in questo metodo principale, che per me è una complessità ciclomatica di 8.

In termini Java, ogni meccanismo per uscire da una funzione conta sulla sua complessità, quindi, un metodo che ha uno stato di successo e, ad esempio, genera fino a 3 eccezioni, ha 4 percorsi di uscita documentati.

La complessità di un metodo che chiama tale funzione è:

CC(method) = 1 + sum (methodCallComplexity - 1)

Penso che altre cose da considerare, è che, a mio parere, la clausola catch non non contribuisca alla complessità del metodo, il catch è semplicemente l'obiettivo di una throws branch, e quindi un catch catch che è il target di più throw s conta 1 volta per ogni throw , e non solo una volta per tutto.

    
risposta data 29.11.2013 - 16:31
fonte

Leggi altre domande sui tag