I denne opplæringen vil vi gi deg ni praktiske teknikker for å skrive elegant og lesbar kode. Vi snakker ikke om bestemte arkitekturer, språk eller plattformer. Fokus ligger på å skrive bedre kode. La oss komme i gang.
"Å måle utviklingsprosessen ved hjelp av kodelinjer, er som å måle flybygging fremover etter vekt." - Bill Gates
Hvis du er en utvikler, så har det sikkert vært tider når du har skrevet kode, og etter noen dager, uker eller måneder, så du tilbake til det og sa til deg selv: "Hva gjør dette stykke kode?" Svaret på det spørsmålet kan ha vært "Jeg vet egentlig ikke!" I så fall er det eneste du kan gjøre å gå gjennom koden fra start til slutt, og prøver å forstå hva du tenkte da du skrev det.
Dette skjer for det meste når vi er lat og vi vil bare implementere den nye funksjonen klienten ba om. Vi vil bare få jobben gjort med så liten innsats som mulig. Og når det virker, bryr vi oss ikke om selve koden, fordi klienten aldri vil se stygg sannhet, enn si forstå det. Ikke sant? Feil. I disse dager har samarbeidet med programvare blitt standard og folk vil se, lese og inspisere koden du skriver. Selv om koden din ikke blir gransket av dine kolleger, bør du gjøre det til en vane å skrive klar og lesbar kode. Alltid.
Mesteparten av tiden jobber du ikke alene med et prosjekt. Vi ser ofte stygg kode med variabler som har navn som Jeg
, en
, p
, pro
, og RQS
. Og hvis det virkelig blir dårlig, er dette mønsteret synlig over hele prosjektet. Hvis dette høres kjent, så er jeg ganske sikker på at du har spurt deg selv spørsmålet "Hvordan kan denne personen skrive kode som dette?" Selvfølgelig gjør dette deg enda mer takknemlig når du kommer over klar, lesbar og til og med vakker kode. Klar og ren kode kan leses om sekunder, og det kan spare deg og dine kolleger mye tid. Det bør være din motivasjon for å skrive kvalitetskode.
Vi er alle enige om at kode skal være lett å forstå. Ikke sant? Det første eksemplet fokuserer på avstand. La oss se på to eksempler.
returnere kjønn == "1"? vekt * (høyde / 10): vekt * (høyde * 10);
hvis (kjønn == "1") returvekt * (høyde / 10); ellers returvekt * (høyde * 10);
Selv om resultatet av disse eksemplene er identisk, ser de ganske annerledes ut. Hvorfor bør du bruke flere kodelinjer hvis du kan skrive mindre? La oss utforske to andre eksempler, noe jeg vedder på at du ser ofte.
for (Node * node = list-> head; node! = NULL; node = node-> neste) print (node-> data);
Node * node = list-> head; hvis (node == NULL) tilbake; mens (node-> next! = NULL) Print (node-> data); node = node-> neste; Hvis (node! = NULL) Skriv ut (node-> data);
Igjen er resultatet av disse eksemplene identiske. Hvilken er bedre? Og hvorfor? Betyr færre kodelinjer bedre kode? Vi vil besøke dette spørsmålet senere i denne opplæringen.
I datavitenskap hører du ofte uttrykket "mindre er mer". Generelt, hvis du kan løse et problem i færre linjer med kode, jo bedre. Det vil nok ta deg mindre tid til å forstå en 200-linjers klasse enn en 500-linjeklasse. Men er dette alltid sant? Ta en titt på følgende eksempler.
reservasjon ((! room = FindRoom (room_id))) || ! Rom-> isOccupied ());
room = FindRoom (room_id); hvis (rom! = NULL) reservasjon (! room-> isOccupied ());
Er du ikke enig i at det andre eksemplet er lettere å lese og forstå? Du må kunne optimalisere for lesbarhet. Selvfølgelig kan du legge til noen få kommentarer til det første eksemplet for å gjøre det lettere å forstå, men det er ikke bedre å utelate kommentarene og skrive kode som er lettere å lese og forstå?
// Bestem hvor du skal gyte monsteret langs Y-aksen CGSize winSize = [CCDirector sharedDirector] .winSize; int minY = monster.contentSize.width / 2; int maxY = winSize.width - monster.contentSize.width / 2; int rangeY = maxY - minY; int actualY = (arc4random ()% rangeY) + minY;
Å velge beskrivende navn for ting som variabler og funksjoner er et viktig aspekt ved å skrive lesbar kode. Det hjelper både kolleger og deg selv til raskt å forstå koden. Oppgi en variabel tmp
forteller deg ikke noe annet enn at variabelen er midlertidig av en eller annen grunn, noe som ikke er noe mer enn et utdannet gjetning. Det forteller ikke om variabelen lagrer navn, dato osv.
Et annet godt eksempel er å navngi en metode Stoppe
. Det er ikke et dårlig navn per se, men det avhenger egentlig av metodens implementering. Hvis det utfører en farlig operasjon som ikke kan fortrykkes, kan det hende du vil endre det til drepe
eller pause
hvis operasjonen kan gjenopptas. Får du ideen?
Hvis du jobber med en variabel for vekten av poteter, hvorfor vil du nevne den tmp
? Når du besøker det stykke kode noen dager senere, vil du ikke huske hva tmp
brukes til.
Det sier vi ikke tmp
er et dårlig navn på en variabel, fordi det er tidspunkter når tmp
er helt rimelig som et variabelt navn. Ta en titt på følgende eksempel der tmp
er ikke et dårlig valg i det hele tatt.
tmp = first_potato; first_potato = second_potato; second_potato = tmp;
I eksemplet ovenfor, tmp
beskriver hva den gjør, det lagrer midlertidig en verdi. Den overføres ikke til en funksjon eller metode, og den økes ikke eller endres. Den har en veldefinert levetid, og ingen erfaren utvikler vil bli kastet av variabelenes navn. Noen ganger er det imidlertid bare ren dovenskap. Ta en titt på det neste eksemplet.
NSString * tmp = user.name; tmp + = "" + user.phone_number; tmp + = "" + user.email; ... [template setObject: tmp forKey: @ "user_info"];
Hvis tmp
lagrer brukerens informasjon, hvorfor heter den ikke brukerinformasjon
? Riktig navngivning av variabler, funksjoner, metoder, klasser, etc. er viktig når du skriver lesbar kode. Det gjør ikke bare koden din mer lesbar, det sparer tid i fremtiden.
Som vi så i forrige tips, er det viktig å velge navn klokt. Det er imidlertid like viktig å legge til betydninger på navnene du bruker for variabler, funksjoner, metoder, osv. Dette hjelper ikke bare forvirring, det gjør koden du skriver lettere å forstå. Å velge et navn som gir mening er nesten som å legge til metadata til en variabel eller metode. Velg beskrivende navn og unngå generiske. Ordet Legg til
, for eksempel, er ikke alltid ideell som du kan se i det neste eksemplet.
bool addUser (Bruker u) ...
Det er ikke klart hva adduser
er ment å gjøre. Legger den til en bruker i en liste over brukere, til en database, eller til en liste over personer som inviteres til en fest? Sammenlign dette til registerUser
eller signupUser
. Dette gir mer mening. Ikke sant? Ta en titt på følgende liste for å få en bedre ide om hva vi kjører på.
Ord | synonymer | gjøre | lage, utføre, utføre, komponere, legge til | start | lansere, lage, begynne, åpne | eksplodere | detonere, sprenge, sette av, briste |
Mange programmerere liker ikke lange navn, fordi de er vanskelig å huske og tungvint å skrive. Selvfølgelig bør et navn ikke være latterlig lenge newClassForNavigationControllerNamedFirstViewController
. Dette er vanskelig å huske, og det gjør bare koden din stygge og ulæselige.
Som vi så tidligere, er det motsatte, korte navn heller ikke noe bra. Hva er riktig størrelse for et variabel- eller metodenavn? Hvordan bestemmer du mellom å navngi en variabel len
, lengde
, eller user_name_length
? Svaret avhenger av konteksten og enheten som navnet er knyttet til.
Lange navn er ikke lenger et problem ved bruk av et moderne IDE (Integrated Development Environment). Kodefylling hjelper deg med å unngå skrivefeil, og det gjør også forslag til å gjøre husk navn mindre smerte.
Du kan bruke korte (er) navn hvis variabelen er lokal. I tillegg anbefales det å bruke kortere navn for lokale variabler for å holde koden lesbar. Ta en titt på følgende eksempel.
NSString * link = [[NSString alloker] initWithFormat: @ "http: // localhost: 8080 / WrittingGoodCode / resources / GoodCode / getGoodCode /% @", idCode]; NSURL * infoCode = [NSURL URLWithString: link];
Boolesker kan være vanskelig å nevne, fordi de kan ha en annen betydning, avhengig av måten du leser eller tolker navnet på. I neste kodestykke, read_password
kan bety at passordet har blitt lest av programmet, men det kan også bety at programmet skal lese passordet.
BOOL readPassword = JA;
For å unngå dette problemet, kan du omdøpe ovennevnte booleanske til didReadPassword
for å indikere at passordet har blitt lest eller shouldReadPassword
for å vise at programmet må lese passordet. Dette er noe du ser mye i Objective-C, for eksempel.
Å legge til kommentarer til kode er viktig, men det er like viktig å bruke dem sparsomt. De bør brukes til å hjelpe noen å forstå koden din. Lesing av kommentarer tar imidlertid også tid, og hvis en kommentar ikke legger til mye verdi, er den tiden bortkastet. Den neste kodestykket viser hvordan ikke å bruke kommentarer.
// Dette skjer når minnet advarsel er mottatt - (void) didReceiveMemoryWarning [super didReceiveMemoryWarning]; // Kast bort eventuelle ressurser som kan gjenopprettes. // Dette validerer feltene - (BOOL) validateFields
Er disse kodene nyttige for deg? Svaret er sannsynligvis "Nei". Kommentarene i eksemplene ovenfor legger ikke til tilleggsinformasjon, særlig siden metodens navn er allerede svært beskrivende, noe som er vanlig i Objective-C. Ikke legg til kommentarer som forklarer det opplagte. Ta en titt på det neste eksemplet. Er dette ikke mye bedre bruk av kommentarer?
// Bestem hastigheten til monsteret int minDuration = 2.0; int maxDuration = 8,0; int rangeDuration = maxDuration - minDuration; int actualDuration = (arc4random ()% rangeDuration) + minDuration;
Kommentarer som dette gjør det veldig enkelt å navigere en kodebase raskt og effektivt. Det sparer deg fra å måtte lese koden og hjelper deg med å forstå logikken eller algoritmen.
Hvert språk eller plattform har en (eller flere) stilguide, og selv de fleste bedrifter har en. Setter du de krøllete båndene på en Objective-C-metode på en egen linje eller ikke?
- (void) calculateOffset
- (void) calculateOffset
Svaret er at det spiller ingen rolle. Det er ikke noe riktig svar. Selvfølgelig er det stilguider du kan adoptere. Det som er viktig er at koden din er konsistent når det gjelder stil. Selv om dette ikke påvirker kvaliteten på koden, påvirker det sikkert lesbarheten, og det vil mest sannsynlig irritere helvete ut av kollegaene dine eller den som leser koden din. For de fleste utviklere er stygg kode den verste typen kode.
En vanlig feil blant utviklere prøver å få så mye funksjonalitet i funksjoner og metoder. Dette fungerer, men det er inelegant og gjør debugging en smerte i nakken. Ditt liv - og det som dine kolleger har - vil bli mye lettere hvis du bryter større problemer i små biter og takler disse bitene i separate funksjoner eller metoder. Ta en titt på det neste eksemplet der vi skriver et bilde til disk. Dette virker som en triviell oppgave, men det er mye mer til det hvis du vil gjøre det riktig.
- (BOOL) saveToImage: (UIImage *) bilde withFileName: (NSString *) fileName BOOL result = NO; NSString * dokumenter = null; NSArray * stier = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); hvis (paths.count) documents = [stier objectAtIndex: 0]; NSString * basePath = [dokumenter stringByAppendingPathComponent: @ "Archive"]; hvis (! [[NSFileManager defaultManager] fileExistsAtPath: basePath]) NSError * error = nil; [[NSFileManager defaultManager] createDirectoryAtPath: basePath withIntermediateDirectories: JA-attributter: null feil: & feil]; hvis (! feil) NSString * filePath = [basePath stringByAppendingPathComponent: fileName]; result = [UIImageJPEGRepresentation (image, 8.0) writeToFile: filePath atomically: YES]; else NSLog (@ "Kunne ikke opprette katalog på grunn av feil% @ med brukerinfo% @.", feil, error.userInfo); returresultat;
Hvis en kodenhet forsøker å gjøre for mye, blir du ofte dypt nestede betingede utsagn, mye feilkontroll og altfor kompliserte betingede utsagn. Denne metoden gjør tre ting, hent banen til programmets katalogkatalog, hent og opprett banen for arkivkatalogen, og skriv bildet til disken. Hver oppgave kan settes i egen metode som vist nedenfor.
- (BOOL) saveToImage: (UIImage *) bilde withFileName: (NSString *) filenavn NSString * archivesDirectory = [self applicationArchivesDirectory]; hvis (! archivesDirectory) returnerer NO; // Opprett banen NSString * filePath = [archivesDirectory stringByAppendingPathComponent: fileName]; // Skriv bilde til Disk tilbake [UIImageJPEGRepresentation (image, 8.0) writeToFile: filePath atomically: YES];
- (NSString *) applicationDocumentsDirectory NSArray * paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); return paths.count? [stier objectAtIndex: 0]: null;
- (NSString *) applicationArchivesDirectory NSString * documentsDirectory = [self applicationDocumentsDirectory]; NSString * archivesDirectory = [documentsDirectory stringByAppendingPathComponent: @ "Archives"]; NSFileManager * fm = [NSFileManager defaultManager]; hvis (! [fm fileExistsAtPath: archivesDirectory]) NSError * error = nil; [fm createDirectoryAtPath: archivesDirectory withIntermediateDirectories: JA-attributter: null feil: & feil]; hvis (feil) NSLog (@ "Kunne ikke opprette katalog på grunn av feil% @ med brukerinfo% @.", feil, error.userInfo); returner null; returnere arkivkatalog;
Dette er mye lettere å feilsøke og vedlikeholde. Du kan til og med gjenbruke applicationDocumentsDirectory
metode på andre steder i prosjektet, noe som er en annen fordel ved å bryte større problemer i håndterbare stykker. Testingskoden blir også mye lettere.
I denne artikkelen har vi tatt en nærmere titt på å skrive lesbar kode ved å velge navn for variabler, funksjoner og metoder, være konsekvent når du skriver kode og bryte komplekse problemer i håndterbare biter. Hvis du har spørsmål eller tilbakemelding, er du velkommen til å legge igjen en kommentar nedenfor.