This document describes a list of coding conventions that are required for code submissions to the project. By default, the coding conventions for most Open Source Projects should follow the existing coding conventions in the code that you are working on. For example, if the bracket is on the same line as the if statement, then you should write all your code to have that convention.
If you commit code that does not follow these conventions and you are caught, you are responsible for also fixing your own code.
Below is a list of coding conventions that are specific to gvSIG, everything else not specificially mentioned here should follow the official Sun Java Coding Conventions
As explained in the Sun Java Coding Conventions:
Code conventions are important to programmers for a number of reasons:
Having coding conventions is nice but having a way to ensure they are applied is even better ... :-)
The gvSIG maven configuration has a checkstyle target which performs coding conventions using the Checkstyle tool.
Please run this target before committing any code.
Also the eclipse configuration needed to format the source code taking into account the code conventions defined in the current document will be available in the org.gvsig.maven.base.build project, from the gvsig-tools OSOR project.
If the project you are working with has a prepare-workspace.xml file which you have used to configure your workspace, you will have those files already downloaded and available into the folder:
WORKSPACE/org.gvsig.maven.base.build/eclipse-configs
Otherwise, you may download all the files through the repository URL:
To import those configurations perform the following:
Headers
Look at the Headers document for more information.
Indentations
4 spaces. NO tabs.
Javadoc
All API interfaces and classes must be fully documented through javadocs comments at interface/class, method and package level.
When you inherit or extend from another interface or class which is already documented, and implement or rewrite one of the parent methods, don't write any javadoc comments, as they are also inherited since java 1.4.
Brackets
All brackets should begin at the end of the line that begins the statement, and end on a new line indented to the beginning of the statement. Example:
AVOID:
public class MyClass
{
public void someMethod()
{
if (...) { // Do something }
}
}
RIGHT:
public class MyClass {
public void someMethod() {
if (...) {
// Do something
}
}
}
Brackets are mandatory even for single line statements:
if (expression) // AVOID!
// some code
if (expression) { // RIGHT
// some code
}
Blank Spaces
Keywords followed by a parenthesis should be separated by a space. Example:
while (true) {
// some code
}
Blank space should appear after commas in argument lists. Binary operators should be separated from their operands by spaces:
a += c + d;
a = (a + b) / (c * d);
while (d++ = s++) {
n++;
}
printSize("size is " + foo + "\n");
Class variables
Class variables should not have any prefix or suffix related to its data type or scope. Example:
String nameString; // AVOID!
String name; // RIGHT
Parameter names
Method parameters should be prefixed by "the" for differentiating them from inner variables, when there is an inner variable with the same name or use. For example:
public void someMethod(String theClassName) {
String className; // inner variable
}
Line length
Avoid lines longer than 80 characters for Code, comments, ...
Versioning
All .java files should have a @version tag like the one below into the class javadoc comment:
@version $Id$
Logging
Do not use System.out to log. Instead, use the SLF4J logging API. For example:
private static final Logger LOG =
LoggerFactory.getLogger(MyClass.class);
public void someMethod() {
LOG.debug("some debug text");
}
For more information on SLF4J usage, you can read the Logging document.
Exception handling
Managing exceptions correctly requires experience. This is not supposed to be a guide on managing exceptions, simply a few best practices.
An example:
public void getTestClass() {
try {
Class responseClass =
Class.forName("some.package.MyClass");
} catch (ClassNotFoundException cnfe) {
String message = "Cannot instantiate test class";
LOG.error(message, ex);
throw new ChainedRuntimeException(message, e);
}
}
Qualified imports
All import statements should containing the full class name of classes to import and should not use the "*" notation: An example:
// AVOID!
import java.util.*;
import java.net.*;
// RIGHT
import java.util.Date;
import java.net.HttpURLConnection;
Use interfaces in the declaration of methods and variables.
By example, if you need a variable x that is a list, declare it as List instead an ArrayList:
// AVOID!
ArrayList x = new ArrayList();
HashMap y = new HashMap();
public HashMap create(ArrayList keys, ArrarList values) {
...
}
// RIGHT
List x = new ArrayList();
Map y = new HashMap();
public Map create(List keys, List values) {
...
}
API packages
Usually, API interfaces and classes will belong to the library's main root package. If you create subpackages, use them to group by functionality, not by type.
How to name packages
All packages must begin with org.gvsig.
For more information on this convention, you can read the How to name packages document.
Attention!
TODO
For more information on this convention, you can read the How to name interfaces and classes document.
This document defines rules for naming classes and interfaces that allow a common style for gvSIG components to be maintained.
The importance of consistency in naming is obvious if one considers a complete Javadoc implementation. From the point of view of the reader, using a variety of naming conventions would create confusion and complicate the understanding of the component.
The use of prefixes and/or suffixes in the names of classes and interfaces is usually a means of providing information about their nature and/or task. For example they can be used to denote a pattern, or a role within a pattern (eg the suffix Factory). At other times, it is necessary to use them if the appropriate name has already been assigned. This is the case of the prefixes and suffixes that are described below.
As a general rule:
Example:
public interface List {} public abstract class AbstractList extends AbstractCollection implements List {}
It is recommended that this prefix not be used.
Typically, the interfaces are the visible part of a component model. They usually represent entities and concepts from the business or domain and therefore it is recommended that the same names be used as in the business.
Example:
public interface ListModel {} public abstract class AbstractListModel implements ListModel, Serializable {} public class DefaultListModel extends AbstractListModel {}
Example:
public abstract class StreamRequestHandler {} public class BaseHTTPRequestHandler extends StreamRequestHandler {}
Example:
public interface Plane {} public abstract class AbstractPlane implements Plane {} // Both are correct (but not equal) public class PlaneImpl implements Plane {} public class PlaneImpl extends AbstractPlane {}
This criterion is applicable to new developments undertaken for gvSIG 2.0 and will be part of the official gvSIG distribution as well as for all developments financed in whole or in part by the CIT.
Due to the variability and lack of unity in the names of packages used in gvSIG 1.X, it has been decided to standardize these, thereby giving the project an identity that over-rides that of the company doing the development.
When creating java packages that will be part of an official gvSIG release, or that will carry the official endorsement of the gvSIG project, the following package is appended:
org.gvsig
No mention is made in the package of the company doing the development.
Normally, the package name org.gvsig is followed by a package name identifying the logical or functional block that it contains.
These criteria will be applied to new developments to be made to gvSIG 2.0, and will be part of the official gvSIG distribution as well as for all developments financed in whole or in part by the CIT.
In gvSIG the SLF4J library is used as a logging API.
The Simple Logging Facade SLF4J is a framework that is designed to abstract the underlying logging system. As Log4j is the most popular logging system in use, the framework's API is very similar to simply removing the direct dependence of this system. This framework is therefore an abstraction layer of the logging system and will allow us to change the underlying components without having to undertake major recoding of the application.
// Those lines produce the same results. The second one has parameters that reduce the overhead when debugging is disabled
LOG.debug("The new entry is "+entry+".");
LOG.debug("The new entry is {}.", entry);
gvSIG 2.0 is ready to work with SLF4J, using LOG4J as implementation, and can be used directly from any gvSIG extension.
To use SLF4J from a Java class just include the following statements:
1.- Import the necessary classes:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
2.- Declare and initialize the Logger:
public class MyClass
{
private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
...
3.- We use the Logger within the code of the class when we want to display a log message, depending on the type: error, warning, information, debug or trace:
LOG.warn(String message);
LOG.warn(String message,Object arg1);
LOG.warn(String message,Object[] arg1);
LOG.warn(String message, Throwable arg1);
LOG.info(String message);
LOG.info(String message,Object arg1);
LOG.info(String message,Object[] arg1);
LOG.info(String message, Throwable arg1);
LOG.error(String message);
LOG.error(String message,Object arg1);
LOG.error(String message,Object[] arg1);
LOG.error(String message, Throwable arg1);
LOG.debug(String message);
LOG.debug(String message,Object arg1);
LOG.debug(String message,Object[] arg1);
LOG.debug(String message, Throwable arg1);
LOG.trace(String message);
LOG.trace(String message,Object arg1);
LOG.trace(String message,Object[] arg1);
LOG.trace(String message, Throwable arg1);
The following methods are provided to check the activation of messages for each level:
LOG.isErrorEnabled();
LOG.isWarnEnabled();
LOG.isInfoEnabled();
LOG.isDebugEnabled();
LOG.isTraceEnabled();
In addition, the messages can also be customized in SLF4J by inserting variables into the String of the log message, as in the following example:
private Integer temperature;
public void setTemperature(Integer temperature) {
LOG.debug("Setting temperature to {}. Old temperature was {}.", temperature, this.temperature);
this.temperature = temperature;
if(temperature.intValue() > 50) {
LOG.info("Temperature has risen above 50 degrees.");
}
}
This stops us from having to concatenate Strings, which reduces the cost of using the instructions for logging. This is because, although the log level that we are using is disabled (for example, debug), the method call will be made anyway, including the concatenation of strings to build the message, if any.
However, if the obtaining of any of the parameters to be passed to the message log proves costly, it is convenient to use the consultation methods to avoid such implementation. For example:
private Integer temperature;
public void setTemperature(Integer temperature) {
LOG.debug("Setting temperature to {}. Old temperature was {}.", temperature, this.temperature);
this.temperature = temperature;
addToTemperatureLog(temperature);
if (LOG.isDebugEnabled()) {
LOG.debug("The current average temperature is {} Celsius", calculateAverageTemperature());
}
}