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: specifies that a method parameter or return value should be non-null or nullable.
 * @ParametersAreNonnullByDefault: all parameters on this class / package / method are expected to be non null unless otherwise specified.
 * @Immutable: this class is immutable.
 * @ThreadSafe / @NotThreadSafe: this class is or is not thread safe.

JSON / XML
Jackson is used for most JSON and XML parsing / serialization, with the use of annotations.

HTTP client
Apache HttpComponents is used as an HTTP client.

As much as possible a single instance of  should be shared within an application. A custom User Agent string should be configured.

Unit Testing Framework
We mostly use JUnit as a testing framework. Some projects are using JUnit 4, while others are using JUnit 5. Some projects have dependencies on component specific testing libraries that don't support JUnit 5 yet. For projects that don't have this limitation, JUnit 5 should be preferred.

Mocking
Mockito is used as a mocking framework where needed.

HTTP Mocking
WireMock is used as an HTTP mock server, which allows testing code that relies on HTTP interactions. Note that WireMock makes it easy to also test various faults (delays, timeout, etc...).

Assertions
AssertJ is our main assertion framework. In almost all cases AssertJ should be preferred over plain, JUnit assertions or Hamcrest.

Unit vs Integration Tests
We follow the usual naming conventions to identify unit tests vs integration tests.

Managing and defensive programming
As much as possible,  values should be avoided. Null Objects should be preferred. Parameters should be expected to be non null and not explicitly checked, unless they come from an untrusted caller. Parameters should be marked with  /   to allow static analysis tools to validate nullity.

Context
Serialization and the use of serialVersionUID is complex topic. In short:


 * when a class is serialized, it's  is part of the serialization
 * when a class is deserialized, the serialized  is compared with the target class, if they don't match, deserialization fails
 * can be set manually, otherwise it is auto computed by the serialization runtime, the UID will change if the structure of the class changes, it might be different across different JRE vendors or versions

Leaving the runtime to compute the  can lead to cases where class versions should be compatible but still fail deserialization.

Manually setting the  can lead to cases where class versions should NOT be compatible but still successfully deserialize, leading to silent problems (when the class structure has changed, but the   has not been updated).

guidelines
should be manually defined only when:


 * classes are expected to be deserialized (not if they just need to extend Serializable)
 * the class or JVM version might change between serialization and deserialization

If manually defined,  should start at   and be incremented on each change to the class structure. The range from  to   is considered non-generated by the FindBugs'   rules