CodeGym /Java blog /Tilfældig /Kodningsregler: Styrken ved korrekte navne, gode og dårli...
John Squirrels
Niveau
San Francisco

Kodningsregler: Styrken ved korrekte navne, gode og dårlige kommentarer

Udgivet i gruppen
Kodningsregler: Styrken ved korrekte navne, gode og dårlige kommentarer - 1Hvor ofte har du været nødt til at grave i en andens kode? I stedet for to timer kan du bruge to dage på blot at forstå logikken i, hvad der sker. Det sjove er, at for den person, der skrev koden, er alt klart og fuldstændig gennemsigtigt. Dette er ikke overraskende: perfekt kode er trods alt et meget vagt koncept, fordi hver udvikler har sin egen vision af verden og også koden. Mere end én gang har jeg været i en situation, hvor en kollega og jeg så på den samme kode og havde forskellige meninger om dens korrekthed og renhed.Kodningsregler: kraften i korrekte navne, gode og dårlige kommentarer - 2Det lyder bekendt, gør det ikke? Alligevel er der nogle gennemprøvede principper, som bør overholdes. I sidste ende vil de være fordelagtige for dig, for hvis du efterlader din kode i den tilstand, du selv gerne vil modtage den i, så ville verden blive lidt gladere og renere. I vores tidligere artikel(eller rettere, lille guide) om kodningsregler, vi fik en lille fornemmelse af anbefalinger til at skrive et system som en helhed og dets bestanddele, såsom objekter, grænseflader, klasser, metoder og variabler. I den samme artikel nævnte jeg tilfældigt den korrekte navngivning af visse elementer. Det vil jeg gerne tale om i dag, for korrekte navne gør koden mange gange nemmere at læse. Vi lukker emnet for korrekt kode af med nogle refleksioner, små eksempler på kommentarer i kode, og en overvejelse af, om dette er godt eller knap så godt. Nå, lad os komme i gang.

Korrekte navne

Korrekte navne forbedrer kodelæsbarheden og reducerer dermed den tid, det tager at sætte sig ind i koden, fordi det er meget nemmere at bruge en metode, når dens navn groft beskriver dens funktionalitet. Alt i kode består af navne (variabler, metoder, klasser, objekter, filer osv.), så dette punkt bliver meget vigtigt, når man laver korrekt, ren kode. Baseret på ovenstående skal navnet formidle betydning, for eksempel hvorfor variablen eksisterer, hvad den gør, og hvordan den bruges. Jeg vil bemærke mere end én gang, at den bedste kommentar til en variabel er at give den et godt navn.Kodningsregler: kraften i korrekte navne, gode og dårlige kommentarer - 3

fra tv-serien "Sherlock" (2010-2017)

Navngivning af grænseflader

Grænseflader har normalt navne, der starter med et stort bogstav og er skrevet i CamelCase. Når man skrev en grænseflade, blev det tidligere betragtet som god praksis at tilføje præfikset "I" for at udpege det som en grænseflade (for eksempel IUserService), men det ser ret grimt og distraherende ud. I sådanne tilfælde er det bedre at udelade præfikset (UserService) og tilføje "Impl" som et suffiks til navnet på dets implementering (f.eks. UserServiceImpl). Eller eventuelt, som en sidste udvej, tilføje et "C" præfiks til navnet på implementeringen (f.eks. CUserService).

Klassenavne

Ligesom grænseflader skrives klassenavne med stort og bruger CamelCase. Det er lige meget, om vi står over for en zombieapokalypse, det er lige meget, om slutningen er nær - aldrig, aldrig, aldrig bør navnet på en klasse være et verbum! Klasse- og objektnavne skal være navneord eller sammensatte navneord (UserController, UserDetails, UserAccount, og så videre). Du bør ikke sætte forkortelsen af ​​applikationen ind i slutningen af ​​navnet på hver klasse, da det kun ville tilføje unødvendig kompleksitet. For eksempel, hvis vi har en User Data Migration-applikation, så lad være med at tilføje "UDM" til hver klasse, dvs. UDMUserDetails, UDMUserAccount, UDMUserController.

Metodenavne

Normalt begynder metodenavne med et lille bogstav, men de bruger også kamel-case-stil (camelCase). Ovenfor sagde vi, at klassenavne aldrig må være verber. Her er situationen lige omvendt: navnene på metoderne skal være verber eller verbum: findUserById, findAllUsers, createUser, og så videre. Når du opretter en metode (såvel som variabler og klasser), så brug en konsekvent navnekonvention for at undgå forvirring. For at finde en bruger kan en metode f.eks. hedde getUserById eller findUserById. Og en ting mere: Brug ikke humor i navnene på metoderne, for andre forstår måske ikke vittigheden. Som følge heraf kan de ikke forstå, hvad metoden gør.

Variable navne

I de fleste tilfælde begynder variabelnavne med et lille bogstav og bruger også camelCase, undtagen når variablen er en global konstant. I sådanne tilfælde skrives alle bogstaver i navnet med store bogstaver, og ordene er adskilt af en understregning ("_"). For nemheds skyld kan du bruge meningsfuld kontekst, når du navngiver variabler. Med andre ord, når en variabel eksisterer som en del af noget større, for eksempel fornavn, efternavn eller status. I sådanne tilfælde kan du tilføje et præfiks, der angiver det objekt, som denne variabel tilhører. For eksempel: userFirstName, userLastName, userStatus. Du bør også undgå lignende navne for variabler, når de har helt forskellige betydninger. Her er nogle hyppigt forekommende antonymer, der bruges i variabelnavne:
  • begynde/slut
  • først sidst
  • låst/låst op
  • min/max
  • næste/forrige
  • gammel/ny
  • åbnet/lukket
  • synlig/usynlig
  • kilde/mål
  • kilde/destination
  • op ned

Korte variabelnavne

Når vi har variabler som x eller n eller sådan noget, ser vi ikke umiddelbart hensigten med den person, der skrev koden. Det er ikke indlysende, hvad n gør. At finde ud af det kræver mere omhyggelig kontemplation (og det betyder tid, tid, tid). Antag for eksempel, at vi har et felt, der repræsenterer id'et for den ansvarlige bruger. I stedet for et variabelnavn som x eller blot id, vil vi navngive denne variabel "responsibleUserId", som straks forbedrer læsbarheden og informationsindholdet. Når det er sagt, har korte navne som n en plads som lokale variabler i små metoder, hvor kodeblokken, der involverer denne variabel, kun er et par linjer lang, og metodenavnet beskriver perfekt, hvad der sker der. Når en udvikler ser en sådan variabel, forstår den, at den er af sekundær betydning og har et meget begrænset omfang. Som et resultat heraf har omfanget en vis afhængighed af et variabelnavns længde: Jo længere navnet er, jo mere globalt er variablen og omvendt. Som et eksempel er her en metode til at finde den sidst gemte bruger efter dato:

public User findLastUser() {
   return findAllUsers().stream()
           .sorted((x, y) -> -x.getCreatedDate().compareTo(y.getCreatedDate()))
           .findFirst()
           .orElseThrow(() -> new ResourceNotFoundException("No user exists"));
}
Her bruger vi kortnavnede variable x og y til at sortere strømmen, og så glemmer vi dem.

Optimal længde

Lad os fortsætte med emnet navnelængde. Den optimale navnelængde er et sted mellem n og maximumNumberOfUsersInTheCurrentGroup. Korte navne lider med andre ord under manglende betydning, mens navne, der er for lange, forlænger programmet uden at tilføje læsbarhed, og vi er simpelthen for dovne til at skrive dem hver gang. Bortset fra tilfældet beskrevet ovenfor for variabler med et kort navn som n, bør du holde dig til en længde på omkring 8-16 tegn. Dette er ikke en streng regel, kun en retningslinje.

Små forskelle

Jeg kan ikke undlade at nævne subtile forskelle i navne. Dette er også en dårlig praksis, da disse forskelle simpelthen kan være forvirrende eller kræve at bruge meget ekstra tid på at lægge mærke til dem. For eksempel er forskellen mellem InvalidDataAccessApiUsageException og InvalidDataAccessResourceUsageException svær at få øje på med et øjeblik. Der kan også ofte opstå forvirring ved brug af små bogstaver L og O, fordi de let kan forveksles med 1 og 0. I nogle skrifttyper er forskellen mere tydelig, i nogle er den mindre.

Betydningen

Vi skal gøre navne meningsfulde, men ikke skabe tvetydighed gennem synonymer, da for eksempel UserData og UserInfo faktisk har samme betydning. I dette tilfælde skal vi grave dybere ned i koden for at forstå, hvilket bestemt objekt vi har brug for. Undgå ord, der ikke formidler nyttig information. For eksempel, i firstNameString, hvorfor har vi brug for ordet String? Kan dette virkelig være et Dato-objekt? Selvfølgelig ikke. Så vi bruger simpelthen fornavn. Jeg vil også gerne nævne booleske variable. Som et eksempel, tag en boolsk navngivet flagDeleted. Ordet flag har ingen betydning. Det er mere rimeligt at kalde det er slettet.

Desinformation

Jeg vil også gerne sige et par ord om forkerte navnekonventioner. Lad os sige, at vi har en variabel ved navn userActivityList, men i stedet for at være en liste, er dette objekt en anden containertype eller brugerdefineret lagerobjekt. Dette kunne forvirre den gennemsnitlige programmør: det er bedre at kalde det noget som userActivityGroup eller userActivities.

Søg

En af ulemperne ved korte og enkle navne er, at de er svære at finde i en stor kode – hvad ville være nemmere at finde: "navn" eller "NAME_FOR_DEFAULT_USER"? Den anden mulighed, selvfølgelig. Vi bør undgå ofte stødte på ord (bogstaver) i navne, da de kun vil øge antallet af matchende filer under en søgning, hvilket ikke er godt. Jeg vil gerne minde dig om, at programmører bruger mere tid på at læse kode end at skrive den, så vær smart med at navngive elementerne i din applikation. Men hvad nu hvis et godt navn bare ikke kan findes? Hvad hvis navnet på en metode ikke beskriver dens funktionalitet godt? Det er her, kommentarer kommer på scenen.

Kommentarer

Kodningsregler: kraften i korrekte navne, gode og dårlige kommentarer - 4Der er intet bedre end en relevant kommentar, men intet roder op i et modul som tomme, forældede eller falske kommentarer. De kan være et tveægget sværd, ikke? Alligevel skal du ikke behandle kommentarer som entydigt gode, men snarere som et mindre onde. En kommentar er jo i bund og grund en måde at kompensere for tænkning, der ikke kommer tydeligt frem i koden. For eksempel bruger vi dem til på en eller anden måde at formidle essensen af ​​en metode, hvis selve metoden viser sig at være for forvirrende. I denne situation er det bedre at omfaktorere koden korrekt end at skrive beskrivende noter. Jo ældre kommentaren er, jo værre kommentaren, fordi kode har en tendens til at vokse og udvikle sig, men kommentarer kan forblive de samme. Jo længere tid der er gået, siden en kommentar blev oprettet, jo mere tvivlsom kan den være. Upræcise kommentarer er meget værre end ingen kommentarer overhovedet, fordi de er forvirrende og vildledende og giver falske forventninger. Og selvom vi har en meget vanskelig kode, bør vi omskrive den i stedet for at kommentere den.

Typer af kommentarer

  • Juridiske kommentarer — Kommentarer i begyndelsen af ​​hver kildefil af juridiske årsager, 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, der repræsenterer en forklaring af koden (der giver yderligere oplysninger eller forklarer hensigten med en given kodesektion).

    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 tilfælde kan du undvære kommentarer, da navnet på metoden og dens parametre kombineret med meget gennemsigtig funktionalitet beskriver sig selv godt.

  • Advarselskommentarer — Kommentar beregnet til at advare andre udviklere om de uønskede konsekvenser af en handling (for eksempel at advare dem om, hvorfor en test blev markeret 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, der er en note om noget, der skal gøres i fremtiden, men som af en eller anden grund ikke kan gøres nu. Dette er en god praksis, men sådanne kommentarer bør gennemgås regelmæssigt for at fjerne irrelevante og undgå rod.

    Et eksempel ville 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 bemærker vi det faktum, at vi skal tilføje en sammenligning af brugeren, der udfører download-handlingen (hvis ID vi vil udtrække fra sikkerhedskonteksten) med den, der udførte lagringsoperationen.

  • Forstærkende kommentarer — Kommentarer, der understreger vigtigheden af ​​en omstændighed, der ved første øjekast kan virke ubetydelig.

    Som et eksempel kan du overveje et stykke af en metode, der fylder en testdatabase med nogle scripts:

    
    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, der beskriver API'et for visse funktioner. Der er nok de mest nyttige kommentarer, da den dokumenterede API er meget nemmere at arbejde med. Når det er sagt, kan de også være forældede som enhver anden type kommentar. Så glem aldrig, at hovedbidraget til dokumentation ikke kommer af kommentarer, men af ​​god kode.

    Her er et eksempel på en ret almindelig metode til at opdatere en bruger:

    
    /**
    * 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, der normalt skrives i en fart, og hvis betydning kun er forståelig for udvikleren, der har skrevet dem, da kun han eller hun opfatter den nuancerede situation, som kommentaren refererer til.

    Overvej dette eksempel:

    
    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 indlæser disse indstillinger? Er de allerede blevet indlæst? Skal denne metode fange undtagelser og indlæse standardindstillinger? Der opstår for mange spørgsmål, som kun kan besvares ved at dykke ned i en undersøgelse af andre dele af systemet.

  • Redundante kommentarer — Kommentarer, der ikke bærer nogen semantisk belastning, da det, der sker i en given sektion af koden, er helt klart. Kommentaren er med andre ord ikke nemmere at læse end koden.

    Lad os 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;
       }
    

    Hvad er meningen med sådanne kommentarer? Alt, hvad de forklarer, er allerede helt klart.

  • Upålidelige kommentarer — Kommentarer, der er usande og kun vildledende (desinformation). 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();
    }
    

    Hvad er der galt med denne kommentar? At det lyver lidt for os, i og med at forbindelsen lukkes hvis isNotUsing er falsk, ikke omvendt, som kommentaren oplyser os om.

  • Obligatoriske kommentarer — Kommentarer, der anses for obligatoriske (f.eks. Javadoc-kommentarer), men som faktisk nogle gange hober sig for meget op og er upålidelige og unødvendige (du skal tænke over, om disse kommentarer 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 være i stand til at forstå, hvad metoden gør uden disse kommentarer? Mest sandsynligt, ja, så kommentarer bliver meningsløse her.

  • Logkommentarer — Kommentarer, der nogle gange føjes til begyndelsen af ​​et modul, hver gang det redigeres (noget som en ændringslog).

    
    /**
    * 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 tilgang var engang berettiget, men med fremkomsten af ​​versionskontrolsystemer (for eksempel Git) blev det en unødvendig rod og komplikation af koden.

  • Forfatterskabskommentarer — Kommentarer, hvis formål er at angive den person, der har skrevet koden, så du kan kontakte ham/hende og diskutere hvordan, hvad og hvorfor, f.eks.

    
    * @author Bender Bending
    

    Endnu en gang husker versionskontrolsystemer nøjagtigt, hvem der tilføjede enhver kode og hvornår, så denne tilgang er overflødig.

  • Udkommen kode — Kode, der blev kommenteret ud af en eller anden grund. Dette er en af ​​de værste vaner, for det, der sker, er, at du kommenterer noget og glemmer det, og så har andre udviklere bare ikke modet til at slette det (trods alt, hvad nu hvis det er noget værdifuldt?).

    
    //    public void someMethod(SomeObject obj) {
    //    .....
    //    }
    

    Som et resultat akkumuleres kommenteret kode som skrald. I intet tilfælde bør du efterlade en sådan kode. Hvis du virkelig har brug for det, så glem ikke versionskontrolsystemet.

  • Ikke-oplagte kommentarer — Kommentarer, der beskriver noget på en alt for kompliceret måde.

    
    /*
        * 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 skal forklare koden. Det burde ikke i sig selv kræve en forklaring. Så hvad er der galt her? Hvad er "filterbytes"? Hvad handler det "+1" om? Hvorfor lige præcis 300?

Hvis du allerede har besluttet dig for at skrive kommentarer, er her et par tips:
  1. Brug stilarter, der er nemme at vedligeholde: At vedligeholde stilarter, der er for fancy og eksotiske, er irriterende og tidskrævende.
  2. Brug ikke end-of-line kommentarer, der refererer til enkelte linjer: Resultatet er en stor bunke kommentarer. Hvad mere er, er det svært at finde en meningsfuld kommentar for hver linje.
  3. Når du skriver en kommentar, så prøv at besvare spørgsmålet "hvorfor", ikke "hvordan".
  4. Undgå forkortet information. Som jeg sagde ovenfor, behøver vi ikke en forklaring på en kommentar: selve kommentaren er forklaringen.
  5. Du kan bruge kommentarer til at notere enheder og værdiintervaller.
  6. Placer kommentarer tæt på den kode, de beskriver.
Til sidst vil jeg stadig minde dig om, at den bedste kommentar er ingen kommentar, men derimod brugen af ​​dygtige navngivninger i hele din ansøgning. Som regel vil vi det meste af tiden arbejde med eksisterende kode, vedligeholde og udvide den. Det er meget mere praktisk, når denne kode er let at læse og forståelig, da dårlig kode er en hindring. Det er som at kaste en skruenøgle i gang, og hastværk er dens trofaste følgesvend. Og jo mere dårlig kode vi har, jo mere falder ydeevnen. Det betyder, at vi er nødt til at refaktorere fra tid til anden. Men hvis du fra starten forsøger at skrive kode, der ikke vil få de næste udviklere til at ville finde og dræbe dig, så behøver du ikke at refaktorere den så ofte. Men det vil stadig være nødvendigt, da produktets betingelser og krav konstant ændres med tilføjelse af nye afhængigheder og forbindelser. Nå, det er vel alt for mig i dag. Tak til alle der har læst med indtil videre :)
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION