2014-09-15 11 views
5

wolę ten styl pisania z pierwszych zwrotów:stwierdzenia wcześniejszego powrotu i Złożoność cykliczna

public static Type classify(int a, int b, int c) { 
    if (!isTriangle(a, b, c)) { 
     return Type.INVALID; 
    } 
    if (a == b && b == c) { 
     return Type.EQUILATERAL; 
    } 
    if (b == c || a == b || c == a) { 
     return Type.ISOSCELES; 
    } 
    return Type.SCALENE; 
} 

Niestety, każdy return oświadczenie zwiększa złożoność cyclomatic metrykę obliczoną przez sonar. Rozważmy taką alternatywę:

public static Type classify(int a, int b, int c) { 
    final Type result; 
    if (!isTriangle(a, b, c)) { 
     result = Type.INVALID; 
    } else if (a == b && b == c) { 
     result = Type.EQUILATERAL; 
    } else if (b == c || a == b || c == a) { 
     result = Type.ISOSCELES; 
    } else { 
     result = Type.SCALENE; 
    } 
    return result; 
} 

cyklomatyczna złożoność tego ostatniego podejścia zgłoszonych przez Sonar jest niższa niż pierwsza, przez 3. Powiedziano mi, że może to być wynikiem niewłaściwej implementacji metryki CC. Czy też Sonar jest poprawny, a to jest naprawdę lepsze? Te pytania związane wydają się nie zgodzić z tym:

https://softwareengineering.stackexchange.com/questions/118703/where-did-the-notion-of-one-return-only-come-from

https://softwareengineering.stackexchange.com/questions/18454/should-i-return-from-a-function-early-or-use-an-if-statement

Jeśli dodać wsparcie dla kilku więcej rodzajów trójkątów, oświadczenia return doda się do znaczącej różnicy w metrykę i przyczyny naruszenie sonaru. Nie chcę przyklejać metody do metody // NOSONAR, ponieważ może to maskować inne problemy poprzez dodanie nowych funkcji/błędów do metody w przyszłości. Używam więc drugiej wersji, mimo że jej nie lubię. Czy istnieje lepszy sposób poradzenia sobie z sytuacją?

+0

Według http://en.wikipedia.org/wiki/Cyclomatic_complexity, CC jest liczba liniowo niezależnych ścieżek poprzez funkcję, która jest w obu przypadkach 4. Czy Sonar mówi ci coś innego? –

+1

Yeap. Sonar dodaje +1 dla każdej instrukcji 'return'. Jest to zasada 'squid: MethodCyclomaticComplexity': https://dev.eclipse.org/sonar/rules/show/squid:MethodCyclomaticComplexity Wcześniejsza reguła (ale teraz przestarzała na rzecz squid) nie miała tego ograniczenia: https: // dev.eclipse.org/sonar/rules/show/checkstyle:com.puppycrawl.tools.checkstyle.checks.metrics.CyclomaticComplexityCheck – janos

+0

, więc to pytanie naprawdę oznacza "jak zapobiec Sonarowi od obliczenia CC źle" - co nie jest dobre pasuje do tej witryny. Takie pytania są lepiej umieszczone na stackoverflow. Zgłaszam to pytanie do migracji. –

Odpowiedz

2

Naprawdę nie jest to odpowiedź, ale zbyt długo na komentarz.

Ta zasada SONAR wydaje się być całkowicie zepsuta. Można przepisać

b == c || a == b || c == a 

jak

b == c | a == b | c == a 

i zdobyć dwa punkty w tej dziwnej grze (a może nawet jakiś prędkością jak rozgałęzienia jest drogie, ale jest to w gestii JITc, w każdym razie).

The old rule twierdzi, że cykliczna złożoność jest związana z liczbą testów. The new one nie, i to dobrze, ponieważ oczywiście liczba sensownych testów dla twoich obydwu snippetów jest dokładnie taka sama.

Czy istnieje lepszy sposób radzenia sobie z sytuacją?

Faktycznie, mam odpowiedź: Aby korzystać każdy wcześniejszy powrót | zamiast || raz. : D

Teraz poważnie: Wystąpił błąd z prośbą o wyłączenie jednej reguły, która jest oznaczona jako naprawiona. Nie patrzę dalej.

2

Twoje pytanie dotyczy https://jira.codehaus.org/browse/SONAR-4857. Na razie wszystkie analizatory SonarQube mieszają złożoność cykliczną i istotną złożoność. Z teoretycznego punktu widzenia instrukcja return nie powinna zwiększać wartości cc, a ta zmiana będzie miała miejsce w ekosystemie SQ.

+0

Dzięki! Jakieś pomysły kiedy? – janos

+1

Na pewno do końca roku, ale na razie nie może być bardziej precyzyjny. –

0

Ponieważ pytanie dotyczy również wcześniejszych zwrotów jako stylu kodowania, pomocne byłoby rozważenie wpływu rozmiaru na styl powrotu. Jeśli metoda lub funkcja jest mała, mniej niż powiedzmy 30 linii, wczesne zwroty nie stanowią problemu, ponieważ każdy czytający kod może zobaczyć całą metodę na pierwszy rzut oka, w tym wszystkie zwroty.W większych metodach lub funkcjach wczesny powrót może być pułapką nieumyślnie ustawioną dla czytnika. Jeśli wczesny powrót nastąpi powyżej kodu, który czyta czytelnik, a czytelnik nie wie, że powrót jest powyżej lub zapomina, że ​​jest powyżej, czytelnik źle zrozumie kod. Kod produkcyjny może być zbyt duży, aby zmieścić się na jednym ekranie.

Tak więc ktokolwiek zarządza bazą kodu dla złożoności, powinien pozwalać na wielkość metody w przypadkach, gdy złożoność wydaje się być problemem. Jeśli kod zajmuje więcej niż jeden ekran, bardziej pedantyczny styl powrotu może być uzasadniony. Jeśli metoda lub funkcja jest niewielka, nie przejmuj się nią.

(używam Sonar i doświadczyli tego samego problemu.)

+1

Zdecydowanie się nie zgadzam. Masz rację z częścią, która w małej metodzie, wczesne zwroty są w porządku. W rzeczywistości w niewielkiej metodzie wszystko jest w porządku. W dużej metodzie wszystko stanowi problem i właśnie o to chodzi. Dlaczego ktoś pisze metody powyżej 30 linii? Patrząc na kod, który napisałem wczoraj na pół snu, widzę bałagan i bałagan to wielkie metody (około 30 linii). ** Pozbądź się wielkich metod **, a wszystko będzie dobrze. ** Jeśli kod zajmuje więcej niż jeden ekran, refaktor. ** – maaartinus