CodeGym /Java-blogg /Tilfeldig /Kodingsregler: Kraften til riktige navn, gode og dårlige ...
John Squirrels
Nivå
San Francisco

Kodingsregler: Kraften til riktige navn, gode og dårlige kommentarer

Publisert i gruppen
Kodingsregler: Kraften til riktige navn, gode og dårlige kommentarer - 1Hvor ofte har du måttet grave i andres kode? I stedet for to timer kan du bruke to dager på å forstå logikken i det som skjer. Det morsomme er at for personen som skrev koden, er alt klart og helt gjennomsiktig. Dette er ikke overraskende: perfekt kode er tross alt et veldig vagt konsept, fordi hver utvikler har sin egen visjon om verden og koden også. Mer enn én gang har jeg vært i en situasjon da en kollega og jeg så på den samme koden og hadde forskjellige meninger om dens korrekthet og renhet.Kodingsregler: kraften til riktige navn, gode og dårlige kommentarer - 2Høres kjent ut, gjør det ikke? Likevel er det noen utprøvde prinsipper som bør følges. Til slutt vil de være fordelaktige for deg, for hvis du lar koden din være i den tilstanden du selv ønsker å motta den i, vil verden bli litt gladere og renere. I vår forrige artikkel(eller rettere sagt, liten guide) om kodingsregler, vi fikk en liten følelse av anbefalinger for å skrive et system som en helhet og dets bestanddeler, for eksempel objekter, grensesnitt, klasser, metoder og variabler. I den samme artikkelen nevnte jeg tilfeldig riktig navn på visse elementer. Jeg vil gjerne snakke om dette i dag, fordi riktige navn gjør koden mange ganger lettere å lese. Vi vil avslutte temaet riktig kode med noen refleksjoner, små eksempler på kommentarer i kode, og en vurdering av om dette er bra eller ikke så bra. Vel, la oss komme i gang.

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.Kodingsregler: kraften i riktige navn, gode og dårlige kommentarer - 3

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

Kodingsregler: kraften til korrekte navn, gode og dårlige kommentarer - 4Det er ingenting bedre enn en relevant kommentar, men ingenting roter opp en modul som tomme, utdaterte eller falske kommentarer. De kan være et tveegget sverd, ikke sant? Likevel bør du ikke behandle kommentarer som entydig gode, men heller som et mindre onde. Tross alt er en kommentar i hovedsak en måte å kompensere for tenkning som ikke kommer tydelig frem i koden. For eksempel bruker vi dem til på en eller annen måte å formidle essensen av en metode, hvis selve metoden viser seg å være for forvirrende. I denne situasjonen er det bedre å refaktorere koden riktig enn å skrive beskrivende notater. Jo eldre kommentaren er, desto verre er kommentaren, fordi kode har en tendens til å vokse og utvikle seg, men kommentarer kan forbli de samme. Jo mer tid som har gått siden en kommentar ble opprettet, jo mer tvilsom kan den være. Unøyaktige kommentarer er mye verre enn ingen kommentarer i det hele tatt, fordi de er forvirrende og villedende, og gir falske forventninger. Og selv om vi har veldig vanskelig kode, bør vi skrive den om i stedet for å kommentere den.

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?

Hvis du allerede har bestemt deg for å skrive kommentarer, her er et par tips:
  1. Bruk stiler som er enkle å vedlikeholde: å opprettholde stiler som er for fancy og eksotiske er irriterende og tidkrevende.
  2. 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.
  3. Når du skriver en kommentar, prøv å svare på spørsmålet "hvorfor", ikke "hvordan".
  4. Unngå forkortet informasjon. Som jeg sa ovenfor, trenger vi ingen forklaring på en kommentar: selve kommentaren er forklaringen.
  5. Du kan bruke kommentarer til å notere enheter og verdiområder.
  6. Legg inn kommentarer i nærheten av koden de beskriver.
Til slutt vil jeg likevel minne deg på at den beste kommentaren er ingen kommentar, men heller bruken av dyktig navngivning gjennom hele søknaden din. Som regel vil vi mesteparten av tiden jobbe med eksisterende kode, vedlikeholde og utvide den. Det er mye mer praktisk når denne koden er lett å lese og forståelig, siden dårlig kode er en hindring. Det er som å kaste en skiftenøkkel i verkene, og hastverk er dens trofaste følgesvenn. Og jo mer dårlig kode vi har, jo mer faller ytelsen. Dette betyr at vi må refaktorere fra tid til annen. Men hvis du fra begynnelsen prøver å skrive kode som ikke vil føre til at de neste utviklerne vil finne og drepe deg, trenger du ikke å refaktorere den så ofte. Men det vil fortsatt være nødvendig, siden produktets betingelser og krav stadig endres med tillegg av nye avhengigheter og forbindelser. Vel, jeg antar at det var alt for meg i dag. Takk til alle som har lest så langt :)
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION