Stručné shrnutí osvědčených postupů kódování Java

založené na standardech kódování společností Oracle, Google, Twitter a Spring Framework

Cílem tohoto článku je poskytnout vám rychlé shrnutí úkolů a jinými slovy preferovat a vyhýbat se na základě kódovacích standardů od technických gigantů, jako jsou Oracle, Google, Twitter a Spring Framework.

Můžete nebo nemusíte souhlasit s některými doporučenými postupy zde uvedenými, a to je naprosto v pořádku, pokud existuje nějaký standard pro kódování.

Proč kódování standardů na prvním místě? Existuje mnoho dobrých důvodů, pokud to Google Google a já vám nechám následující obrázek

Dokument standardů kódování může být zdlouhavý a nudný. Tento článek cherry vybírá kousky a kousky z konvencí kódování společností Google, Oracle, Twitter a Spring a jeho cílem je poskytnout vám snadno sledovatelný a méně nudný soubor praktik, aby byl váš kód snadno čitelný a udržovatelný.

Téměř vždy se připojíte k týmům, které pracují na existujícím softwaru, a existuje docela dobrá šance, že většina autorů odešla nebo přešla na jiné projekty, takže jste uvázli s částmi kódu, díky nimž zpochybňujete lidstvo.

Podívejme se na osvědčené postupy z různých standardů kódování.

Zdrojový soubor Java

Následující postup je považován za osvědčený postup, pokud jde o zdrojové soubory java:

  • Délka zdrojového souboru je menší než 2 000 řádků kódu
  • Zdrojový soubor je organizován s komentářem k dokumentaci, deklarací balíčku, následovaným komentářem k třídě, importem seskupeným (statický poslední), podpisem třídy / rozhraní atd., Jak je uvedeno níže
balíček com.example.model;
/ **
 * Perspektiva bez implementace, kterou si vývojáři přečtou
 * kteří nemusí mít nutně k dispozici zdrojový kód
 *
 * @autor x, y, z
 * @schůzka, termín
 * @verze
 * @autorská práva
 *
 * /
import com.example.util.FileUtil;
/ *
 * Volitelný komentář pro konkrétní třídu
 *
 * /
veřejná třída SomeClass {
  // Statické proměnné v pořadí viditelnosti
  veřejné statické finální celé číslo PUBLIC_COUNT = 1;
  statické konečné celé číslo PROTECTED_COUNT = 1;
  soukromé statické finální celé číslo PRIVATE_COUNT = 1;
  // Proměnné instance v pořadí viditelnosti
  public String name;
  String postalCode;
  soukromá adresa řetězce;
  // Konstruktor a přetížený v sekvenčním pořadí
  public SomeClass () {}
  public SomeClass (String name) {
    this.name = name;
  }
  // Metody
  public String doSomethingUseful () {
    návrat "Něco užitečného";
  }
  // getters, setters, rovná se, hashCode a toString na konci
}

Pojmenování

Názvy tříd a rozhraní jsou CamelCase a je doporučeno používat celé slovo a vyhýbat se zkratkám. Například třída Raster nebo třída ImageSprite

  • Package - jména com.deepspace přes com.deepSpace nebo com.deep_space
  • Názvy souborů jsou CamelCase a končící na .java odpovídající názvu třídy. V každém souboru je jedna veřejná třída s každou třídou nejvyšší úrovně v jejím souboru
  • Metoda - jména by měla být slovesa ve smíšeném případě, přičemž každé interní slovo je velké, například run (); or runFast ();
  • Konstanty - měla by být velká písmena, přičemž každé slovo odděluje „_“, například int MIN_WIDTH = 44; a int MAX_WIDTH = 99;
  • Proměnná - jméno, které sděluje čtenáři programu, co proměnná představuje, tj. Pokud ukládáte testovací stupeň, vyberte stupeň vs var1. Názvy proměnných udržujte krátké, vyhněte se zahrnutí metadat.
// Prefer () - krátká jména proměnných a popište, co ukládá
int schoolId;
int []filtrovánoSchoolIds;
int [] uniqueSchooldIds;
Mapa  usersById;
Řetězcová hodnota;
// Vyhnout se (x) - Příliš podrobné pojmenování proměnných
int schoolIdentificationNumber;
int [] userProvidedSchoolIds;
int [] schoolIdsAfterRemovingDuplicates;
Mapa  idToUserMap;
String valueString;

Pamatujte - název proměnné by měl být krátký a snadno sdělte čtenáři, jakou hodnotu představuje. Použijte svůj úsudek.

Preferujte & Vyhněte se

Formátování a odsazení jsou o uspořádání vašeho kódu, aby byl snadno čitelný, a zahrnuje mezery, délku řádku, obaly a konce atd.

  • Odsazení - použijte 2 nebo 4 mezery a zůstaňte v souladu
  • Délka řádku - Až 70 až 120 znaků v závislosti na vlivu na čitelnost. Je důležité vyloučit potřebu vodorovného rolování a zalomení řádků za čárkou a operátorem.

Metody - Zde je seznam doporučených postupů

// Prefer () Konce řádků jsou libovolné a za čárkou jsou konce.
String downloadAnInternet (internetový internet, Trubky,
    Blogy blogosféry, šířka pásma ) {
  tubes.download (internet);
}
// Vyhněte se (x) Obtížnost metody se liší od těla metody
String downloadAnInternet (internetový internet, Trubky,
    Blogy blogosféry, šířka pásma ) {
    tubes.download (internet);
}
// Preferujte () Přidejte 8 (dvojnásobek ze 2 nebo 4) mezer pro hluboké odsazení
soukromá statická synchronizovaná horkingLongMethodName (int anArg,
        Objekt otherArg, String yetAnotherArg,
        Objekt andStillAnother) {
  ...
}
// Preferujte () Snadné skenování a další sloupec.
public String downloadAnInternet (
    Internet,
    Trubky,
    Blogy blogosféry,
    Částka  šířka pásma) {
  tubes.download (internet);
  ...
}
Jednotkový test by to zachytil

If-check - IMO psaní dobře naformátovaného kódu usnadňuje rozpoznání překlepů a chyb autorovi a recenzentům kódu, viz níže:

// Vyhněte se (x) Nezapomeňte {}
pokud (podmínka)
  tvrzení;
// Vyhněte se (x)
jestliže (x <0) negativní (x);
// Vyhněte se (x)
if (a == b && c == d) {
...
}
// Preferujte ()
if ((a == b) && (c == d)) {
...
}
// Preferujte ()
if (podmínka) {
  prohlášení;
} jinak pokud (podmínka) {
  prohlášení;
} jinak pokud (podmínka) {
  prohlášení;
}
// Vyhněte se (x)
if ((podmínka1 && podmínka2)
    || (podmínka 3 && podmínka4)
    ||! (podmínka 5 && podmínka6)) {// BAD WRAPS
    doSomethingAboutIt (); // PŘEČTĚTE SI TENTO ŘÁD SNADNO
}
// Preferujte ()
if ((podmínka1 && podmínka2)
        || (podmínka 3 && podmínka4)
        ||! (podmínka 5 && podmínka6)) {
    doSomethingAboutIt ();
}

Ternární operátor - A níže jsou doporučené postupy

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

Přepnout - pokud jde o přepnutí, je to nejlepší postup

  • Vždy máte výchozí případ i bez kódu
  • Pomocí / * prochází * / označte, že se ovládací prvek dostane k dalšímu případu
přepínač (podmínka) {
  případ ABC:
    prohlášení;
  / * prochází * /
  případ DEF:
    prohlášení;
    přestávka;
  výchozí:
    prohlášení;
     přestávka;
}

Výjimečné zprávy - Při vyvolání výjimky jsou zde ukázky dobrých a špatně odsazených zpráv.

// Vyhněte se (x) - Není snadné číst
throw new IllegalStateException („Nepodařilo se zpracovat požadavek“ + request.getId ()
    + "pro uživatele" + user.getId () + "query: '" + query.getText ()
    + "'");
// Prefer () - Je to mnohem snazší čtení
vyvolejte novou IllegalStateException („Nepodařilo se zpracovat“)
    + „žádost“ + žádost.getId ()
    + „pro uživatele“ + user.getId ()
    + "query: '" + query.getText () + "'");

Iterátory a proudy - proudy se stávají běžnějšími a občas to může být velmi složité, proto je pro snadné čtení důležité odsazení.

// Vyhněte se (x) - Není snadné číst
Iterable  modules = ImmutableList.  builder (). Add (new LifecycleModule ())
    .add (new AppLauncherModule ()). addAll (application.getModules ()). build ();
// Prefer () - Je to mnohem snazší čtení
Iterable  modules = ImmutableList.  builder ()
    .add (nový LifecycleModule ())
    .add (nový AppLauncherModule ())
    .addAll (application.getModules ())
    .stavět();
Stačí sledovat kódovací standard - každý opravdu

Prohlášení a přiřazení - Doporučuje se jedno prohlášení na řádek, protože podporuje komentáře, jak je uvedeno níže.

// Preferujte ()
úroveň int; // úroveň odsazení
int sizeMeter; // velikost tabulky
// Vyhněte se (x) ve prospěch výše uvedeného
úroveň int, sizeMeter;
// Prefer () - Zahrňte jednotku do názvu nebo typu proměnné
dlouhé pollIntervalMs;
int fileSizeGb;
Částka  fileSize;
// Vyvarujte se (x) typů míchání
int foo, fooarray [];
// Vyhněte se (x) - Neoddělovejte čárkou
Format.print (System.out, „error“), exit (1);
// Vyhněte se (x) vícenásobnému přiřazení
fooBar.fChar = barFoo.lchar = 'c';
// Vyvarujte se (x) vestavěných přiřazení ve snaze zvýšit výkon // nebo uložit řádek. Jsem vinen za to :(
d = (a = b + c) + r;
// Preferujte () nad výše
a = b + c;
d = a + r;
// Preferujte ()
String [] args
// Vyhněte se (x)
String args []
// Preferujte () Dlouho použijte „L“ místo „l“, abyste zabránili záměně s 1
dlouhý časový limit = 3000000000L;
// Vyhněte se (x) - Těžko říct poslední písmeno je 1 a ne 1
dlouhý časový limit = 3000000000l;

Deklarace vkládejte pouze na začátek bloků (blok je kód obklopený složenými závorkami {a}). Nečekejte na deklaraci proměnných až do jejich prvního použití; může zmatit nežádoucí programátor a ztěžovat přenositelnost kódu v rozsahu.

// Preferujte () deklarovat na začátku bloku.
public void doSomething () {
  int whatIRepresent; // začátek bloku metod
  if (podmínka) {
    int someFlag; // začátek bloku „if“
    …
  }
}

Je také důležité vyhnout se místním prohlášením, která skryjí prohlášení vyšších úrovní a vyhnout se zmatkům, jak je uvedeno níže

int count;
...
public void doSomething () {
  if (podmínka) {
    int count; // VYHÝBAT SE!
    ...
  }
  ...
}

Mezery a zalomení řádků - Vyhněte se pokušení ukládat 1–2 řádky kódu na úkor čitelnosti. Zde jsou všechny osvědčené postupy, pokud jde o mezery a prázdné řádky (Bílý prostor dělá rozdíl)

  • Jeden (1) prázdný řádek mezi metodami a vývojáři na jaře doporučuje dva (2) prázdné řádky za konstruktory, statický blok, pole a vnitřní třídu
  • Operátory mezerníku, tj. Použijte int foo = a + b + 1; přes int foo = a + b + 1;
  • Oddělte všechny binární operátory kromě „.“ Od operandů používajících mezeru
  • Otevřená rovnátka „{“ se objeví na konci stejného řádku jako prohlášení nebo metoda deklarace a závěrečná rovnátka „}“ spustí řádek sám odsazený
// Prefer () - mezera za „while“ a před „(“
while (true) {
  ...
}
// Vyhněte se (x) - Na rozdíl od prostoru bez mezer
while (true) {
  ...
}
// Prefer () - Mezi "doSomething" a "("
public void doSomething () {
  ...
}
// Vyhněte se (x) - Na rozdíl od prostoru nad
public void doSomething () {
  ...
}
// Prefer () - Za argument přidejte mezeru
public void doSomething (int a, int b) {
  ...
}
// Prefer () - mezera mezi operandem a operátory (tj. +, =)
a + = c + d;
a = (a + b) / (c * d);
while (d ++ = s ++) {
  n ++;
}

Dokumentace a komentáře

Stojí za zmínku, že téměř celý kód se během celé své životnosti mění a budou chvíle, kdy se vy nebo někdo snažíte zjistit, co je složitý blok kódu, metoda nebo třída zamýšleno, pokud není jasně popsán. Realita je téměř vždy následovní

Někdy komentář k složité části kódu, metody, třídy nepřidává žádnou hodnotu ani neslouží jejímu účelu. K tomu obvykle dochází, když se k tomu vyjadřují komentáře.

Poznámky by měly být použity k poskytnutí přehledů kódu a poskytnutí dalších informací, které nejsou snadno dostupné v samotném kódu. Začněme. Existují dva typy komentářů

Poznámky k implementaci - mají komentovat kód nebo komentář k konkrétní implementaci kódu.

Poznámky k dokumentaci - mají za cíl popsat specifikaci kódu z pohledu bez implementace, který si mají přečíst vývojáři, kteří nemusí mít zdrojový kód nutně po ruce.

Četnost komentářů někdy odráží špatnou kvalitu kódu. Pokud se cítíte nuceni přidat komentář, zvažte přepsání kódu, aby byl jasnější.

Typy implementačních komentářů

Níže jsou uvedeny čtyři (4) typy implementačních komentářů

  • Blokovat komentář - viz příklad níže
  • Jeden řádkový komentář - pokud komentář není delší než jeden řádek
  • Koncové komentáře - Velmi krátký komentář byl přesunut na pravý konec
  • Konec řádku - začíná komentář, který pokračuje na nový řádek. Může komentovat celý řádek nebo pouze částečný řádek. Nemělo by být použito na více po sobě jdoucích řádcích pro textové komentáře; lze ji však použít v několika po sobě jdoucích řádcích pro komentování sekcí kódu.
// Blokovat komentář
/ *
 * Použití: Poskytuje popis souborů, metod, datových struktur
 * a algoritmy. Lze použít na začátku každého souboru a
 * před každou metodou. Používá se pro dlouhé komentáře, které se nehodí
 * jeden řádek. 1 Prázdný řádek pro pokračování za komentářem k bloku.
 * /
// Jeden řádkový komentář
if (podmínka) {
 / * Zvládněte podmínku. * /
  ...
}
// Zadní komentář
if (a == 2) {
 návrat PRAVDA; /* speciální případ */
} jinde {
 návrat isPrime (a); / * funguje pouze pro liché a * /
}
// komentář na konci řádku
if (foo> 1) {
  // Proveďte dvojité převrácení.
  ...
} jinde {
  návrat false; // Vysvětlete proč.
}
// if (bar> 1) {
//
// // Proveďte trojité převrácení.
// ...
//}
//jiný
// return false;

Poznámky k dokumentaci (tj. Javadoc)

Javadoc je nástroj, který generuje HTML dokumentaci z java kódu pomocí komentářů začínajících / ** a končících * / - viz Wikipedia, kde najdete další podrobnosti o tom, jak Javadoc pracuje, nebo si jen přečtěte.

Zde je příklad Javadocu

/ **
 * Vrátí obrazový objekt, který lze poté malovat na obrazovku.
 * Argument url musí specifikovat absolutní {@link URL}. Název
 * argument je specifikátor, který je relativní k argumentu url.
 * 

 * Tato metoda se vždy vrací okamžitě, ať už je nebo není  * obrázek existuje. Když se tento applet pokusí nakreslit obrázek  * na obrazovce budou data načtena. Grafické primitivy  *, které nakreslí obrázek, se budou postupně malovat na obrazovku.  *  * @param url absolutní URL udávající základní umístění obrázku  * @param pojmenujte umístění obrázku vzhledem k argumentu url  * @vraťte obrázek na zadanou adresu URL  * @ viz obrázek  * /  public Image getImage (URL URL, String name) {         Snaž se {             return getImage (nová adresa URL (adresa URL, jméno));         } úlovek (MalformedURLException e) {             návrat null;         }  }

A výše uvedené by vyústilo v HTML, jak bude následovat, když se javadoc spustí proti kódu, který má výše

Více zde

Zde jsou některé klíčové značky, které můžete použít ke zvýšení kvality generované dokumentace Java.

@author => @author Raf
@code => {@code A  C}
@deprecated => @deprecated deprecation-message
@exception => @exception IOException vyvolán, když
@link => {@link package.class # member label}
@param => @param název-parametru popis
@return => Co se metoda vrací
@see => @see "řetězec" NEBO @see  
@since => Označení verze při přidání veřejně dostupné metody

Úplný seznam a podrobnější popis naleznete zde

Kódovací standard služby Twitter nedoporučuje použití značky @author

Kód může během svého života mnohokrát změnit ruce a po několika iteracích je často původní autor zdrojového souboru irelevantní. Zjistili jsme, že je lepší důvěřovat historii odevzdání a souborům OWNERS, abychom určili vlastnictví souboru kódu.

Následuje příklad, jak byste mohli napsat komentář k dokumentaci, který je bystrý, jak je popsáno v normě kódování Twitter

// Špatné.
// - Doktor neříká nic, co deklarace metody ne.
// - Toto je 'filler doc'. Prošlo by to kontrolami stylu, ale
nikomu nepomůže.
/ **
 * Rozdělí řetězec.
 *
 * @param s Řetězec.
 * @return Seznam řetězců.
 * /
Seznam  split (String s);
// Lepší.
// - Víme, na co se metoda dělí.
// - Stále nějaké nedefinované chování.
/ **
 * Rozdělí řetězec na bílé.
 *
 * @param s Řetězec, který se má rozdělit. Řetězec {@code null} je považován za prázdný řetězec.
 * @return Seznam částí textu oddělených mezerami.
 * /
Seznam  split (String s);
// Skvělý.
// - Pokrývá další okrajový případ.
/ **
 * Rozdělí řetězec na bílé. Opakované znaky mezery
 * jsou zhrouteny.
 *
 * @param s Řetězec, který se má rozdělit. Řetězec {@code null} je považován za prázdný řetězec.
 * @return Seznam částí textu oddělených mezerami.
 * /
Seznam  split (String s);

Při psaní komentářů je důležité být profesionální

// Vyhněte se (x)
// Nenávidím xml / mýdlo tolik, proč to nemůže udělat pro mě !?
Snaž se {
  userId = Integer.parseInt (xml.getField ("id"));
} catch (NumberFormatException e) {
  ...
}
// Preferujte ()
// TODO (Jim): Potvrzení pole v knihovně.
Snaž se {
  userId = Integer.parseInt (xml.getField ("id"));
} catch (NumberFormatException e) {
  ...
}

A je důležité mít na paměti, aby nebyla dokumentována přepsaná metoda, pokud se nezmění implementace.

A zde je několik dalších bodů, které byste měli mít na paměti

  • Vyhněte se importům zástupných znaků - jak je popsáno v kódovacích standardech Twitteru, je zdroj třídy méně jasný. Pracuji v týmu se směsicí uživatelů Eclipse a IntelliJ a zjistil jsem, že Eclipse odstraní import zástupných znaků a IntelliJ jej představí. Pravděpodobně existuje možnost, jak to vypnout, jen jsem chtěl poukázat na výchozí pro oba.
  • Při přepisování vždy používejte anotaci @Override
  • Podporujte použití @Nullable, když se pole nebo metoda vrátí null
  • Využijte speciální komentáře pro budoucí práci a nezapomeňte zanechat odkaz na sebe, aby ostatní věděli, komu položit svou otázku Y, místo hádání, odstraňování nebo kontroly viny za účelem zjištění, kdo ji přidal. Některé IDE, jako jsou Eclipse a IntelliJ, také pomáhají při jejich uvádění pro snadný přístup a připomenutí.
// FIXME (Raf): Zpráva, kterou lze provést, popisuje, co je třeba udělat
// TODO (Raf): Zpráva, kterou lze provést, popisuje, co je třeba udělat

Konečná hra je napsat kód, který usnadní život budoucím autorům a správcům.

Konečná hra

Další relevantní materiály pro čtení

Seznam relevantních článků, které jsou důležité pro psaní kódu, který je čistý, dobře strukturovaný, snadno čitelný a udržovatelný. Pokud si chcete přečíst více, rozhodně doporučujeme následující

a další dobrý seznam tipů pro psaní čistého kódu