Skip to content

Java code style

Yevhenii Nadtochii edited this page Feb 25, 2025 · 4 revisions

We use Google Style conventions with 4 spaces (instead of 2) for indentation. Other extensions and changes are described below.


Table of contents


Javadocs

See Javadoc page for details.

Wrapping

Ternary operator

When wrapped, the ternary operator should have ? and : starting lines with options. This way they look like a bulleted list:

EntityStorageRecord singleResult = shouldApplyFieldMask 
        ? standStorage.read(singleId, fieldMask) 
        : standStorage.read(singleId);

Builder call chain

Place the newBuilder() call on a new line after the type:

CompositeColumnFilter result = CompositeColumnFilter
        .newBuilder()
        .addAllFilter(filters)
        .setOperator(operator)
        .build();

This way in Java 11 we'd have a shorter construct with a type clearly visible on the same line:

var result = CompositeColumnFilter
        .newBuilder()
        ...
        .build();

Static import for String.format()

Use the following syntax for building formatted strings:

import static java.lang.String.format;
...

   final String msg = format("Missing event handler for event class %s", eventClass);

This makes the code more compact, and we don't need to read the text String twice on a line.

Dealing with nulls

@ParametersAreNonnullByDefault

This annotation must be set in package-info.java of all the framework packages.

Use @Nullable when required

Everything which is not annotated with @Nullable is not null by default.

Use Tests.<T>nullRef() method in tests

If it is needed to pass null to some method in tests, use Tests.<T>nullRef() method to avoid warning suppressions.

Checking multiple parameters with checkNotNull()

Non-nullity of parameters should be checked in public and protected methods to catch incorrect use of the API as early as possible.

If a method accepts two or more parameters that cannot be null, we call Preconditions.checkNotNull() in the order of parameters. checkNotNull() must be statically imported:

    protected void dispatch(Message message, CommandContext context) {
        checkNotNull(message);
        checkNotNull(context);
        ...
    }

Check null state with checkNotNull()

By convention, checking nullity of a state should be done via checkNotNull(), not via checkState(). For example, a Product.Builder’s method build() should look like this:

    ...

    public Product build() {
        checkNotNull(this.name, "Product name must be set.");
        checkNotNull(this.price, "Product price must be set.");
        ...
    }

Returning immutable collections

If a method returns a collection, it must be immutable. Use those provided by Guava.

API for tests

If you really need to call some non-public method in tests, add a method wrapper with the access modifier you need.
This method must:

  • have @VisibleForTesting annotation (this means that the method is only for tests);
  • have the same name as the method of interest + forTest suffix;
  • not perform any complex actions, just calling the needed method is the best;
  • have a Javadoc stating that this method is provided only for testing, and what method does it wrap.

The example:

    // This is a private method to wrap
    private void apply(Iterable<? extends Message> messages, CommandContext commandContext) {
        ...
    }

    /**
     * This method is provided <em>only</em> for the purpose of testing event appliers
     * of an aggregate and must not be called from the production code.
     *
     * <p>Calls {@link #apply(Iterable, CommandContext)}.
     */
    @VisibleForTesting
    public final void applyForTest(Message message, CommandContext commandContext) {
        // may perform some setup
        init();
        // may wrap the checked exception
        try {
            apply(singletonList(message), commandContext);
        } catch (InvocationTargetException e) {
            throw propagate(e);
        }
    }

Do not use Mockito

Our experience proved that it does more harm than good. Framework tests that still use it would be eventually migrated.

Suppressing unchecked warnings using annotation

Suppress unchecked warnings via standardized @SuppressWarnings annotation only instead of IntelliJ IDEA-specific //noinspection suppression style. We want to keep code compliant with any tool, not just with IntelliJ IDEA.

Always comment on why a specific suppression is valid

Please do. Framework users and developers need to know the reason why a warning was suppressed.

Comment separators for sections of the class

Use such comment separators if you need to split a class into sections:

/*
 * Test command handlers
 ************************/

Such comments are not collapsed in the IDE, so you can collapse all code blocks in the class and still see the comment separators, which is quite convenient.
Typically, the comment separators are useful in big test classes. We recommend to perform some refactoring instead of splitting a big production class into sections.

Formatting String literals

Concatenated strings

When concatenating a long string, start each continuation line with a space character:

String text = "This is an important error message." +
        " Here are some details regarding what happened." +
        " See the documentation for more information.";

It's easier to spot and understand as a continuation. Oftentimes, people miss a space character in concatenated messages. With the starting space, it happens less often.

Clone this wiki locally