

Riktige navn
Riktige navn forbedrer kodens lesbarhet, og reduserer dermed tiden som kreves for å gjøre deg kjent med koden, fordi det er mye enklere å bruke en metode når navnet beskriver dens funksjonalitet grovt. Alt i kode består av navn (variabler, metoder, klasser, objekter, filer osv.), så dette punktet blir veldig viktig når man skal lage korrekt, ren kode. Basert på ovenstående skal navnet formidle betydning, for eksempel hvorfor variabelen eksisterer, hva den gjør og hvordan den brukes. Jeg vil merke mer enn én gang at den beste kommentaren til en variabel er å gi den et godt navn.
fra TV-serien "Sherlock" (2010-2017)
Navnegrensesnitt
Grensesnitt har vanligvis navn som starter med stor bokstav og er skrevet i CamelCase. Når du skrev et grensesnitt, ble det tidligere ansett som god praksis å legge til prefikset "I" for å angi det som et grensesnitt (for eksempel IUserService), men det ser ganske stygt og distraherende ut. I slike tilfeller er det bedre å utelate prefikset (UserService) og legge til "Impl" som et suffiks til navnet på implementeringen (f.eks. UserServiceImpl). Eller muligens, som en siste utvei, legg til et "C"-prefiks til navnet på implementeringen (f.eks. CUserService).Klassenavn
Akkurat som grensesnitt, er klassenavn skrevet med store bokstaver og bruker CamelCase. Det spiller ingen rolle om vi står overfor en zombieapokalypse, det spiller ingen rolle om slutten er for hånden - aldri, aldri, aldri skal navnet på en klasse være et verb! Klasse- og objektnavn må være substantiv eller sammensatte substantiv (UserController, UserDetails, UserAccount, og så videre). Du bør ikke feste forkortelsen av applikasjonen på slutten av navnet på hver klasse, siden det bare vil legge til unødvendig kompleksitet. For eksempel, hvis vi har en User Data Migration-applikasjon, vennligst ikke legg til "UDM" i hver klasse, dvs. UDMUserDetails, UDMUserAccount, UDMUserController.Metodenavn
Vanligvis begynner metodenavn med en liten bokstav, men de bruker også kamelstil (camelCase). Ovenfor sa vi at klassenavn aldri skal være verb. Her er situasjonen akkurat motsatt: navnene på metodene skal være verb eller verbfraser: findUserById, findAllUsers, createUser, og så videre. Når du oppretter en metode (så vel som variabler og klasser), så bruk en konsistent navnekonvensjon for å unngå forvirring. For å finne en bruker kan for eksempel en metode hete getUserById eller findUserById. Og en ting til: Ikke bruk humor i navnene på metodene, for andre forstår kanskje ikke vitsen. Som et resultat kan de mislykkes i å forstå hva metoden gjør.Variable navn
I de fleste tilfeller begynner variabelnavn med en liten bokstav og bruker også camelCase, bortsett fra når variabelen er en global konstant. I slike tilfeller skrives alle bokstavene i navnet med store bokstaver, og ordene er atskilt med et understrek ("_"). For enkelhets skyld kan du bruke meningsfull kontekst når du navngir variabler. Med andre ord, når en variabel eksisterer som en del av noe større, for eksempel fornavn, etternavn eller status. I slike tilfeller kan du legge til et prefiks som indikerer objektet som denne variabelen tilhører. For eksempel: brukerFornavn, brukerEtternavn, brukerStatus. Du bør også unngå lignende navn for variabler når de har helt forskjellige betydninger. Her er noen ofte forekommende antonymer som brukes i variabelnavn:- begynne/slutte
- først sist
- låst/opplåst
- min/maks
- neste/forrige
- gammel/ny
- åpnet/stengt
- synlig/usynlig
- kilde/mål
- kilde/destinasjon
- opp ned
Korte variabelnavn
Når vi har variabler som x eller n eller noe sånt, ser vi ikke umiddelbart intensjonen til personen som skrev koden. Det er ikke åpenbart hva n gjør. Å finne ut av det krever mer nøye ettertanke (og dette betyr tid, tid, tid). Anta for eksempel at vi har et felt som representerer ID-en til den ansvarlige brukeren. I stedet for et variabelnavn som x eller bare id, vil vi gi denne variabelen navnet "responsibleUserId", som umiddelbart forbedrer lesbarheten og informasjonsinnholdet. Når det er sagt, har korte navn som n en plass som lokale variabler i små metoder, der kodeblokken som involverer denne variabelen bare er et par linjer lang, og metodenavnet beskriver perfekt hva som skjer der. Når en utvikler ser en slik variabel, forstår den at den er av sekundær betydning og har et svært begrenset omfang. Som et resultat har omfanget en viss avhengighet av lengden til et variabelnavn: jo lengre navnet er, desto mer globalt er variabelen og omvendt. Som et eksempel, her er en metode for å finne den sist lagrede brukeren etter dato:
public User findLastUser() {
return findAllUsers().stream()
.sorted((x, y) -> -x.getCreatedDate().compareTo(y.getCreatedDate()))
.findFirst()
.orElseThrow(() -> new ResourceNotFoundException("No user exists"));
}
Her bruker vi korte navngitte variabler x og y for å sortere strømmen, og så glemmer vi dem.
Optimal lengde
La oss fortsette med temaet navnelengde. Den optimale navnelengden er et sted mellom n og maximumNumberOfUsersInTheCurrentGroup. Korte navn lider med andre ord av mangel på mening, mens navn som er for lange forlenger programmet uten å legge til lesbarhet, og vi er rett og slett for late til å skrive dem hver gang. Bortsett fra tilfellet beskrevet ovenfor for variabler med et kort navn som n, bør du holde deg til en lengde på ca. 8-16 tegn. Dette er ikke en streng regel, bare en retningslinje.Små forskjeller
Jeg kan ikke unngå å nevne subtile forskjeller i navn. Dette er også en dårlig praksis, siden disse forskjellene rett og slett kan være forvirrende eller kreve å bruke mye ekstra tid på å legge merke til dem. For eksempel er forskjellen mellom InvalidDataAccessApiUsageException og InvalidDataAccessResourceUsageException vanskelig å få øye på med et øyeblikk. Forvirring kan også ofte oppstå ved bruk av små bokstaver L og O, fordi de lett kan forveksles med 1 og 0. I noen fonter er forskjellen mer tydelig, i noen er den mindre.Betydningen
Vi må gjøre navn meningsfylt, men ikke skape tvetydighet gjennom synonymer, siden for eksempel UserData og UserInfo faktisk har samme betydning. I dette tilfellet må vi grave dypere inn i koden for å forstå hvilket bestemt objekt vi trenger. Unngå ord som ikke gir nyttig informasjon. For eksempel, i firstNameString, hvorfor trenger vi ordet String? Kan dette virkelig være et Dato-objekt? Selvfølgelig ikke. Så vi bruker ganske enkelt fornavn. Jeg vil også nevne boolske variabler. Som et eksempel, ta en boolsk navn som heter flagDeleted. Ordet flagg har ingen betydning. Det er mer fornuftig å kalle det isDeleted.Desinformasjon
Jeg vil også si noen ord om uriktige navnekonvensjoner. La oss si at vi har en variabel kalt userActivityList, men i stedet for å være en liste, er dette objektet en annen beholdertype eller tilpasset lagringsobjekt. Dette kan forvirre den gjennomsnittlige programmereren: det er bedre å kalle det noe sånt som userActivityGroup eller userActivities.Søk
En av ulempene med korte og enkle navn er at de er vanskelige å finne i en stor mengde kode — Hva ville være lettere å finne: "navn" eller "NAME_FOR_DEFAULT_USER"? Det andre alternativet, selvfølgelig. Vi bør unngå ofte påtreffende ord (bokstaver) i navn, siden de bare vil øke antallet samsvarende filer under et søk, noe som ikke er bra. Jeg vil minne deg på at programmerere bruker mer tid på å lese kode enn å skrive den, så vær smart med å navngi elementene i applikasjonen din. Men hva om et godt navn bare ikke kan bli funnet? Hva om navnet på en metode ikke beskriver funksjonaliteten godt? Det er her kommentarer kommer inn på scenen.Kommentarer

Typer kommentarer
-
Juridiske kommentarer — Kommentarer i begynnelsen av hver kildefil av juridiske årsaker, for eksempel:
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-
Informative kommentarer — Kommentarer som representerer en forklaring av koden (gir tilleggsinformasjon eller forklarer intensjonen med en gitt del av koden).
For eksempel:
/* * Combines the user from the database with the one passed for updating * When a field in requestUser is empty, it is filled with old data from foundUser */ private User mergeUser(User requestUser, User foundUser) { return new User( foundUser.getId(), requestUser.getFirstName() == null ? requestUser.getFirstName() : foundUser.getFirstName(), requestUser.getMiddleName() == null ? requestUser.getMiddleName() : foundUser.getMiddleName(), requestUser.getLastName() == null ? requestUser.getLastName() : foundUser.getLastName(), requestUser.getAge() == null ? requestUser.getAge() : foundUser.getAge() ); }
I dette tilfellet kan du klare deg uten kommentarer, siden navnet på metoden og dens parametere, kombinert med svært gjennomsiktig funksjonalitet, beskriver seg selv godt.
-
Advarselskommentarer — Kommentar ment å advare andre utviklere om de uønskede konsekvensene av en handling (for eksempel advare dem om hvorfor en test ble merket som @Ignorer):
// Takes too long to run // Don't run if you don't have a lot of time @Ignore @Test public void someIntegrationTest() { …… }
-
TODO — Kommentarer som er en merknad om noe som må gjøres i fremtiden som, men av en eller annen grunn, ikke kan gjøres nå. Dette er en god praksis, men slike kommentarer bør gjennomgås regelmessig for å fjerne irrelevante og unngå rot.
Et eksempel kan være:
// TODO: Add a check for the current user ID (when the security context is created) @Override public Resource downloadFile(File file) { return fileManager.download(file); }
Her merker vi det faktum at vi må legge til en sammenligning av brukeren som utfører nedlastingsoperasjonen (hvis ID vi vil trekke ut fra sikkerhetskonteksten) med den som utførte lagringsoperasjonen.
-
Forsterkende kommentarer — Kommentarer som understreker viktigheten av en omstendighet som ved første øyekast kan virke ubetydelig.
Som et eksempel kan du vurdere en del av en metode som fyller en testdatabase med noen skript:
Stream.of(IOUtils.resourceToString("/fill-scripts/" + x, StandardCharsets.UTF_8) .trim() .split(";")) .forEach(jdbcTemplate::update); // The trim() call is very important. It removes possible spaces at the end of the script // so that when we read and split into separate requests, we don't end up with empty ones
-
Javadoc-kommentarer — Kommentarer som beskriver API-en for visse funksjoner. Det er sannsynligvis de mest nyttige kommentarene, siden det dokumenterte API-et er mye enklere å jobbe med. Når det er sagt, kan de også være utdaterte som alle andre typer kommentarer. Så glem aldri at hovedbidraget til dokumentasjon ikke kommer av kommentarer, men av god kode.
Her er et eksempel på en ganske vanlig metode for å oppdatere en bruker:
/** * Updates the passed fields for a user based on its id. * * @param id id of the user to be updated * @param user user with populated fields for updating * @return updated user */ User update(Long id, User user);
Dårlige kommentarer
-
mumlende kommentar — Kommentarer som vanligvis skrives i en hast og hvis betydning bare er forståelig for utvikleren som skrev dem, siden bare han eller hun oppfatter den nyanserte situasjonen som kommentaren refererer til.
Tenk på dette eksemplet:
public void configureSomeSystem() { try{ String configPath = filesLocation.concat("/").concat(CONFIGURATION_FILE); FileInputStream stream = new FileInputStream(configPath); } catch (FileNotFoundException e) { // If there is no configuration file, the default configuration is loaded } }
Hvem laster inn disse innstillingene? Er de allerede lastet? Er denne metoden ment å fange opp unntak og laste inn standardinnstillinger? Det dukker opp for mange spørsmål som bare kan besvares ved å fordype seg i en undersøkelse av andre deler av systemet.
- Overflødige kommentarer — Kommentarer som ikke bærer noen semantisk belastning, siden det som skjer i en gitt del av koden er helt klart. Kommentaren er med andre ord ikke lettere å lese enn koden.
La oss se et eksempel:
public class JdbcConnection{ public class JdbcConnection{ /** * The logger associated with the current class */ private Logger log = Logger.getLogger(JdbcConnection.class.getName()); /** * Creates and returns a connection using the input parameters */ public static Connection buildConnection(String url, String login, String password, String driver) throws Exception { Class.forName(driver); connection = DriverManager.getConnection(url, login, password); log.info("Created connection with db"); return connection; }
Hva er vitsen med slike kommentarer? Alt de forklarer er allerede helt klart.
-
Upålitelige kommentarer — Kommentarer som er usanne og bare villedende (desinformasjon). For eksempel, her er en.
/** * Helper method. Closes the connection with the scanner if isNotUsing is true */ private void scanClose(Scanner scan, boolean isNotUsing) throws Exception { if (!isNotUsing) { throw new Exception("The scanner is still in use"); } scan.close(); }
Hva er galt med denne kommentaren? Det at det lyver litt for oss, ved at forbindelsen er stengt hvis isNotUsing er usant, ikke omvendt, som kommentaren informerer oss om.
-
Obligatoriske kommentarer — Kommentarer som anses som obligatoriske (f.eks. Javadoc-kommentarer), men som faktisk noen ganger hoper seg opp og er upålitelige og unødvendige (du må tenke på om disse kommentarene faktisk er nødvendige).
Eksempel:
/**
* Create a user based on the parameters
* @param firstName first name of the created user
* @param middleName middle name of the created user
* @param lastName last name of the created user
* @param age age of the created user
* @param address address of the created user
* @return user that was created
*/
User createNewUser(String firstName, String middleName, String lastName, String age, String address);
Ville du kunne forstå hva metoden gjør uten disse kommentarene? Mest sannsynlig, ja, så kommentarer blir meningsløse her.
Loggkommentarer — Kommentarer som noen ganger legges til i begynnelsen av en modul hver gang den redigeres (noe som en endringslogg).
/**
* Records kept since January 9, 2020;
**********************************************************************
* 9 Jan 2020: Providing a database connection using JDBC Connection;
* 15 Jan 2020: Adding DAO-level interfaces for working with the database;
* 23 Jan 2020: Adding integration tests for the database;
* 28 Jan 2020: Implementation of DAO-level interfaces;
* 1 Feb 2020: Development of interfaces for services,
* in accordance with the requirements specified in user stories;
* 16 Feb 2020: Implementation of service interfaces
* (implementation of business logic related to the work of the database);
* 25 Feb 2020: Adding tests for services;
* 8 Mar 2020: Celebration of International Women's Day (Terry is drunk again);
* 21 Mar 2020: Refactoring the service layer;
*/
Denne tilnærmingen var en gang rettferdiggjort, men med bruken av versjonskontrollsystemer (for eksempel Git), ble det en unødvendig rot og komplikasjon av koden.
Forfatterkommentarer — Kommentarer som har til hensikt å indikere personen som skrev koden, slik at du kan kontakte ham/henne og diskutere hvordan, hva og hvorfor, f.eks.
* @author Bender Bending
Nok en gang husker versjonskontrollsystemer nøyaktig hvem som la til noen kodebiter og når, så denne tilnærmingen er overflødig.
Kommentert kode — Kode som ble kommentert ut av en eller annen grunn. Dette er en av de verste vanene, for det som skjer er at du kommenterer noe og glemmer det, og så har andre utviklere rett og slett ikke mot til å slette det (tross alt, hva om det er noe verdifullt?).
// public void someMethod(SomeObject obj) {
// .....
// }
Som et resultat akkumuleres kommentert kode som søppel. Ikke i noe tilfelle bør du legge igjen en slik kode. Hvis du virkelig trenger det, ikke glem versjonskontrollsystemet.
Ikke-opplagte kommentarer — Kommentarer som beskriver noe på en altfor komplisert måte.
/*
* Start with an array large enough to store
* all the data bytes (plus filter bytes) with a cushion, plus 300 bytes
* for header data
*/
this.dataBytes = new byte[(this.size * (this.deep + 1) * 2)+300];
En kommentar bør forklare koden. Det burde ikke i seg selv trenge en forklaring. Så hva er galt her? Hva er "filterbytes"? Hva handler den "+1" om? Hvorfor akkurat 300?
- Bruk stiler som er enkle å vedlikeholde: å opprettholde stiler som er for fancy og eksotiske er irriterende og tidkrevende.
- Ikke bruk end-of-line kommentarer som refererer til enkeltlinjer: Resultatet er en stor haug med kommentarer. Dessuten er det vanskelig å finne en meningsfull kommentar for hver linje.
- Når du skriver en kommentar, prøv å svare på spørsmålet "hvorfor", ikke "hvordan".
- Unngå forkortet informasjon. Som jeg sa ovenfor, trenger vi ingen forklaring på en kommentar: selve kommentaren er forklaringen.
- Du kan bruke kommentarer til å notere enheter og verdiområder.
- Legg inn kommentarer i nærheten av koden de beskriver.
GO TO FULL VERSION