
A Cyclomatic Complexity egy olyan kódmutató, amelyet számos IDE-ben, például a Visual Studio-ban megtekinthet. Bár ez nem egzakt tudomány, lehetővé teszi, hogy általános képet kapjon a függvények, osztályok és névterek bonyolultságáról, amelyek hasznosak lehetnek a refaktorhoz szükséges kód keresésekor.
Mi a ciklikus komplexitás?
A ciklikus komplexitás alapvetően azt méri, hogy a kód mennyit ágazik el. Valahányszor van egy if
utasítás vagy más vezérlőblokk, mint egy hurok, a ciklomatikus bonyolultság felfelé megy, mivel a grafikon egyre inkább egy fára hasonlít.
Ha a kódját műveletek (függvények, metódushívások, változó hozzárendelések) sorozataként képzeled el, amelyek összekapcsolódnak a vezérlési folyamaton, akkor egy absztrakt grafikont kapsz, amely segítségével jobban megértheted a bonyolultságot. A közös vezérlési áramlásokhoz hasonló if
nyilatkozatok és for
ciklusok, a grafikonok így néznek ki:
A képlet egyszerű; vegye be a grafikon éleinek számát (a mindent összekötő nyilak), és vonja le a grafikon csomópontjainak számát (maguk a műveletek).
Complexity = Edges -- Nodes + 2
Például ennek a kódnak ciklikus bonyolultsága van, mivel nincsenek ágak, és csak újra és újra hívja a WriteLine-t. Mivel csak tökéletesen lineáris kódról van szó, a csomópontok száma törli az élek számát, egy ciklikus komplexitást adva.
public void TestFunction() { Console.WriteLine("Test"); Console.WriteLine("Test"); Console.WriteLine("Test"); Console.WriteLine("Test"); Console.WriteLine("Test"); }
Az elágazásokkal bonyolultabb kódok esetében a bonyolultság nagyobb lesz. Ez a kód, amely a switch
utasítás komplexitása 6, mert a kód sokféle utat követhet. Minden egyes case
A switch utasítás bonyolultabbá teszi, mivel különböző kimenetekhez vezethet, eltérő bemenetekkel.
public void TestFunction(string arg) { switch(arg) { case "one": Console.WriteLine("Test"); break; case "two": Console.WriteLine("Test"); break; case "three": Console.WriteLine("Test"); break; case "four": Console.WriteLine("Test"); break; case "five": Console.WriteLine("Test"); break; } Console.WriteLine("Test"); }
A ciklikus komplexitást csak a függvény keretein belül számoljuk. Ha egy függvény meghív egy másik olyan funkciót, amely nagy ciklikusságú bonyolultsággal rendelkezik, akkor az csak egyetlen csomópontnak számít, és semmit sem ad hozzá a hívóhoz, annak ellenére, hogy technikailag hozzáadja a programot általános értelemben vett komplexitáshoz.
Hasznos a ciklomatikus komplexitás?
A ciklikus komplexitás nem tökéletes mutató. Ez egy nagyon alapvető mutató, és áttekinti a kód árnyalatait. Természetesen továbbra is rendelkezhet szörnyű, alacsony bonyolultságú kóddal, vagy nagyon bonyolult tisztességes kóddal. De általában még mindig nagyon hasznos a körforgalom megismeréséhez, hogy mennyire összetett egy program.
A 6–8 alatti komplexitás többnyire valószínűleg rendben van, amíg maga a kód jól formázott. Bármi, ami 8-15-ig terjed, megkérdőjelezhető, és minden, ami meghaladja a 15-öt, valószínűleg nem nagyszerű. Bármi, ami meghaladja a 25-et, szinte biztosan probléma, hacsak másként nem bizonyítják.
Bár a ciklomatikus bonyolultság az adott funkcióban még nem a világ vége, egy nagyobb problémára utalhat. A bonyolult funkciókat nehezebb fenntartani, és hajlamosabbak a több hibára, mivel több dolog is hibás. A nagyobb komplexitású függvények pedig közvetlenül magasabb komplexitású egységtesztekhez vezetnek, ami a tesztelés nehézségei miatt hosszú távon nehézkessé teszi a kód fenntartását.
A Visual Studio és más IDE-k kiszámítják a teljes osztályok és névterek összesített összetettségét, ami hasznos lehet a legösszetettebb osztályok felkutatásához. Rendezhet a legnagyobb összetettség szerint, és részletezheti az egyes funkciókat.
Gyakran a kódellenőrzés figyelembe veheti a ciklikus bonyolultságot, sőt megjelöli azokat a problémás funkciókat is, amelyek manuális felülvizsgálatra szorulhatnak. Ez nagyon hasznos eszközzé teheti a tiszta és rendezett kódbázis fenntartását.
Rossz kódot keres
Számos IDE, például a Visual Studio, beépített eszközöket kínál a ciklomatikus bonyolultság és más kódmutatók kiszámításához a teljes kódbázison.
Ehhez kattintson a Visual Studio elemzésére, majd kattintson az Elemzés> Kódmérők kiszámítása> Megoldáshoz elemre.
Ekkor megjelenik a „Code Metrics” panel, amely a megoldás lebontását mutatja. A bonyolultság szerint csökkenő sorrendben rendezheti a legproblémásabb névtereket.
A bonyolultság mellett a Visual Studio bemutat egy „Fenntarthatósági indexet” is, amely 0-100 pontértéket mutat a könnyen karbantartható magas szinten, valamint az „Osztálykapcsolás” elemet, amely felsorolja, hogy hány osztályra hivatkoznak az adott funkció vagy osztály.
Itt a Visual Studio rámutatott egy 400 vonalas módszeremre, amely óriási 72-et ért el a bonyolultsági skálán, valamint egy 14/100-at a karbantarthatósági indexen (sárga háromszög-veszélyjelként mutatják be), és 65 különböző osztályra hivatkozik.
Az eredmény alapján közvetlenül a gyász öt szakaszába küldhet. “De ez egy nagyon hosszú korutin, amelynek rengeteg feladata van!” Mondom magamnak, miközben megpróbálom tagadni, hogy az általam írt kód matematikailag rossz, addig a pontig, amikor a Visual Studio figyelmeztetést dob. A 72-es összetettség minden bizonnyal tisztításra szorul.
Ebben az esetben a javítás egyszerű volt – a coroutinnak egy csomó feladata van, ezért ezeket a feladatokat kisebb koroutinokra bontom, és a fő módszert alprogramok hívására cserélem. Az általános kód nem változott, és maga az osztály teljes bonyolultsága sem, de most a fő funkció nem 400 soros szörnyűség.