Java Coding Conventions

From InfiniteERP Wiki
Jump to: navigation, search
Back button.png   Back to Main Page


Java Coding Conventions

This document describes the coding standards and coding principles used in the development of InfiniteERP.

At InfiniteERP, IntelliJ IDEA is the recommended IDE. For a description on how to set up the development environment, see Development Stack Setup.

Standard Code Conventions

InfiniteERP uses the standard coding conventions as defined by Sun in Code Conventions for the Java Programming Language.

Skimmable Code: Easy to Read, Easy to Change

Skimmable code has one main characteristic (next to being readable and understandable): it is code for which it is possible to read and change parts of the code without needing to fully understand the complete codebase (the rest of the code). Skimmable code is therefore naturally robust and easier to maintain than non-skimmable code.

When creating skimmable code one abstract term is important: lexical encapsulation. Lexical encapsulation concretely means that code is grouped together in clearly defined methods which are not longer than one window/screen.

Other principles which help to create skimmable and therefore maintainable and understandable code:

  • Use clear, readable and intention-revealing names for variables, methods and classes
  • Use intermediate variables to increase readability
  • Make short methods which fit in one window/screen
  • Define variables and methods within the scope and close to where they are used
  • Use horizontal spacing to group statements together
  • Keep methods clear and focused — let a method do one thing: retrieve a value or change a value

These are the main principles which help skimmability; other conventions discussed in this document also facilitate maintainability, correctness, quality and robustness.

Main Coding Principles

In addition to the skimmability enablers and the standard (more formatting-related) Code Conventions, an InfiniteERP programmer should follow these guidelines.

Formatting

Use an IDE with automatic code formatting at save

Although IntelliJ IDEA is recommended, other popular IDEs are available. In any case, the source code should always be automatically formatted (when a file is saved) using the standard Sun Java code conventions.

To enable code formatting when saving and to use the InfiniteERP code formatting standard, make sure to import the preferences provided in the config/ folder of the development project.

InfiniteERP Copyright on InfiniteERP Intellectual Property (must-do)

Each file which is InfiniteERP Intellectual Property should have the following copyright message at the top:

/*

*************************************************************************
* The contents of this file are subject to the InfiniteERP License
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* https://github.com/infinite-erp/core/blob/main/legal/InfiniteERP_license.txt
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing rights
* and limitations under the License.
* All portions are Copyright (C) 2021–2025 InfiniteERP contributors
* All Rights Reserved.
* Contributor(s): the InfiniteERP project contributors
*************************************************************************
*/

The year in the copyright statement is the current year when the file is new and contains two dates if the file is updated in a different year than it was created. For example, a file created in 2020 and changed for the last time in 2025 will have the following years: 2020 - 2025 specified near the © sign.

Vertical Spacing

Use vertical spacing to separate different parts of the code and to make the code less dense to read. Here is an example without vertical spacing:

try {

   configuration = new Configuration();
   mapModel(configuration);
   setInterceptor(configuration);
   configuration.addProperties(getOpenbravoProperties());
   // add a default second level cache
   if (configuration.getProperties().get(
       Environment.CACHE_PROVIDER) == null) {
   configuration.getProperties().setProperty(
   Environment.CACHE_PROVIDER,
   HashtableCacheProvider.class.getName());
   }
   sessionFactory = configuration.buildSessionFactory();
   log.debug("Session Factory initialized");

} catch (final Throwable t) {

   throw new OBException(t);

}

And here is the same example with vertical spacing to make it easier to read:

try {

   configuration = new Configuration();
   mapModel(configuration);
   setInterceptor(configuration);
   configuration.addProperties(getOpenbravoProperties());
   // add a default second level cache
   if (configuration.getProperties().get(
           Environment.CACHE_PROVIDER) == null) {
       configuration.getProperties().setProperty(
           Environment.CACHE_PROVIDER,
           HashtableCacheProvider.class.getName());
   }
   sessionFactory = configuration.buildSessionFactory();
   log.debug("Session Factory initialized");

} catch (final Throwable t) {

   // this is done to get better visibility of the exceptions
   t.printStackTrace(System.err);
   throw new OBException(t);

}

Code Documentation Policy

Well-documented and commented code is great and helps to understand the meaning of the code, thereby improving productivity and preventing future bugs.

The InfiniteERP code documentation policy aims to combine a lightweight code documentation process which adds value to a developer navigating through the InfiniteERP code in his/her IDE. Comments and documentation should be easy to maintain and be up-to-date with the code they describe.

Documentation and comments can be divided in two main parts: Javadoc and inline commenting.

In InfiniteERP, Javadoc comments have two main uses: to be used as the basis to generate Javadoc HTML pages and technical documentation, and to support specific features of current IDEs (e.g., show Javadoc when hovering with the mouse over methods and constants).

Inline commenting is used to clarify the meaning of the code and underlying implementation decisions which may influence future coding decisions.

Note that all comments and documentation must be in English using the US notation (for example: organization instead of organisation).

Class Javadoc (a must-do)

Each class must have a well-formatted Javadoc section at the top. The class doc comment must describe the overall function of the class and its relation to other classes. The class Javadoc must not contain implementation details as they may change quickly with the risk of having outdated comments. The class Javadoc must contain @author annotations with the name/login of the developers who have worked on that class.

While writing Javadoc class comments also provide @link and @see annotations to related classes. This helps to place the class in the context of other classes.

Here is an example of a class doc:

/**

* Models the business object type. The Entity is the main concept in the
* in-memory model. An entity corresponds to a {@link Table} in the database. An
* Entity has properties which are primitive typed, references or lists of child
* entities.
*
* @see Property
* @see ModelProvider
*
* @author <developer name>
*/

Method Javadoc (a must-do)

Every public method in the InfiniteERP code base must have a Javadoc comment.

There is one exception to this rule: getters/setters which do nothing more than get or set a member of the class should not have a Javadoc comment. The main reason is that Javadoc for these methods does not add much value.

The Javadoc of a method must describe the general logic of the method without too many implementation details. The input and output of the method should be described. Some other rules which must be followed:

  • Every parameter must be described using the @param annotation (do not use empty @param annotations)
  • The return value must be described using the @return annotation (also avoid empty return annotations)
  • If the method throws an UncheckedException then this exception must be mentioned in the Javadoc using the @throws annotation
  • It must specifically be documented if a method can return null so that the caller can take that into account

/**

* The main entry point. This method walks through the elements in the root
* and parses them. The children of a business object (in the xml) are also
* parsed. Referenced objects are resolved through the
* {@link EntityResolver}.
* <p/>
* After a call to this method the to-be-inserted objects can be retrieved
* through the {@link #getToInsert()} method and the to-be-updated objects
* through the {@link #getToUpdate()} method.
*
* @param xml
*   the xml string
* @return the list of BaseOBObject present in the root of the xml. This
*   list contains the to-be-updated, to-be-inserted as well as the
*   unchanged business objects
*/

or

/**

* Validates the values of the properties of the entityObject. The
* validation messages are collected into one ValidationException.
*
* @param entityObject
*   the entity instance
* @throws ValidationException
*/

public void validate(Object entityObject) {

   ...

}

Javadoc for Class Members

Members should not have Javadoc, as a class member is always private.

Javadoc for Constants

Public final static constants must have Javadoc. Private constants should not have Javadoc.

Javadoc Formatting

The Javadoc must use standard doc constructs like linking to Javadoc of other classes and use Javadoc formatting.

Inline Commenting

Inline comments can be crucial for a developer to understand the meaning of code and to be informed about earlier implementation decisions. However, when commenting keep the following in mind:

  • The general philosophy is that there is only a minimal need for comments: the code itself should be readable (using descriptive names and variables to store intermediate results)
  • Comments should only be added if they add value and provide deeper insight which is not directly visible in the code itself
  • Inline comments are hard to maintain and are quickly outdated because code changes quickly; therefore comments must be placed as closely as possible to the code they refer to
  • Remove outdated comments!

Naming Conventions

InfiniteERP follows standard Java naming conventions:

  • Classes: UpperCamelCase, nouns
  • Methods: lowerCamelCase, verbs
  • Constants: UPPER_SNAKE_CASE
  • Variables: lowerCamelCase
  • Packages: reverse domain name, lowercase (e.g., org.openbravo.model)

Don't use encoding in names (Hungarian notation or member prefix with preceding underscore). Don't start an interface name with a capital I.

Test Driven Development

It is crucial that for new functionality one or more test cases are created in the InfiniteERP test suite. It makes a lot of sense to support your coding with test cases:

  • A test case proves that the functionality is implemented and works correctly
  • A test case can validate that the functionality still works in the future
  • Test cases provide a much easier (and therefore more productive) entry point for testing functionality than starting InfiniteERP and going through the web interface
  • A test case can be used as a demonstration and a description of how the software should operate

InfiniteERP test cases need to be created in the src-test folder of the InfiniteERP project.

See the InfiniteERP test documentation for more information on how to create test cases.

Quality and Conventions

For information about this point, visit the resources on good programming practices.

Be-aware-of

There are also some standard Java constructs which should be used with care and with some understanding of the underlying processes:

ThreadLocal and Tomcat's re-use of Thread objects

A ThreadLocal is a great mechanism to store singleton instances per thread and make them only available in that thread. However, when using ThreadLocals one needs to understand that Tomcat re-uses thread instances from one request to another (not at the same time). This means that data stored in a ThreadLocal in one thread can re-appear in another request (re-using that same Thread object).

Class.forName and classloading

When you dynamically need to load a class you have different classloading options. Within Tomcat, using Class.forName works. However, it is important that you understand how Java classloading works when using dynamic classloading mechanisms.

Synchronized Blocks

Synchronized blocks are not always a safe way to handle multi-threaded access. See the references on double-checked locking for a detailed description of the underlying processes and possible solutions.

See Also

References


This page is a derivative of Java Coding Conventions by Openbravo Wiki, used under CC BY-SA 2.5 ES. This work is licensed under CC BY-SA 2.5.