Kratki sažetak najboljih praksi kodiranja Java

na temelju standarda kodiranja od strane Oracle, Googlea, Twittera i Spring Framework-a

Cilj ovog članka je dati vam kratak sažetak posla i nemojte drugim riječima preferirati i izbjegavati na temelju standarda kodiranja tehnoloških divova kao što su Oracle, Google, Twitter i Spring Framework.

Možda se ili ne slažete s nekim od ovdje prikazanih najboljih praksi, i to je sasvim u redu ako postoji neki standard za kodiranje.

Zašto standardi kodiranja na prvom mjestu? Mnogo je dobrih razloga ako to objavite na Googleu, a ja ću vam ostaviti sljedeću ilustraciju

Dokument sa standardima kodiranja može biti dugotrajan i dosadan. Ovaj članak trešnja bira komade i dijelove iz konvencija kodiranja od strane Googlea, Oracle, Twittera i Springa, a cilj mu je pružiti vam jednostavan praćenje i manje dosadan niz postupaka kako bi vaš kôd bio lak za čitanje i održavanje.

Gotovo uvijek ćete se pridružiti timovima koji rade na postojećem softveru i postoji prilično dobra šansa da je većina autora napustila ili prešla na različite projekte, ostavljajući vas na cjedilu s dijelovima koda koji vas dovode u pitanje čovječanstvo.

Uđimo u najbolje prakse iz različitih standarda kodiranja.

Java izvorna datoteka

Sljedeće se smatra najboljom praksom kada su u pitanju izvorne datoteke Java:

  • Duljina izvorne datoteke manja je od 2.000 redaka koda
  • Izvorna datoteka organizirana je s komentarom dokumentacije, deklaracijom paketa, zatim komentarom klase, uvozom grupiranim (statički zadnji), potpisom klase / sučelja i tako dalje, kao što je prikazano u nastavku
paket com.example.model;
/ **
 * Perspektiva bez primjene koju trebaju čitati programeri
 * koji možda ne moraju nužno imati izvorni kod pri ruci
 *
 * @author x, y, z
 * @date
 * @verzija
 * @ autorskih prava
 *
 * /
import com.example.util.FileUtil;
/ *
 * Neobavezni komentar specifičan za klasu
 *
 * /
javna klasa SomeClass {
  // Statičke varijable prema redoslijedu vidljivosti
  javni statički konačni Integer PUBLIC_COUNT = 1;
  statički konačni cjelobrojni broj PROTECTED_COUNT = 1;
  privatni statički završni Integer PRIVATE_COUNT = 1;
  // Promjene instanci prema redoslijedu vidljivosti
  javni nizovi;
  Niz poštanskog broja;
  privatna string adresa;
  // Konstruktor i preopterećen redoslijedom
  javni SomeClass () {}
  javni SomeClass (Ime niza) {
    this.name = ime;
  }
  // Metode
  javni String doSomethingUseful () {
    povratak "Nešto korisno";
  }
  // getters, setters, equals, hashCode i toString na kraju
}

Imenovanje

Nazivi klase i sučelja su CamelCase i preporučuje se upotreba cijele riječi i izbjegavanje akronima / skraćenica. Na primjer klasa Raster ili klasa ImageSprite

  • Paket - naziva com.deepspace preko com.deepSpace ili com.deep_space
  • Nazivi datoteka su CamelCase i završavaju s .java podudaranjem s nazivom klase. Postoji jedna javna klasa po datoteci sa svakom razredom najviše razine u svojoj datoteci
  • Metoda - imena trebaju biti glagoli u miješanom slučaju, a svaka interna riječ s velikim slovom, na primjer run (); ili runFast ();
  • Konstante - trebaju biti velika slova s ​​"_" odvajanjem svake riječi, na primjer, int MIN_WIDTH = 44; i int MAX_WIDTH = 99;
  • Varijabla - naziv koji čitatelju programa govori što varijabla predstavlja, tj. Ako spremate testnu ocjenu, tada odaberite ocjenu vs var1. Imena varijabli kraće izbjegavajte, uključujući metapodatke.
// Prefer () - nazivi varijabli su kratki i opisuju što pohranjuje
int schoolId;
int [] filtriraneSchoolIds;
int [] jedinstveniSchooldIds;
Karta  usersById;
Vrijednost niza;
// Izbjegavaj (x) - Previše detaljno imenovanje varijabli
int schoolIdentificationNumber;
int [] userProvidedSchoolIds;
int [] schoolIdsAfterRemovingDuplicates;
Karta  idToUserMap;
Vrijednost nizaString;

Zapamtite - naziv varijable trebao bi biti kratak i čitatelju lako reći koju vrijednost predstavlja. Upotrijebite svoj sud.

Preferirajte i izbjegavajte

Formatiranje i odstupanja odnose se na organiziranje koda radi lakšeg čitanja, a uključuje razmake, duljinu retka, obloge i prijelome itd.

  • Udubljenje - koristite 2 ili 4 razmaka i budite dosljedni
  • Duljina retka - do 70 do 120 znakova, ovisno o utjecaju na čitljivost. Važno je ukloniti potrebu za horizontalnim pomicanjem i postavljanjem prijeloma linija nakon zareza i operatora.

Metode - Ovdje je popis najboljih praksi

// Preferira () Prijelomi redaka su proizvoljni i prelomi se nakon zareza.
Preuzimanje nizaAnInternet (Internet Internet, cijevi,
    Blogosphere blogovi, Količina  širina pojasa) {
  tubes.download (Internet);
}
// Izbjegavajte (x) argumente koji se teško razlikuju u tijelu metode
Preuzimanje nizaAnInternet (Internet Internet, cijevi,
    Blogosphere blogovi, Količina  širina pojasa) {
    tubes.download (Internet);
}
// Preferirajte () Dodajte 8 (dvostruko 2 ili 4) razmaka za duboku uvlaku
privatni statički sinkronizirani horkingLongMethodName (int anArg,
        Object anotherArg, String yetAbodyArg,
        Object andStillAgether) {
  ...
}
// Preferirajte () Jednostavno skeniranje i dodatni prostor stupaca.
preuzimanje javnog nizaAnInternet (
    Internet Internet,
    Cijevi cijevi,
    Blogovi o blogosferi,
    Iznos  širina pojasa) {
  tubes.download (Internet);
  ...
}
Jedinstveni test bi to uhvatio

Ako se provjeri - IMO pisanje dobro oblikovanog koda olakšava uočavanje pogrešaka pri upisu i pogrešaka autoru i recenzentima koda, pogledajte u nastavku:

// Izbjegavajte (x) ne izostavljajte {}
ako (uvjet)
  izjava;
// Izbjegavaj (x)
ako je (x <0) negativan (x);
// Izbjegavaj (x)
ako je (a == b&& c == d) {
...
}
// Preferiraj ()
ako je ((a == b) && (c == d)) {
...
}
// Preferiraj ()
ako (uvjet) {
  izjave;
} else if (uvjet) {
  izjave;
} else if (uvjet) {
  izjave;
}
// Izbjegavaj (x)
if ((uvjet1 i uvjeti2)
    || (uvjet 3 i uvjeti4)
    ||! (uvjet5 && uvjeti6)) {// BAD WRAPS
    doSomethingAboutIt (); // OVU LINIJU LAKO MISLITE
}
// Preferiraj ()
if ((uvjet1 i uvjeti2)
        || (uvjet 3 i uvjeti4)
        ||! (condition5 && condition6)) {
    doSomethingAboutIt ();
}

Ternarni operator - i ispod su preporučene prakse

alfa = (aLongBooleanExpression)? beta: gama;
alfa = (aLongBooleanExpression)? beta
        : gama;
alfa = (aLongBooleanExpression)
        ? beta
        : gama;

Switch - kada je u pitanju prelazak na najbolju praksu

  • Uvijek imajte zadani slučaj, čak i bez koda
  • Upotrijebite / * prolazi kroz * / da označite pad pada na sljedeći slučaj
prebaciti (uvjet) {
  slučaj ABC:
    izjave;
  / * pada kroz * /
  slučaj DEF:
    izjave;
    pauza;
  zadano:
    izjave;
     pauza;
}

Poruke izuzetaka - Kada bacate iznimku, ovdje su uzorci dobrih i slabo razvedenih poruka.

// Izbjegavajte (x) - Nije lako čitati
baciti novu IllegalStateException ("Neuspješno obrađivanje zahtjeva" + request.getId ()
    + "za korisnika" + user.getId () + "upit:" "+ query.getText ()
    + "'");
// Prefer () - prilično je lako čitati
izbaci novu IllegalStateException ("Neuspjelo obrađivanje"
    + "zahtjev" + request.getId ()
    + "za korisnika" + user.getId ()
    + "upit:" "+ query.getText () +" '");

Iteratori i tokovi - potoci postaju sve češći i ponekad mogu biti vrlo složeni, stoga je važno uvlačiti uvlačenje radi lakšeg čitanja.

// Izbjegavajte (x) - Nije lako čitati
Isključivi moduli  = ImmutableList.  builder (). Add (novi LifecycleModule ())
    .add (novi AppLauncherModule ()). addAll (application.getModules ()). build ();
// Prefer () - prilično je lako čitati
Iterable  module = ImmutableList.  builder ()
    .add (novi LifecycleModule ())
    .add (novi AppLauncherModule ())
    .addAll (application.getModules ())
    .izgraditi();
Samo slijedite standard kodiranja - sve stvarno

Izjave i zadatci - preporučuje se jedna deklaracija po retku jer potiče komentare kao što je prikazano u nastavku.

// Preferiraj ()
int nivo; // razina udubljenja
int sizeMeter; // veličina tablice
// Izbjegavajte (x) u prilog gore navedenom
int nivo, sizeMeter;
// Prefer () - Uključi jedinicu u naziv ili vrstu varijable
duga anketaIntervalM;
int fileSizeGb;
Iznos  veličina datoteke;
// Izbjegavajte (x) miješanje vrsta
int foo, fooarray [];
// Izbjegavaj (x) - Ne odvajaj se zarezom
Format.print (System.out, "pogreška"), izlaz (1);
// Izbjegavajte (x) višestruko dodjeljivanje
fooBar.fChar = barFoo.lchar = 'c';
// Izbjegavajte (x) ugrađene zadatke u pokušaju povećanja performansi // ili spremanja retka. Ja sam kriv za ovo :(
d = (a = b + c) + r;
// Preferirajte () iznad
a = b + c;
d = a + r;
// Preferiraj ()
String [] args
// Izbjegavaj (x)
String args []
// Preferirajte () Dugo koristite "L" umjesto "l" kako biste izbjegli zbunjenost s 1
dugo vremena = 3000000000L;
// Izbjegavaj (x) - teško je reći da je posljednje slovo l, a ne 1
dugo vremena = 3000000000l;

Deklaraciju stavite samo na početak blokova (Blok je kod okružen kovrčavim zagradama {i}). Nemojte čekati deklariranje varijabli do njihove prve uporabe; može zbuniti nepažljivog programera i ometati prenosivost koda unutar dosega.

// Prefer () deklarirati na početku bloka.
javna void doSomething () {
  int whatIRepresent; // početak bloka metoda
  ako (uvjet) {
    int someFlag; // početak bloka "ako"
    ...
  }
}

Također je važno izbjegavati lokalne deklaracije koje skrivaju deklaracije viših razina i izbjegavati zabune kako je prikazano u nastavku

int count;
...
javna void doSomething () {
  ako (uvjet) {
    int count; // IZBJEGAVAJTE!
    ...
  }
  ...
}

Razmak i prijelomi redaka - Izbjegavajte iskušenje spremanja 1-2 retka koda na štetu čitljivosti. Ovdje su sve najbolje prakse kada su u pitanju razmaci i prazne crte (bijeli prostor čini neku razliku)

  • Jedna (1) prazna linija između metoda i Spring programera preporučuje dvije (2) prazne crte nakon konstruktora, statički blok, polja i unutarnju klasu
  • Operatori svemirske podloge tj. Koristite int foo = a + b + 1; over int foo = a + b + 1;
  • Odvojite sve binarne operatore osim "." Od operanda koji koriste razmak
  • Otvorena zagrada "{" pojavljuje se na kraju istog retka s izjavom ili metodom deklaracije, a zatvarajući zarez "}" započinje liniju samu s razrezom
// Prefer () - razmak nakon "dok" i prije "("
dok je (istina) {
  ...
}
// Izbjegavaj (x) - za razliku od gore nema prostora
dok je (istina) {
  ...
}
// Prefer () - nema razmaka između "doSomething" i "("
javna void doSomething () {
  ...
}
// Izbjegavaj (x) - za razliku od gornjeg prostora
javna void doSomething () {
  ...
}
// Prefer () - Dodajte razmak nakon argumenta
public void doSomething (int a, int b) {
  ...
}
// Prefer () - razmak između operanda i operatora (tj. +, =)
a + = c + d;
a = (a + b) / (c * d);
dok je (d ++ = s ++) {
  n ++;
}

Dokumentacija i komentari

Vrijedno je napomenuti da gotovo cijeli kôd mijenja promjene tijekom svog životnog vijeka, a postojat će i trenutci kada vi ili netko pokušate shvatiti što treba napraviti složeni blok koda, metoda ili klase ako nije jasno opisano. Realnost je gotovo uvijek takva kakva slijedi

Postoje slučajevi da komentar složenog dijela koda, metode, klase ne dodaje nikakvu vrijednost niti služi njegovoj svrsi. To se obično događa kada komentirate radi njega.

Komentari se trebaju koristiti za pregled koda i pružanje dodatnih informacija koje nisu dostupne u samom kodu. Započnimo. Postoje dvije vrste komentara

Komentari primjene - znače se komentirati kôd ili komentirati određenu implementaciju koda.

Komentari dokumentacije - trebaju opisati specifikaciju koda iz perspektive bez implementacije koju trebaju čitati programeri koji možda ne moraju imati izvorni kod pri ruci.

Učestalost komentara ponekad odražava lošu kvalitetu koda. Kad se osjećate primoranim dodati komentar, razmislite o ponovnom pisanju koda da bi bio jasniji.

Vrste primjena komentara

Postoje četiri (4) vrste komentara za provedbu kao što je prikazano u nastavku

  • Blokiraj komentar - pogledajte primjer u nastavku
  • Komentar s jednom linijom - ako komentar nije duži od retka
  • Zadnji komentari - vrlo kratki komentar premješten je na pravi kraj
  • Komentar na kraju retka - započinje komentar koji nastavlja u novi redak. Može komentirati potpunu ili samo djelomičnu liniju. Ne bi se trebao koristiti u uzastopnim više redaka za komentare teksta; međutim, on se može koristiti u više uzastopnih redaka za komentiranje dijelova koda.
// Blokiraj komentar
/ *
 * Upotreba: pruža opis datoteka, metoda, struktura podataka
 * i algoritmi. Može se koristiti na početku svake datoteke i
 * prije svake metode. Koristi se za duge komentare koji ne odgovaraju a
 * jedna linija. 1 Prazan redak za nastavak nakon komentara na bloku.
 * /
// Komentar u jednom retku
ako (uvjet) {
 / * Riješite stanje. * /
  ...
}
// Zadnji komentar
ako je (a == 2) {
 vratiti TRUE; /* poseban slučaj */
} else {
 povratak jePrime (a); / * radi samo za neparni * /
}
// Komentar na kraju retka
ako (foo> 1) {
  // Napravite dvostruki okret.
  ...
} else {
  vratiti lažno; // Objasnite zašto ovdje.
}
// if (bar> 1) {
//
// // Napravite trostruko okretanje.
// ...
//}
//drugo
// vratiti lažno;

Komentari na dokumentaciju (tj. Javadoc)

Javadoc je alat koji generira HTML dokumentaciju iz vašeg java koda koristeći komentare koji počinju s / ** i završavaju sa * / - za više detalja pogledajte kako funkcionira Javadoc ili samo čitajte.

Evo primjera Javadoca

/ **
 * Vraća objekt slike koji se zatim može slikati na zaslonu.
 * Argument URL mora navesti apsolutni {@link URL}. Ime
 * argument je odrednik koji je u odnosu na argument url.
 * 

 * Ova se metoda uvijek vraća odmah, bez obzira na to je li ili ne  * slika postoji. Kada ovaj aplet pokušava nacrtati sliku  * zaslon, podaci će se učitati. Grafički primitivi  * koji crtaju sliku postepeno će se slikati na zaslonu.  *  * @param url apsolutni URL daje osnovnu lokaciju slike  * @param imenujte lokaciju slike u odnosu na argument URL-a  * @ vratite sliku na navedeni URL  * @ vidi sliku  * /  javna slika getImage (URL URL, naziv niza) {         probaj {             vratiti getImage (novi URL (URL, naziv));         } hvatanje (neispravnoURLException e) {             vratiti null;         }  }

A gore navedeno rezultira HTML-om kao što slijedi kada se javadoc pokrene protiv koda koji ima gore

Pogledajte ovdje za više

Evo nekoliko ključnih oznaka pomoću kojih možete poboljšati kvalitetu generirane java dokumentacije.

@author => @author Raf
@code => {@code A  C}
@deprecated => @deprecated deprecation-message
@exception => @exception IOException bačen kada
@link => {@link package.class # članska oznaka}
@param => @param opis parametra
@return => Što metoda vraća
@see => @see "string" ILI @ vidi  
@since => Navesti verziju kada se doda javno dostupna metoda

Kompletan popis i detaljniji opis pogledajte ovdje

Twitter standard za kodiranje savjetuje uporabu oznake @author

Kôd može mijenjati ruke više puta u svom životnom vijeku, a često je izvorni autor izvorne datoteke nevažan nakon nekoliko iteracija. Smatramo da je bolje da vjerujemo povijesti povijesti počinjenja i vlasnicima datoteka kako bi odredili vlasništvo nad tijelom koda.

Slijede primjeri kako biste mogli napisati komentar dokumentacije koji je uvidan kako je opisano u Twitterovom standardu za kodiranje

// Loše.
// - Dokument ne govori ništa što deklaracija metode nije.
// - Ovo je "doc filler". Prošao bi provjere stila, ali
ne pomaže nikome.
/ **
 * Podijeli niz.
 *
 * @param s A string.
 * @return Popis niza.
 * /
Popis  podijeljen (stringovi);
// Bolje.
// - Znamo na što se ta metoda dijeli.
// - Još uvijek nedefinirano ponašanje.
/ **
 * Podijeli niz na razmaku.
 *
 * @param s Niz za dijeljenje. {@Code null} niz smatra se praznim nizom.
 * @return Popis dijelova ulaza razgraničenih razmakom.
 * /
Popis  podijeljen (stringovi);
// Sjajno.
// - Pokriva još jedan rubni slučaj.
/ **
 * Podijeli niz na razmaku. Ponavljani znakovi s razmacima
 * su urušeni.
 *
 * @param s Niz za dijeljenje. {@Code null} niz smatra se praznim nizom.
 * @return Popis dijelova ulaza razgraničenih razmakom.
 * /
Popis  podijeljen (stringovi);

Kada je u pitanju pisanje komentara, važno je biti profesionalan

// Izbjegavaj (x)
// Toliko mrzim xml / sapun, zašto to ne može učiniti i za mene !?
probaj {
  userId = Integer.parseInt (xml.getField ("id"));
} hvatanje (NumberFormatException e) {
  ...
}
// Preferiraj ()
// TODO (Jim): Provjera valjanosti polja u knjižnici.
probaj {
  userId = Integer.parseInt (xml.getField ("id"));
} hvatanje (NumberFormatException e) {
  ...
}

I važno je imati na umu da ne dokumentirate prevršenu metodu ako se implementacija nije promijenila.

Evo još nekoliko točaka koje morate imati na umu

  • Izbjegavajte uvoz skrivenih znakova - kao što je opisano u Twitterovim standardima kodiranja, izvor klase čini manje jasnim. Radim u timu s kombinacijom korisnika Eclipse i IntelliJ i saznao sam da Eclipse uklanja uvoz zamjenskih znakova i IntelliJ ga uvodi. Vjerojatno postoji opcija da se isključi, samo sam htio ukazati na zadanu za ta dva.
  • Uvijek koristite napomenu @Override prilikom preglasavanja
  • Potaknite upotrebu @Nullable kad polje ili metoda vrati null
  • Iskoristite posebne komentare za budući rad i ne zaboravite ostaviti referencu na sebe kako bi drugi znali kome postaviti Y pitanje, umjesto da nagađaju, uklanjaju ga ili provjeravaju git krivnju kako bi pronašli tko ga je dodao. Neki IDE-ovi poput Eclipse i IntelliJ također pomažu u popisivanju njih radi lakšeg pristupa kao i podsjetnik.
// FIXME (Raf): Dostavna poruka opisuje što treba učiniti
// TODO (Raf): Djelotvorna poruka opisuje što treba učiniti

Krajnja igra je pisanje koda koji olakšava život budućim autorima i održavanjima.

Završna igra

Ostali relevantni materijali za čitanje

Popis relevantnih članaka koji su relevantni za pisanje koda koji je čist, dobro strukturiran, jednostavan za čitanje i održavanje. Ako želite pročitati više, svakako preporučite sljedeće

i još jedan dobar popis savjeta za pisanje čistog koda