Manual:Coding conventions/Java/cs

Tato stránka popisuje kódovací konvence používané v souborech MediaWiki codebase napsané v Java. Viz také obecné konvence, které platí pro všechny programové jazyky, včetně Javy.

Sestavení
Jako stavební nástroj se používá Maven. Všechny projekty by měly zdědit z discovery-parent-pom. Konfiguruje řadu nástrojů pro statickou analýzu a linters, které pomohou udržet projekty koherentní. Konvence kódu jsou začleněny do konfigurace checkstyle používané tímto pom.xml a nebudou zde opakovány. Soubor README v tomto projektu popisuje, jak používat tento nadřazený pom.

Java projekty hostované na Gerritu by měly být sestaveny Jenkinsem pomocí -maven-java8-docker šablony. Pro publikování dokumentace a pro správu procesu vydání jsou k dispozici další šablony.

Java projekty by měly být analyzovány pomocí SonarCloud.



Verze Java
Většina našich projektů je v současné době zaměřena na Java 8. Jsme v procesu přechodu na Java 11.

SDKMAN vám může pomoci spravovat více JDK a snadno mezi nimi přepínat.

Knihovny
V našich různých projektech Java se běžně používá řada knihoven. Použití stejných knihoven pro podobné případy použití může pomoci koherenci napříč projekty. Jak již bylo řečeno, používejte níže uvedený seznam jako návrhy, nikoli jako tvrdé pravidlo.



Guava
Guava se používá v řadě projektů. Všimněte si, že v některých případech máme závislosti, které samy o sobě spoléhají na zastaralé verze Guava, což nám brání používat nejnovější verzi. Funkce Guava, které používáme nejčastěji, jsou:


 * Předpoklady
 * Immutable Collections
 * Caches

Lombok
I když Lombok není striktně knihovna, poskytuje Javě velmi užitečný syntaktické oslazení. Vzhledem k tomu, že Lombok je anotační procesor spouštěný v době kompilace, Lombok nemá žádné runtime závislosti, a proto nevytváří problémy s kompatibilitou.

Lombok lze dále konfigurovat přidáním souboru  na úrovni balíčku, což může být zvláště užitečné, aby se s Jacksonem hrálo pěkně. Příklad takové konfigurace:

lombok.equalsAndHashCode.callSuper = call lombok.extern.findbugs.addSuppressFBWarnings = true lombok.addLombokGeneratedAnnotation = true lombok.anyConstructor.addConstructorProperties = true
 * 1) disable SpotBugs, it does not like generated code by lombok
 * 1) useful for jackson that will be able to use the all args constructor when deserializing

Několik zvláště užitečných funkcí:


 * @Data: usnadňuje generování DTO / DO, stará se o všechny tyto getry / nastavovače a má správný, platný  a.
 * @SneakyThrows: lepší způsob, jak se vypořádat se zaškrtnutými výjimkami, než je zabalit do nekontrolované výjimky.

V závislosti na vašem IDE možná budete muset nainstalovat lombok plugin. Viz [dokumentace https://www.projectlombok.org/setup/overview pro vaše konkrétní IDE].

JSR 305
JSR 305 poskytuje anotace pro lepší dokumentaci očekávaného chování a pomáhá odhalovat chyby. Tyto anotace jsou pouze závislé na čase kompilace a nejsou vyžadovány za běhu, negenerují problémy se závislostmi.

Zejména:


 * @Nonnull / @Nullable - určuje, že parametr metody nebo návratová hodnota by neměly být null nebo s možností null.
 * @ParametersAreNonnullByDefault - očekává se, že všechny parametry v této třídě / balíčku / metodě nebudou null, pokud není uvedeno jinak.
 * @Immutable: this class is immutable.
 * @ThreadSafe / @NotThreadSafe: tato třída je nebo není bezpečná pro vlákna.

JSON / XML
Jackson se používá pro většinu JSON a XML analýzy / serializace s použitím anotací.



HTTP klient
Apache HttpComponents se používá jako HTTP klient.

V rámci aplikace by měla být v maximální možné míře sdílena jedna instance. Měl by být nakonfigurován vlastní řetězec User-Agent.

Unit Testing Framework
Jako testovací rámec většinou používáme JUnit. Některé projekty používají JUnit 4, zatímco jiné používají JUnit 5. Některé projekty jsou závislé na testovacích knihovnách specifických pro komponenty, které zatím nepodporují JUnit 5. U projektů, které toto omezení nemají, by měl být preferován JUnit 5.

Mocking
Mockito se v případě potřeby používá jako napodobující rámec.

HTTP Mocking
WireMock se používá jako falešný server HTTP, který umožňuje testování kódu, který se spoléhá na interakce HTTP. Všimněte si, že WireMock usnadňuje také testování různých poruch (zpoždění, časový limit atd...).

Assertions
AssertJ je náš hlavní rámec tvrzení. Téměř ve všech případech by měl být AssertJ upřednostněn před prostým, tvrzeními JUnit nebo Hamcrest.



Různé konvence


Jednotkové versus integrační testy
Při identifikaci unit testy vs integrační testy se řídíme obvyklými konvencemi pojmenování.



Správa a defensivní programování
Pokud je to možné, měli byste se vyhnout hodnotám. Null Objects should be preferred. U parametrů by se mělo očekávat, že nebudou null a nebudou explicitně kontrolovány, pokud nepocházejí od nedůvěryhodného volajícího. Parametry by měly být označeny  / , aby nástroje statické analýzy mohly ověřit nulitu.

Optionals should be used sparingly. Read this blog post before committing to using Optionals.

Kontext
Serializace a použití serialVersionUID je komplexní téma. Ve zkratce:


 * když je třída serializována, je součástí serializace
 * když je třída deserializována, porovná se serializovaný  s cílovou třídou, pokud se neshodují, deseralizace se nezdaří
 * lze nastavit ručně, jinak je automaticky vypočítán během běhu serializace, UID se změní, pokud se změní struktura třídy, může se lišit u různých dodavatelů nebo verzí JRE

Ponechání doby běhu prostředí pro výpočet  může vést k případům, kdy by verze tříd měly být kompatibilní, ale přesto by deserializace selhala.

Ruční nastavení  může vést k případům, kdy by verze tříd neměly být kompatibilní, ale přesto by se měly úspěšně deserializovat, což vede k tichým problémům (když se struktura třídy změnila, ale   nebyla aktualizována).

pokyny
by měl být definován ručně pouze tehdy, když:


 * očekává se, že třídy budou deserializovány (ne, pokud jen potřebují rozšířit Serializovatelné)
 * verze třídy nebo JVM se může mezi serializací a deserializací změnit

Pokud je definován ručně,  by měl začínat na   a měl by být zvýšen při každé změně struktury třídy. Rozsah od  do   je považován za negenerovaný podle pravidel FindBugs