Det er ingen hemmelig kode er en komplisert ting å skrive, feilsøke og vedlikeholde som er nødvendig for høy programvarekvalitet. Videre bringer høy kode kompleksitet med seg et høyere nivå av kodefeil, noe som gjør koden dyrere å opprettholde.
så ved å redusere kodekompleksiteten kan vi redusere antall feil og mangler, sammen med levetidskostnaden. Hva er egentlig kompleks kode? Hvordan kan vi objektivt vurdere hvor komplisert et stykke kode er, enten det er en hel kodebase eller en liten funksjon?
i denne artikkelen skal jeg gå gjennom tre kompleksitetsmålinger for å vurdere kodekompleksitet. Disse er:
- Cyclomatic kompleksitet
- Bytt setning og logikk tilstand kompleksitet
- Utvikler ferdighet
jeg vil også gå gjennom noen av fordelene med å vurdere og forstå kode kompleksitet.
Syklomatisk Kompleksitet
I 1976 foreslo Thomas McCabe Snr en beregning for beregning av kodekompleksitet, kalt Syklomatisk Kompleksitet. Det er definert som:
et kvantitativt mål på antall lineært uavhengige baner gjennom programmets kildekode … beregnet ved hjelp av kontrollflyt-grafen til programmet.
hvis Du ikke er kjent med En Kontrollflyt-Graf:
det er en representasjon, ved hjelp av grafnotasjon, av alle baner som kan krysses gjennom et program under utførelsen.
sa mer oversiktlig, jo færre stier gjennom et stykke kode, og jo mindre komplekse disse stiene er, desto lavere Er Syklomatisk Kompleksitet. Som et resultat er koden mindre komplisert. For å demonstrere metriske, la oss bruke tre, noe vilkårlig, gå kodeeksempler.
Eksempel En
func main() { fmt.Println("1 + 1 =", 1+1)}
siden det bare er en bane gjennom funksjonen, har Den En Cyclomatic Complexity score på 1, som vi kan finne ved å kjøre gocyclo på den.
Eksempel To
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) }}
i dette eksemplet henter vi inneværende år, måned og dag. Med denne informasjonen sjekker vi om gjeldende dato er 10.November 2018 med en if/else-tilstand.
hvis det er, skriver koden » Happy go day!»til konsollen. Hvis det ikke er det, skriver det ut «den nåværende måneden er» og navnet på den nåværende måneden. Kodeeksemplet gjøres mer komplisert som hvis betingelsen består av tre underbetingelser. Gitt at, den har en høyere kompleksitet score på 4.
Eksempel Tre
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.") }}
i dette eksemplet skriver vi ut gjeldende måned, basert på verdien month
, hentet fra anropet til time.Now().Date()
. Det er syv baner gjennom funksjonen, en for hver av saksoppgavene og en for standard.
Som et resultat er Dens Syklomatiske Kompleksitet 7. Hvis vi hadde regnet for alle månedene av året, sammen med en standard, ville poengsummen være fjorten. Det skjer fordi Gocyclo bruker følgende beregningsregler:
1 er grunnkompleksiteten til en funksjon
+1 for hver ‘hvis’, ‘for’, ‘sak’, ‘&&’ eller ‘||’
Ved å Bruke disse tre eksemplene kan vi se at ved å ha en standard metrisk for beregning av kodekompleksitet, kan vi raskt vurdere hvor komplisert et stykke kode er.
Vi kan også se hvordan ulike komplekse deler av koden er i forhold til hverandre. Imidlertid Er Syklomatisk Kompleksitet ikke nok alene.
Bryteruttrykk Og Logisk Tilstandskompleksitet
den neste bedømmeren av kodekompleksitet er bryteruttrykk og logisk tilstandskompleksitet. I kodeeksemplet nedenfor har jeg tatt det Andre Go-eksemplet og delt forbindelsen hvis tilstanden i tre nestede forhold; en for hver av de opprinnelige forholdene.
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)}
hvilken er lettere å forstå (eller mindre komplisert), den opprinnelige eller denne? La oss nå bygge videre på dette ved å vurdere følgende tre spørsmål.
- Hva om vi hadde, som vi gjør ovenfor, flere hvis forhold og hver enkelt var ganske komplisert?
- Hva om vi hadde flere hvis forholdene og koden i kroppen til hver enkelt var ganske komplekse?
- ville koden være lettere eller vanskeligere å forstå?
det er rimelig å si at jo større antall nestede forhold og jo høyere kompleksitetsnivå innenfor disse forholdene, desto høyere er kodenes kompleksitet.
Programvareutvikler Ferdighetsnivå
hva med ferdighetsnivået til utvikleren? Ta en titt På C-versjonen av det Andre Go-eksemplet nedenfor.
#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); }}
Teknisk gjør Det hva de andre eksemplene gjør. Det krever imidlertid mer kode for å oppnå det samme resultatet. For å være rettferdig, hvis Jeg hadde større kjennskap Til C, kan koden ikke være lenger Enn Go-eksemplet.
la Oss imidlertid si at dette er minimumskravet for å oppnå det samme resultatet. Hvis du sammenligner de to, gitt Den mer verbose naturen Til Cs syntaks i forhold Til Go, er det vanskeligere å forstå.
hva mer, hvis du ikke hadde noen tidligere erfaring Med C, til tross for en relativt lik Cyclomatic Kompleksitet score, hva ville din oppfatning være?
vil du vurdere koden for å være mindre eller mer komplisert? Så dette er en annen viktig faktor for å forstå kodekompleksitet.
Fordelene Ved Å Måle Programvarekompleksitet
det er fire kjernefordeler ved å måle kodekompleksitet, pluss en ekstra.
Bedre Tester
ved å vite hvor mange uavhengige baner det er gjennom et stykke kode, vet vi hvor mange baner det er å teste.
jeg taler ikke for 100% kodedekning forresten—det er ofte en meningsløs programvaremåling. Imidlertid fortaler jeg alltid for så høyt kodedekning som det er både praktisk og mulig.
så ved å vite hvor mange kodebaner det er, kan vi vite hvor mange baner vi må teste. Som et resultat har du et mål på hvor mange tester som kreves, for å sikre at koden er dekket.
Redusert Risiko
som det gamle ordtaket går:
det er vanskeligere å lese kode enn å skrive den.
Hva mer:
- Koden leses langt mer enn den er skrevet
- en god programvareutvikler bør aldri vurderes av kodelinjene de har skrevet (eller endret), men av kvaliteten på koden de har opprettholdt.
Gitt at ved å redusere kodekompleksiteten, reduserer du risikoen for å introdusere feil; enten de er små eller store, litt pinlige eller konkursfremkallende.
Lavere Kostnader
når risikoen for potensielle defekter reduseres, er det færre feil å finne – og fjerne. Som et resultat reduseres vedlikeholdskostnadene også.
vi har alle sett og er kjent med kostnadene forbundet med å finne feil på de ulike stadiene i en programvares liv, som eksemplifisert i diagrammet nedenfor.
så det er fornuftig at hvis vi forstår kompleksiteten til koden vår, og hvilke seksjoner som er mer kompliserte enn andre, er vi i en langt bedre posisjon for å redusere kompleksiteten.
så ved å redusere denne kompleksiteten, reduserer vi sannsynligheten for å innføre feil. Det flyter inn i alle stadier av en programvares liv.
Større Forutsigbarhet
ved å redusere programvarekompleksiteten kan vi utvikle oss med større forutsigbarhet. Det jeg mener med det er at vi bedre kan si-med tillit-hvor lang tid en del av koden tar å fullføre. Ved å vite dette, er vi bedre i stand til å forutsi hvor lang tid en utgivelse tar å sende.
basert på denne kunnskapen er virksomheten eller organisasjonen bedre i stand til å sette sine mål og forventninger, spesielt de som er direkte avhengige av programvaren. Når dette skjer, er det enklere å sette realistiske budsjetter, prognoser og så videre.
Hjelper Utviklere Å Lære
Å Hjelpe utviklere å lære og vokse er den endelige fordelen av å forstå hvorfor koden deres anses som kompleks. Verktøyene jeg har brukt til å vurdere kompleksitet frem til dette punktet, gjør det ikke.
det de gjør er å gi en samlet eller granulær kompleksitetspoeng. Et omfattende kodekompleksitetsverktøy, For Eksempel Codacy, gjør det imidlertid.
i skjermbildet ovenfor kan vi se at av de seks filene som er oppført, har man en kompleksitet på 30, en poengsum som vanligvis anses som ganske høy.
Syklomatisk kompleksitet er en god indikator for å forstå om kodekvaliteten forverres for en gitt endring. Syklomatisk kompleksitet kan være vanskeligere å begrunne når man ser på det eller sammenligner hele moduler gitt sin uendelige skala og ikke er relatert til modulstørrelsen. Men noe du kan finne nyttig, ser På Codacys Filliste sortert etter prioritet, noe som vil hjelpe deg å forstå hvilke filer som er kandidater med dårlig kodekvalitet, og deretter følge deres moduler.
Det Er En Wrap
dette har også vært en grundig diskusjon om hva kodekompleksitet er, hvordan det vurderes, samt de betydelige fordelene med å redusere det. Mens det er mer å forstå kodekompleksitet enn jeg har dekket her, har vi gått langt for å forstå det.
hvis dette er første gang du hører om begrepet eller lærer om noen av verktøyene, oppfordrer jeg deg til å utforske de koblede artiklene og verktøyene, slik at du lærer mer. Hvis Du ikke koder I Go Eller C, må du google «code complexity tool» pluss programvarespråkene dine. Du er sikker på å finne mange verktøy tilgjengelig.
for flere tips for å forbedre kodekvaliteten, sjekk ut noen andre blogginnlegg Fra Codacy.
Til Slutt, hvis du vil ha et omfattende verktøy for å vurdere kodekvalitet, og en som hjelper utviklerne å lære og vokse, så prøv Codacy.
Codacy brukes av tusenvis av utviklere å analysere milliarder av linjer med kode hver dag!
Det er enkelt Å komme i gang-og gratis! Bare bruk Din GitHub, Bitbucket eller Google-konto for å registrere deg.
KOM I GANG