Use custom code style

Context and Problem Statement

Code should be formatted consistently. Which code style and auto formatter to be used?

Decision Drivers

  • Consistency to the Java world (to lower the cognitive load)
  • Maintained tooling to reduce risk of non-working tooling in the future

Considered Options

  • Use custom code style
  • Use prettier-java
  • Use palantir-java-format
  • Use google-java-format
  • Use spring-javaformat
  • Use eclipse formatter

Decision Outcome

Chosen option: “Use custom code style”, because comes out best (see below).

Consequences

  • Good, because the style closely follows the maintainer’s expectations on code formatting
  • Good, because the IntelliJ tooling works reasonably well
  • Bad, because users need to setup IntelliJ to use the code style

Pros and Cons of the Options

Use custom code style

IntelliJ offers to customize the code style and export it into an XML file.

  • Good, because the style closely follows the maintainer’s expectations on code formatting
  • Good, because the IntelliJ tooling works reasonably well
  • Bad, because users need to setup IntelliJ to use the code style
  • Bad, because depends on IntelliJ’s capabilities (and is not tool-independent)
  • Bad, because the statement after -> is always on the next line.

Use prettier-java

prettier-java is a prettier plugin for Java.

It uses around 80 characters as soft width limit:

For readability we recommend against using more than 80 characters:

In code styleguides, maximum line length rules are often set to 100 or 120. However, when humans write code, they don’t strive to reach the maximum number of columns on every line. Developers often use whitespace to break up long lines for readability. In practice, the average line length often ends up well below the maximum.

Prettier’s printWidth option does not work the same way. It is not the hard upper allowed line length limit. It is a way to say to Prettier roughly how long you’d like lines to be. Prettier will make both shorter and longer lines, but generally strive to meet the specified printWidth.

We tried out at https://github.com/JabRef/jabref-koppor/pull/717.

Example:

        action
            .getKeyBinding()
            .ifPresent(keyBinding ->
                keyBindingRepository
                    .getKeyCombination(keyBinding)
                    .ifPresent(combination -> setAccelerator(combination))
            );
  • Good, because prettier-java is updated regularly.
  • Good, because the subject is “always” in the first thing in the line.
  • Good, because it also formats the imports
  • Neutral, because optimized for code review (because of the 80 characters width): Favors short lines (80 characters); the reading is more top-to-buttom; screens are typically wider.
  • Bad, because prettier-action cannot be used
  • Bad, because has line breaks at single variables

Use palantir-java-format

Example:

        action.getKeyBinding().ifPresent(keyBinding -> keyBindingRepository
                .getKeyCombination(keyBinding)
                .ifPresent(combination -> setAccelerator(combination)));

Use google-java-format

Use spring-javaformat

spring-javaformat is a code style of Spring. The plugin is automatically activated in IntelliJ. For the code style, see https://github.com/spring-projects/spring-framework/wiki/Code-Style.

We tried out at https://github.com/JabRef/jabref-koppor/pull/716.

  • Neutral, because each class field is separated by an empty line:\

    empty lines between class fields

  • Bad, because merges lines together where it should not:

    style merges lines

  • Bad, because import statements are not handled.
  • Bad, because we need to accept that else starts on the “first” column. (“Kernighan and Ritchie style”) -> https://github.com/spring-projects/spring-framework/wiki/Code-Style#block-like-constructs-kr-style
  • Bad, because it provides bad wrapping:

          /**
      -     * Add X11 clipboard support to a text input control. It is necessary to call this method in every input where you
      -     * want to use it: {@code ClipBoardManager.addX11Support(TextInputControl input);}.
      -     *
      -     * @param input the TextInputControl (e.g., TextField, TextArea, and children) where adding this functionality.
      -     * @see <a href="https://www.uninformativ.de/blog/postings/2017-04-02/0/POSTING-en.html">Short summary for X11
      -     * clipboards</a>
      -     * @see <a href="https://unix.stackexchange.com/questions/139191/whats-the-difference-between-primary-selection-and-clipboard-buffer/139193#139193">Longer
      +     * Add X11 clipboard support to a text input control. It is necessary to call this
      +     * method in every input where you want to use it:
      +     * {@code ClipBoardManager.addX11Support(TextInputControl input);}.
      +     * @param input the TextInputControl (e.g., TextField, TextArea, and children) where
      +     * adding this functionality.
      +     * @see <a href=
      +     * "https://www.uninformativ.de/blog/postings/2017-04-02/0/POSTING-en.html">Short
      +     * summary for X11 clipboards</a>
      +     * @see <a href=
      +     * "https://unix.stackexchange.com/questions/139191/whats-the-difference-between-primary-selection-and-clipboard-buffer/139193#139193">Longer
          * text over
    
      -    public ArgumentProcessor(String[] args,
      -                             Mode startupMode,
      -                             PreferencesService preferencesService,
      -                             FileUpdateMonitor fileUpdateMonitor,
      -                             BibEntryTypesManager entryTypesManager) throws org.apache.commons.cli.ParseException {
      +    public ArgumentProcessor(String[] args, Mode startupMode, PreferencesService preferencesService,
      +            FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager)
      +            throws org.apache.commons.cli.ParseException {
    

Use eclipse formatter