Et kort sammendrag av beste praksis for Java-koding

basert på kodingsstandarder fra Oracle, Google, Twitter og Spring Framework

Målet med denne artikkelen er å gi deg et raskt sammendrag av gjør og ikke, med andre ord foretrekker og unngå basert på kodingsstandarder fra teknisk giganter som Oracle, Google, Twitter og Spring Framework.

Du er kanskje ikke enig i noen av de beste fremgangsmåtene som presenteres her, og det er helt greit så lenge det er noen kodingsstandarder på plass.

Hvorfor kodingsstandarder i utgangspunktet? Det er mange gode grunner hvis du google det, og jeg vil gi deg følgende illustrasjon

Dokument for kodingsstandarder kan være lange og kjedelige. Denne artikkelen kirsebær plukker biter og deler fra kodingskonvensjoner av Google, Oracle, Twitter og Spring, og det er målet å gi deg et enkelt å følge og mindre kjedelig sett med fremgangsmåter for å gjøre koden din lett å lese og vedlikeholde.

Nesten alltid vil du bli med i team som jobber med eksisterende programvare, og det er en ganske god sjanse for at de fleste av forfatterne har forlatt eller byttet til forskjellige prosjekter, slik at du blir strandet med deler av koden som får deg til å stille spørsmål ved menneskeheten.

La oss dykke ned i beste praksis fra forskjellige kodingsstandarder.

Java-kildefil

Følgende anses som beste fremgangsmåter når det gjelder java-kildefiler:

  • Kildefilens lengde er lavere enn 2000 linjer med kode
  • Kildefilen er organisert med dokumentasjonskommentar, pakkedeklarasjon, etterfulgt av en klassekommentar, import gruppert (statisk sist), klasse / grensesnitt signatur og så videre som vist nedenfor
pakke com.example.model;
/ **
 * Implementeringsfritt perspektiv som skal leses av utviklere
 * som kanskje ikke nødvendigvis har kildekoden for hånden
 *
 * @ forfatter x, y, z
 * @Dato
 * @version
 * @opphavsrett
 *
 * /
import com.example.util.FileUtil;
/ *
 * Valgfri klassespesifikk kommentar
 *
 * /
offentlig klasse SomeClass {
  // Statiske variabler i rekkefølgen av synlighet
  offentlig statisk endelig heltall PUBLIC_COUNT = 1;
  statisk endelig heltall PROTECTED_COUNT = 1;
  privat statisk endelig heltall PRIVATE_COUNT = 1;
  // Forekomstvariabler i rekkefølgen av synlighet
  offentlig streng navn;
  Streng postal-kode;
  privat streng adresse;
  // Konstruktør og overbelastet i rekkefølge
  offentlig SomeClass () {}
  public SomeClass (String name) {
    this.name = name;
  }
  // Metoder
  public String doSomethingUseful () {
    returnere "Noe nyttig";
  }
  // getters, setters, equals, hashCode og toString på slutten
}

Naming

Klasse- og grensesnittnavn er CamelCase, og det anbefales å bruke hele ordet og unngå forkortelser / forkortelser. For eksempel klasse Raster eller klasse ImageSprite

  • Pakke - navn com.deepspace over com.deepSpace eller com.deep_space
  • Filnavn er CamelCase og slutter med .java som samsvarer med klassens navn. Det er en offentlig klasse per fil med hver klasse på toppnivå i filen
  • Metode - navn skal være verb i blandet tilfelle med hvert indre ord med store bokstaver for eksempel kjør (); eller runFast ();
  • Konstanter - bør være med store bokstaver med “_” som skiller hvert ord for eksempel int MIN_WIDTH = 44; og int MAX_WIDTH = 99;
  • Variabel - et navn som forteller leseren av programmet hva variabelen representerer, dvs. hvis du lagrer en testkarakter, velg deretter karakter vs var1. Hold variabelenavn korte, unngå å inkludere metadata.
// Foretrekker () - variabelenavn er korte og beskriver hva den lagrer
int skole
int [] filteredSchoolIds;
int [] uniqueSchooldIds;
Kart  brukereById;
Strengverdi;
// Unngå (x) - For detaljert variabel navngivning
int schoolIdentificationNumber;
int [] userProvidedSchoolIds;
int [] schoolIdsAfterRemovingDuplicates;
Kart  idToUserMap;
StrengverdiStreng;

Husk - variabelnavn skal være kort og fortelle leseren hvilken verdi den representerer. Bruk dommen din.

Foretrekker og unngå

Formatering og innrykk handler om å organisere koden din slik at den er lett å lese, og den inkluderer avstand, linjelengde, brytes og pauser og så videre

  • Innrykk - Bruk 2 eller 4 mellomrom og hold deg konsekvent
  • Linjelengde - Opptil 70 til 120 tegn avhengig av påvirkning på lesbarhet. Det er viktig å eliminere behovet for horisontal rulle og plassere linjeskift etter komma og operatør.

Metoder - Her er en liste over beste fremgangsmåter

// Foretrekker () Linjepauser er vilkårlige og bryter etter komma.
StrengnedlastingAnInternett (Internett på internett, rør,
    Blogosphere-blogger, beløp  båndbredde) {
  tubes.download (Internett);
}
// Unngå (x) Metode som er vanskelig å diff, argumenterer for metoden
StrengnedlastingAnInternett (Internett på internett, rør,
    Blogosphere-blogger, beløp  båndbredde) {
    tubes.download (Internett);
}
// Foretrekker () Legg til 8 (dobbelt av 2 eller 4) mellomrom for dypt innrykk
privat statisk synkronisert horkingLongMethodName (int anArg,
        Objekter en annenArg, Streng ennåAn annenArg,
        Object andStillAnother) {
  ...
}
// Foretrekker () Enkel skanning og ekstra kolonneplass.
public String downloadAnInternet (
    Internett internett,
    Rør,
    Blogosphere-blogger,
    Mengde  båndbredde) {
  tubes.download (Internett);
  ...
}
En enhetstest ville ha fanget det

Hvis-sjekker - IMO som skriver godt formatert kode gjør det enkelt å oppdage skrivefeil og feil for forfatteren og kodevurdererne, se nedenfor:

// Unngå (x) Ikke utelat {}
hvis (tilstand)
  uttalelse;
// Unngå (x)
hvis (x <0) negativt (x);
// Unngå (x)
if (a == b && c == d) {
...
}
// Foretrekker ()
hvis ((a == b) && (c == d)) {
...
}
// Foretrekker ()
hvis (betingelse) {
  uttalelser;
} annet hvis (betingelse) {
  uttalelser;
} annet hvis (betingelse) {
  uttalelser;
}
// Unngå (x)
if ((betingelse1 && tilstand2)
    || (betingelse3 && tilstand4)
    ||! (condition5 && condition6)) {// DÅRLIGE WRAPS
    doSomethingAboutIt (); // LAG DENNE LINJEN LETT Å MISS
}
// Foretrekker ()
if ((betingelse1 && tilstand2)
        || (betingelse3 && tilstand4)
        ||! (condition5 && condition6)) {
    doSomethingAboutIt ();
}

Ternary operator - Og nedenfor er anbefalt praksis

alfa = (aLongBooleanEpression)? beta: gamma;
alfa = (aLongBooleanEpression)? beta
        : gamma;
alpha = (aLongBooleanEpression)
        ? beta
        : gamma;

Bytte - Når det gjelder å bytte er det beste praksis

  • Ha alltid en standardsak selv uten kode
  • Bruk / * faller gjennom * / for å indikere at kontrollen faller til neste tilfelle
bryter (tilstand) {
  sak ABC:
    uttalelser;
  / * faller gjennom * /
  sak DEF:
    uttalelser;
    gå i stykker;
  misligholde:
    uttalelser;
     gå i stykker;
}

Unntaksmeldinger - Når du kaster et unntak her, er det eksempler på gode og dårlig innrykkede meldinger.

// Unngå (x) - Ikke lett å lese
kaste ny IllegalStateException ("Kunne ikke behandle forespørsel" + request.getId ()
    + "for user" + user.getId () + "query: '" + query.getText ()
    + "'");
// Foretrekker () - Ganske lettere å lese
kaste ny IllegalStateException ("Kunne ikke behandle"
    + "forespørsel" + forespørsel.getId ()
    + "for bruker" + bruker.getId ()
    + "spørring: '" + spørring.getText () + "'");

Iteratorer og strømmer - Strømmer blir vanligere, og til tider kan det være veldig komplekst. Det er viktig å innrykke for å være lettlest.

// Unngå (x) - Ikke lett å lese
Iterable  modules = ImmutableList.  builder (). Add (new LifecycleModule ())
    .add (ny AppLauncherModule ()). addAll (application.getModules ()). build ();
// Foretrekker () - Ganske lettere å lese
Iterable  modules = ImmutableList.  builder ()
    .add (ny LifecycleModule ())
    .add (ny AppLauncherModule ())
    .addAll (application.getModules ())
    .bygge();
Bare følg en kodingsstandard - hvilken som helst

Erklæringer og oppgaver - Det anbefales en erklæring per linje siden den oppfordrer til kommentarer som vist nedenfor.

// Foretrekker ()
int nivå; // innrykknivå
int størrelseMeter; // størrelse på bordet
// Unngå (x) til fordel for ovenfor
int-nivå, størrelseMeter;
// Foretrukket () - Inkluder enhet i variabelnavn eller -type
lang pollIntervalMs;
int fileSizeGb;
Mengde  filstørrelse;
// Unngå (x) blandingstyper
int foo, fooarray [];
// Unngå (x) - Ikke skille med komma
Format.print (System.out, “error”), exit (1);
// Unngå (x) flere tilordninger
fooBar.fChar = barFoo.lchar = 'c';
// Unngå (x) innebygde oppdrag i forsøk på å øke ytelsen // eller lagre en linje. Jeg er skyld i å gjøre dette :(
d = (a = b + c) + r;
// Foretrekker () over
a = b + c;
d = a + r;
// Foretrekker ()
Streng [] arg
// Unngå (x)
Streng args []
// Foretrekker () Bruk lenge "L" i stedet for "l" for å unngå forvirring med 1
lang tidsavbrudd = 3000000000L;
// Unngå (x) - Vanskelig å si at siste bokstav er l og ikke 1
lang timeout = 3000000000l;

Sett erklæringer bare i begynnelsen av blokker (En blokk er kode omgitt av krøllete seler {og}). Ikke vent med å erklære variabler til deres første bruk; det kan forvirre den uforsiktige programmereren og hemme koden portabilitet innenfor rammen.

// Foretrekker () erklærer i begynnelsen av blokken.
public void doSomething () {
  int whatIRepresent; // begynnelse av metodeblokk
  hvis (betingelse) {
    int noenFlagg; // begynnelsen av “if” -blokk
    ...
  }
}

Det er også viktig å unngå lokale erklæringer som skjuler erklæringer om høyere nivåer og å unngå forvirring som vist nedenfor

int teller;
...
public void doSomething () {
  hvis (betingelse) {
    int teller; // UNNGÅ!
    ...
  }
  ...
}

Avstand og linjeskift - Unngå fristelsen til å lagre 1–2 kodelinjer på bekostning av lesbarhet. Her er alle de beste fremgangsmåtene når det kommer til avstand og blanke linjer (En hvit plass gjør en forskjell)

  • Én (1) blank linje mellom metoder og Spring-utviklere anbefaler to (2) blanke linjer etter konstruktører, statisk blokk, felt og indre klasse
  • Space pad operatører, dvs. bruk int foo = a + b + 1; over int foo = a + b + 1;
  • Skill alle binære operatører unntatt “.” Fra operander ved å bruke et mellomrom
  • Åpen seler “{” vises på slutten av samme linje som erklæringserklæringen eller metoden og lukkestag “}” starter en linje av seg selv innrykket
// Foretrekker () - Mellomrom etter "mens" og før "("
mens (sant) {
  ...
}
// Unngå (x) - I motsetning til over ingen plass
mens (sant) {
  ...
}
// Foretrekker () - Ingen mellomrom mellom "doSomething" og "("
public void doSomething () {
  ...
}
// Unngå (x) - I motsetning til over plassen
public void doSomething () {
  ...
}
// Foretrukket () - Legg til et mellomrom etter et argument
public void doSomething (int a, int b) {
  ...
}
// Foretrekker () - Mellomrom mellom operand og operatører (dvs. +, =)
a + = c + d;
a = (a + b) / (c * d);
mens (d ++ = s ++) {
  n ++;
}

Dokumentasjon og kommentarer

Det er verdt å nevne at nesten all kode endrer seg gjennom hele levetiden, og det vil være tidspunkter når du eller noen prøver å finne ut hva en kompleks blokkkode, en metode eller en klasse er ment å gjøre med mindre det er klart beskrevet. Virkeligheten er nesten alltid som følger

Det er tider at kommentaren til et sammensatt stykke kode, metode, klasse ikke tilfører noen verdi eller tjener formålet. Dette skjer vanligvis når du kommenterer for det.

Kommentarer bør brukes til å gi oversikter over koden og gi tilleggsinformasjon som ikke er lett tilgjengelig i selve koden. La oss komme i gang. Det er to typer kommentarer

Implementering Kommentarer - er ment å kommentere kode eller kommentere om en bestemt implementering av koden.

Dokumentasjonskommentarer - er ment å beskrive spesifikasjonen av koden fra et implementeringsfritt perspektiv som skal leses av utviklere som ikke nødvendigvis har kildekoden for hånden.

Hyppigheten av kommentarer gjenspeiler noen ganger dårlig kvalitet på koden. Når du føler deg tvunget til å legge til en kommentar, kan du vurdere å skrive om koden for å gjøre den tydeligere.

Typer implementeringskommentarer

Det er fire (4) typer implementeringskommentarer som vist nedenfor

  • Blokker kommentar - se eksempel nedenfor
  • Enkeltlinjekommentar - når kommentaren ikke er lengre enn en linje
  • Etterfølgende kommentarer - Veldig kort kommentar flyttet til høyre ende
  • Slutt på linjekommentaren - begynner en kommentar som fortsetter til den nye linjen. Den kan kommentere en komplett linje eller bare en delvis linje. Det skal ikke brukes på flere rad på rad for tekstkommentarer; den kan imidlertid brukes i flere rad på rad for å kommentere kodeseksjoner.
// Blokker kommentar
/ *
 * Bruk: Gir beskrivelse av filer, metoder, datastrukturer
 * og algoritmer. Kan brukes i begynnelsen av hver fil og
 * før hver metode. Brukes til lange kommentarer som ikke passer til
 * enkel linje. 1 Blank linje for å fortsette etter blokkeringskommentaren.
 * /
// Enkeltlinjekommentar
hvis (betingelse) {
 / * Håndter tilstanden. * /
  ...
}
// Etterfølgende kommentar
hvis (a == 2) {
 returnere SANN; /* spesielt tilfelle */
} annet {
 return isPrime (a); / * fungerer bare for rare * /
}
// Slutt på linjekommentaren
if (foo> 1) {
  // Gjør en dobbel klaff.
  ...
} annet {
  return falsk; // Forklar hvorfor her.
}
// if (stolpe> 1) {
//
// // Gjør en trippel-flip.
// ...
//}
//ellers
// returner falsk;

Dokumentasjonskommentarer (dvs. Javadoc)

Javadoc er et verktøy som genererer HTML-dokumentasjon fra din Java-kode ved hjelp av kommentarene som begynner med / ** og slutter med * / - se Wikipedia for mer informasjon om hvordan Javadoc fungerer eller bare les videre.

Her er et eksempel på Javadoc

/ **
 * Returnerer et bildeobjekt som deretter kan males på skjermen.
 * URL-argumentet må spesifisere en absolutt {@link URL}. Navnet
 * argument er en spesifiser som er relativt til url-argumentet.
 * 

 * Denne metoden kommer alltid tilbake umiddelbart, uansett om  * bildet eksisterer. Når denne appleten prøver å tegne bildet på  * på skjermen, vil dataene lastes inn. Grafikken primitiver  * som tegner bildet vil gradvis male på skjermen.  *  * @param url en absolutt URL som gir grunnleggende plassering av bildet  * @param navngi plasseringen av bildet, i forhold til url-argumentet  * @ Sett bildet tilbake på den angitte URL-en  * @see Image  * /  public Image getImage (URL url, String name) {         prøv {             return getImage (ny URL (url, navn));         } fangst (MalformedURLEeksepsjon e) {             returnere null;         }  }

Og det ovennevnte ville resultere i en HTML som følger når javadoc kjøres mot koden som har ovennevnte

Se her for mer

Her er noen nøkkelkoder som du kan bruke for å forbedre kvaliteten på den genererte java-dokumentasjonen.

@author => @author Raf
@code => {@code A  C}
@deprecated => @deprecated deprecation-melding
@exception => @exception IOException kastet når
@link => {@link package.class # medlemsmerke}
@param => @param parameter-navn beskrivelse
@return => Hva metoden returnerer
@see => @see "streng" ELLER @ se  
@since => For å indikere versjonen når en offentlig tilgjengelig metode legges til

For en fullstendig oversikt og mer detaljert beskrivelse se her

Twitter's kodingsstandard fraråder bruk av @author-kode

Koden kan bytte hender flere ganger i løpet av sin levetid, og ganske ofte er den opprinnelige forfatteren av en kildefil uten betydning etter flere iterasjoner. Vi synes det er bedre å stole på forpliktelseshistorikk og OWNERS-filer for å bestemme eierskap til et kodeord.

Følgende er eksempler på hvordan du kan skrive en dokumentasjonskommentar som er innsiktsfull som beskrevet i Twitters kodingsstandard

// Dårlig.
// - Dokumentet forteller ingenting om at metodedeklarasjonen ikke gjorde det.
// - Dette er 'filler doc'. Det ville bestått stilkontroller, men
hjelper ikke noen.
/ **
 * Deler en streng.
 *
 * @param s En streng.
 * @ return En liste over strenger.
 * /
Liste  delt (streng);
// Bedre.
// - Vi vet hva metoden deler seg på.
// - Fortsatt noe udefinert oppførsel.
/ **
 * Deler en streng på hvitområdet.
 *
 * @param s Strengen som skal deles. En {@code null} streng blir behandlet som en tom streng.
 * @ return En liste over delene av inndata som er avgrenset med det hvite mellomrom.
 * /
Liste  delt (streng);
// Flott.
// - Dekker nok en kantkant.
/ **
 * Deler en streng på hvitområdet. Gjentatte mellomromstegn
 * er kollapset.
 *
 * @param s Strengen som skal deles. En {@code null} streng blir behandlet som en tom streng.
 * @ return En liste over delene av inndata som er avgrenset med det hvite mellomrom.
 * /
Liste  delt (streng);

Det er viktig å være profesjonell når det gjelder å skrive kommentarer

// Unngå (x)
// Jeg hater xml / såpe, hvorfor kan den ikke gjøre dette for meg !?
prøv {
  userId = Integer.parseInt (xml.getField ("id"));
} fangst (NumberFormatException e) {
  ...
}
// Foretrekker ()
// TODO (Jim): Valg av feltfelt bort i et bibliotek.
prøv {
  userId = Integer.parseInt (xml.getField ("id"));
} fangst (NumberFormatException e) {
  ...
}

Og det er viktig å huske på å ikke dokumentere overstyret metode med mindre implementeringen har endret seg.

Og her er noen flere punkter du må huske på

  • Unngå import av jokertegn - som beskrevet i Twitters kodingsstandarder, gjør det kilden til klassen mindre tydelig. Jeg jobber i et team med en blanding av Eclipse- og IntelliJ-brukere, og jeg fant ut at Eclipse fjerner import av jokertegn og IntelliJ introduserer den. Det er sannsynligvis et alternativ for å slå den av, ville bare peke på standard for de to.
  • Bruk alltid @Override kommentar når du overstyrer
  • Oppmuntre til bruk av @Nullable når et felt eller metode returnerer null
  • Benytt deg av spesielle kommentarer for fremtidig arbeid, og ikke glem å legge igjen en henvisning til deg selv, så andre vet hvem de skal stille sitt Y-spørsmål i stedet for å gjette, fjerne det eller sjekke git-skylden for å finne hvem som la til det. Noen IDE-er som Eclipse og IntelliJ hjelper også med å liste opp disse for enkel tilgang og en påminnelse.
// FIXME (Raf): En handlingsfull melding beskriver hva som må gjøres
// TODO (Raf): En handlingsfull melding beskriver hva som må gjøres

Sluttspillet er å skrive kode som gjør livet til fremtidige forfattere og vedlikeholdere enkelt.

Sluttspillet

Andre relevante lesestoffer

En liste over relevante artikler som er relevante for å skrive kode som er ren, godt strukturert, lett å lese og vedlikeholde. Hvis du ønsker å lese mer, anbefaler du absolutt følgende

og en annen god liste over tips for å skrive ren kode