není to žádný tajný kód je složitá věc psát, ladit a udržovat, což je nezbytné pro vysokou kvalitu softwaru. Vysoká složitost kódu s sebou navíc přináší vyšší úroveň defektů kódu, díky čemuž je údržba kódu nákladnější.
takže snížením složitosti kódu můžeme snížit počet chyb a vad spolu s jeho životními náklady. Co přesně je komplexní kód? Jak můžeme objektivně posoudit, jak složitý je kus kódu, ať už je to celá kódová základna nebo jedna malá funkce?
v tomto článku projdu tři metriky složitosti pro posouzení složitosti kódu. Jedná se o:
- Cyklomatická složitost
- switch statement and logic condition complexity
- Developer skill
také projdu některými výhodami hodnocení a porozumění složitosti kódu.
Cyklomatická složitost
v roce 1976 Thomas McCabe Snr navrhl metriku pro výpočet složitosti kódu, nazvanou Cyklomatická složitost. Je definován jako:
kvantitativní měřítko počtu lineárně nezávislých cest prostřednictvím zdrojového kódu programu … vypočtené pomocí grafu řídicího toku programu.
Pokud nejste obeznámeni s grafem řídicího toku:
jedná se o reprezentaci, pomocí grafu notace, ze všech cest, které by mohly být procházeny prostřednictvím programu během jeho provádění.
řekl přímočařeji, čím méně cest prochází kusem kódu, a čím méně složité jsou tyto cesty, tím nižší je Cyklomatická složitost. V důsledku toho je Kód méně komplikovaný. Pro demonstraci metriky použijeme tři, poněkud libovolné příklady kódu Go.
příklad jedna
func main() { fmt.Println("1 + 1 =", 1+1)}
protože existuje pouze jedna cesta funkcí, má skóre Cyklomatické složitosti 1, které můžeme najít spuštěním gocyclo na něm.
příklad dva
func main() { year, month, day := time.Now().Date() if month == time.November && day == 10 && year == 2018 { fmt.Println("Happy Go day!") } else { fmt.Println("The current month is", month) }}
v tomto příkladu získáváme aktuální rok, měsíc a den. S těmito informacemi pak zkontrolujeme, zda je aktuální datum 10. Listopadu 2018 s podmínkou if / else.
pokud ano, kód vytiskne “ Happy Go day!“na konzoli. Pokud tomu tak není, vytiskne „aktuální měsíc je“ a název aktuálního měsíce. Příklad kódu je komplikovanější, protože podmínka if se skládá ze tří dílčích podmínek. Vzhledem k tomu má vyšší skóre složitosti 4.
příklad tři
func main() { _, month, _ := time.Now().Date() switch month { case time.January: fmt.Println("The current month is January.") case time.February: fmt.Println("The current month is February.") case time.March: fmt.Println("The current month is March.") case time.April: fmt.Println("The current month is April.") case time.May: fmt.Println("The current month is May.") default: fmt.Println("The current month is unknown.") }}
v tomto příkladu tiskneme aktuální měsíc na základě hodnoty month
načtené z volání na time.Now().Date()
. Existuje sedm cest přes funkci, jeden pro každý z příkazů případu a jeden pro výchozí.
v důsledku toho je jeho Cyklomatická složitost 7. Kdybychom ale počítali všechny měsíce v roce spolu s defaultem, jeho skóre by bylo čtrnáct. K tomu dochází, protože Gocyclo používá následující pravidla výpočtu:
1 je základní složitost funkce
+1 pro každý případ „if“, „for“,“‚, ‚&&‘ nebo ‚||‘
pomocí těchto tří příkladů můžeme vidět, že tím, že máme standardní metriku pro výpočet složitosti kódu, můžeme rychle posoudit, jak složitý je kus kódu.
můžeme také vidět, jak různé složité části kódu jsou ve srovnání s ostatními. Cyklomatická složitost však sama o sobě nestačí.
Switch Statement and Logic Condition Complexity
dalším hodnotitelem složitosti kódu je switch statement and logic condition complexity. V níže uvedeném příkladu kódu jsem vzal druhý příklad Go a rozdělil podmínku compound if do tří vnořených podmínek; jeden pro každou z původních podmínek.
func main() { year, month, day := time.Now().Date() output := fmt.Sprintf("The current month is %s", month) if month == time.November { if day == 13 { if year == 2018 { output = fmt.Sprintf("Happy Go day!") } } } fmt.Println(output)}
který je srozumitelnější (nebo méně komplikovaný), původní nebo tento? Nyní na tom stavíme zvážením následujících tří otázek.
- Co kdybychom měli, jak to děláme výše, více podmínek if a každý z nich byl docela složitý?
- co kdybychom měli více, kdyby podmínky a kód v těle každého z nich byly poměrně složité?
- byl by kód jednodušší nebo těžší pochopit?
je spravedlivé říci, že čím větší je počet vnořených podmínek a čím vyšší je úroveň složitosti v těchto podmínkách, tím vyšší je složitost kódu.
úroveň dovedností vývojáře softwaru
a co úroveň dovedností vývojáře? Podívejte se na verzi C druhého příkladu Go níže.
#include <stdio.h>#include <time.h>#include <string.h>int main(){ time_t t = time(NULL); struct tm tm = *localtime(&t); const char * months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; if (tm.tm_year == 2018 && strncmp(months, "November", strlen(months)) == 0 && tm.tm_mday == 10) { printf("Happy C Day!.\n"); } else { printf("The current month is %s.\n", months); }}
technicky to dělá to, co dělají ostatní příklady. K dosažení stejného výsledku však vyžaduje více kódu. Abych byl spravedlivý, kdybych měl větší znalost C, kód by nemusel být delší než příklad Go.
řekněme však, že toto je minimum potřebné k dosažení stejného výsledku. Pokud porovnáte tyto dva, vzhledem k podrobnější povaze syntaxe C ve srovnání s Go, je to těžší pochopit.
a co víc, pokud byste neměli předchozí zkušenosti s C, navzdory poměrně podobnému skóre Cyklomatické složitosti, jaké by bylo vaše vnímání?
považovali byste kód za méně nebo složitější? Toto je další zásadní faktor pro pochopení složitosti kódu.
výhody složitosti měřicího softwaru
existují čtyři hlavní výhody složitosti měřicího kódu plus jedna navíc.
lepší testy
tím, že víme, kolik nezávislých cest existuje prostřednictvím kódu, víme, kolik cest je třeba otestovat.
nejsem zastáncem 100% pokrytí kódem mimochodem—to je často nesmyslná softwarová metrika. Vždy se však zasazuji o co nejvyšší úroveň pokrytí kódem, jak je praktické a možné.
takže tím, že víme, kolik cest kódu existuje, můžeme vědět, kolik cest musíme otestovat. Výsledkem je, že máte míru, kolik testů je zapotřebí, minimálně, aby se zajistilo, že kód je pokryt.
snížené riziko
jak říká staré přísloví:
je těžší číst kód než psát.
a co víc:
- kód se čte mnohem více, než je napsáno
- dobrý vývojář softwaru by nikdy neměl být hodnocen řádky kódu, které napsal (nebo změnil), ale kvalitou kódu, který udržoval.
vzhledem k tomu, že snížením složitosti kódu snížíte riziko zavlečení vad; ať už jsou malé nebo velké, mírně trapné nebo vyvolávající bankrot.
nižší náklady
když se sníží riziko potenciálních vad, je méně vad k nalezení a odstranění. V důsledku toho se také snižují náklady na údržbu.
všichni jsme viděli a jsou obeznámeni s náklady spojenými s nalezením závad v různých fázích života softwaru, jak je znázorněno v tabulce níže.
takže dává smysl, že pokud pochopíme složitost našeho kódu a které sekce jsou složitější než jiné, pak jsme v mnohem lepší pozici, abychom tuto složitost snížili.
takže snížením této složitosti snižujeme pravděpodobnost zavlečení defektů. To proudí do všech fází života softwaru.
větší předvídatelnost
snížením složitosti softwaru se můžeme vyvíjet s větší předvídatelností. Tím myslím to, že jsme schopni s jistotou říci, jak dlouho trvá dokončení části kódu. Tím, že to víme, jsme lépe schopni předpovědět, jak dlouho trvá vydání k odeslání.
na základě těchto znalostí je podnik nebo organizace lépe schopna stanovit své cíle a očekávání, zejména ty, které jsou přímo závislé na uvedeném softwaru. Když k tomu dojde, je snazší nastavit realistické rozpočty, prognózy atd.
pomáhá vývojářům učit se
pomáhá vývojářům učit se a růst je konečným přínosem pochopení, proč je jejich kód považován za složitý. Nástroje, které jsem použil k posouzení složitosti až do tohoto bodu, to nedělají.
poskytují celkové nebo granulární skóre složitosti. Komplexní nástroj pro složitost kódu, jako je Codacy, však ano.
na obrázku výše vidíme, že ze šesti uvedených souborů má jeden složitost 30, což je obvykle považováno za poměrně vysoké skóre.
Cyklomatická složitost je skvělým ukazatelem pro pochopení, zda se kvalita kódu zhoršuje pro danou změnu. Cyklomatická složitost může být těžší pochopit, když se na ni díváte nebo porovnáváte celé moduly vzhledem k jeho nekonečnému měřítku a nesouvisí s velikostí modulu. Něco, co by vám mohlo připadat užitečné, je podívat se na seznam souborů Codacy seřazený podle priority, což vám pomůže pochopit, které soubory jsou kandidáty špatné kvality kódu, a následně jejich moduly.
to je zábal
také to byla hloubková diskuse o tom, co je složitost kódu, jak je hodnocena, stejně jako významné výhody jeho snížení. I když je zde více pochopení složitosti kódu, než jsem zde popsal, prošli jsme dlouhou cestu k jeho pochopení.
pokud jste poprvé slyšeli o termínu nebo se dozvěděli o některém z nástrojů, doporučuji vám prozkoumat propojené články a nástroje, abyste se dozvěděli více. Pokud nemáte kód V Go nebo C, pak google „Code complexity tool“ plus váš softwarový jazyk(y). Určitě najdete mnoho dostupných nástrojů.
pro více tipů, jak zlepšit kvalitu kódu podívejte se na některé další blogové příspěvky z Codacy.
a konečně, pokud chcete komplexní nástroj pro hodnocení kvality kódu a ten, který pomáhá vývojářům učit se a růst, vyzkoušejte Codacy.
Codacy používají tisíce vývojářů k analýze miliard řádků kódu každý den!
Začínáme je snadné-a zdarma! Stačí se zaregistrovat pomocí účtu GitHub, Bitbucket nebo Google.
ZAČÍT