The OpenEngSB Coding Guidelines are based upon the Code Conventions for the Java Programming Language. There are some additions and deviations for this project.
A line length of 80 was standard 10 years ago, but with increasing screen size and resolution a length of 120 is more reasonable.
Use the auto-formatter of your IDE. Import the Eclipse Formatter file.
Declare variables where they are needed. It's easier to read and restricts the scope of variables. Don't overshadow variables.
Every Java file has to be UTF-8 encoded and has to use UNIX line endings. Indentations consist of four spaces, tab-stops are not allowed.
Every source file has to start with this header:
/** Licensed to the Austrian Association for Software Tool Integration (AASTI) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The AASTI licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */
Guards are a possibility to reduce the amount of nesting. Heavily nested code is much harder to read. Bad:
public void foo() { if (conditionA) { if (conditionB) { if (conditionC) { // do some work } } else { throw new MyException(); } } }
Good:
public void foo() { if (!conditionA) { return; } if (!conditionB) { throw new MyException(); } if (!conditionC) { return; } // do some work }
Methods longer than 40 lines are candidates for refactoring. A method should only do one thing and has to be easily understandable. The number of arguments should be minimized. A method should only be at a single level of abstraction.
Static members are a sign of a design error because they are like global variables. It's fine if you declare a constant as final abstract of course.
Don't import org.example.package.*, instead import the needed classes.
Use interfaces or the abstract base class instead of concrete implementation classes where possible. Don't write:
ArrayList<String> names = new ArrayList<String>();
Instead use the interface name:
List<String> names = new ArrayList<String>();
This is especially important in method signatures.
Don't declare serialVersionUID just because your IDE tells you. Have a good reason why you need it. This can cause bugs that are hard to detect.
If you have to suppress a warning make sure you give it the smallest possible scope. This means you should never annotate a whole class with @SuppressWarnings. A method may be acceptable but you should try to annotate the problematic statements instead.
Use String.format() instead of long concatenation chains which are hard to read.
Always use
Type[] arrayName;
instead of the C-like
Type arrayName[];
Interfaces are not marked by starting their names with I. This exposes more information than necessary and is not Java-like.
Exception/Log Messages have to be concise. Don't end messages with "...".
Don't overuse FINAL, use it where you have a good reason something has to be final. Although it doesn't hurt to declare everything as final it clutters the code.
Don't use history tables in source files. Use the SCM system if you are interested in the changes of a file.
Don't use the JavaDoc author tag. Also use the SCM system.
Don't declare unnecessary constructors, especially the empty default constructor.
Don't make implicit calls explicitly, i.e. calling super(); in every constructor.
Don't specify modifiers that are implicit, i.e. don't make methods in interfaces public
abstract
.
Don't initialize fields with null, they are automatically initialized with null.
Don't use banners in comments.
Don't use closing brace comments, i.e. } // end if, they are a sign of too long methods.
Don't comment out code and commit it. This confuses programmers why it is there. Simply delete it, it's still present in the SCM history.
Don't log and throw. Either a exception should be logged or thrown to be processed at a more appropriate place.
Don't swallow exceptions silently. If you have to do it, you have to make a comment stating the reason.
Use runtime exceptions where possible.
Wrap exceptions in a RuntimeException if you don't want to specify the Exception in your method signature and you can't handle it.
Write meaningful exception message.
Make use of JUnit 4 features, e.g. @Test(expected = SomeException.class)
Tests should not output anything. They have to be automatically verified.
Don't catch exceptions just to fail manually. Declare the method to throw the exception.
Install a shutdown hook for test data files. This assures that they will be deleted and the project remains in a clean state.
Use Mockito for mocking.
Tests should have descriptive method names. It should be deducible what will be tested. Bad:
testError()
. Good: invalidInMessage_ShouldReturnErrorResponse()
.
The Maven profiles for running the tests are configured to filter based on the naming of the test class. The package layout is just a further convenience for the developer for running the tests manually.
Unit Tests test one class/method/feature in isolation from their dependencies by using test doubles as replacement. They should be fast and need no special environment setup for execution.
Filenames end with Test.java
Located in the normal package structure, i.e.
outer.project.package.inner.project.package
Integration Tests combine individual software modules to test their interaction with each other. They do not need a special environment setup for execution.
Filenames end with IT.java
Located in outer.project.package.it.inner.project.package
User Tests need a special execution environment and thus are not run automatically during any maven phase.
Filenames end with UT.java
Located in outer.project.package.ut.inner.project.package
Every XML file has to be UTF-8 encoded and has to use UNIX line endings. Indentations consist of TWO spaces, tabstops are not allowed. The line length shouldn't exceed 120 characters.
If you use Eclipse please choose these settings for your OpenEngSB workspace:
Eclipse XML Settings
Clean Code, Robert C. Martin, 2008
Effective Java Second Edition, Joshua Bloch, 2008