Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Papyrus/Neon Work Description/Discussions/Development rules
Contents
Development Rules For Papyrus (DRAFT)
Context
As the number of contributors on Papyrus increased a lot this passed year, the code becomes heterogeneous with everyone touch. In order to make the Papyrus code more homogenous, it seems to be a good point to put some best practices down in writing. This page is a starting point to discuss about those rules and practices.
Most of those rules are already followed by most of the contributors, and could seem obvious. Others are not yet followed, but should be a good habit to avoid mistake when coding. Sometimes there are different ways to have the same result, then a rule can be added in this base to define the "Papyrus" code style.
To make those rules fullfilled by most of the contributors, they should be either automatable or trackable (i.e.: with a Formatter or with Checkstyle).
Rules organisation
To ease the rules understanding, a classification has been made to organise them. Thus, each rule has an identifier, prefixed by its category.
The different categories are:
- NAME: Rules related to the naming of the elements
- FORM: Rules defining the format of the code and its presentation
- TIPS: Tips and tricks, best practices, etc.
- COMM: Rules dedicated to the comment content and format
- ARCH: Architecture rules, defining how the product components, features and plugins, must be build and configured
Rules application
There is no perfect rules referential. These rules can only have an added value if there are shared and applied. The main objective is to build a code base which can live, be maintained and understood by any contributor, and not only its author.
In some specific cases, it can append that a rule can't be respected, but this must be explained and well-argued in the code comments.
Finally, as the rules live with the project, some existing code may not respect new rules. It's the responsibility of any contributor to correct a file when he has to work on it, and this must be a part of the review process.
Rules repository
Naming category
General
- NAME-01
The names of classes, methods, variables, must not be too long (50 characters max.).
- NAME-02
The code is in English. The attributes, methods, classes, etc. names must be in English.
- NAME-03
The accented characters or any characters specific to a country or an alphabet are forbidden.
Files
- NAME-04
A source file is strictly named as the public Class that it contains, including the case.
- NAME-05
A source file has the .java extension, and the compiled files have the .class extension.
Packages
- NAME-06
A package name contains only lower case letters, separated by dots.
It's recommended to use short words, concatenations and abbreviations instead of group of words to limit the size of the package names. The common acronym could also be used.
- NAME-07
The package names must begin by org.eclipse.papyrus.
- NAME-08
The package name must strictly correspond to the system folders tree, from the source folder root.
Classes
- NAME-09
A Class or Interface name contains only letters, begins by an upper case letter, and respect the CamelCase syntax.
The name must be a word or a group of words which describes the Class role and services. Moreover, using non alphabetic or numerical characters is forbidden. For example, to rename a Class which extends a parent Class by adding only a numerical suffix doesn't allow to understand its behaviour differences. This doesn't ease the code readability and maintainability.
- NAME-10
The acronyms are forbidden, except for the following list of common elements: ASCII, HTML, SQL, URL.
- NAME-11
Some Classes or Interfaces must be prefixed or suffixed to highlight their type or a design pattern used. For example:
IElement | For an Interface |
AbstractElement | For an abstract Class |
ElementNotFoundException | For an Exception |
ElementSingleton | For the singleton design pattern |
ElementFactory | For the factory design pattern |
Methods
- NAME-12
A method name contains only letters, begins by a lower case letter, and respect the CamelCase syntax.
The name must be a word or a group of words which describes the method role and behaviour. Moreover, using non alphabetic or numerical characters is forbidden.
- NAME-13
A method will perform something, the first word is thus generally a verb.
- NAME-14
The accessors methods of a property have a normalised prefix:
get | Getter of a property |
set | Setter of a property |
is | Getter of a boolean property |
add | To add an element to a collection property |
remove | To remove an element from a collection property |
- NAME-15
The accessors of collection property must have a name ending by a plural. The indexed accessors have a name ending by a singular. For example:
public Collection getElements() {...}
public IElement getElement(int i) {...}
- NAME-16
Some method names are normalised according to the kind of action that they perform:
Action | Prefix | Example |
---|---|---|
Conversion | to | toString() |
Creation | create | createElement() |
Variables
- NAME-17
A variable name begins by a lower case letter.
- NAME-18
A variable name is composed of letters, potentially including numbers.
- NAME-19
The dollar character ($) is forbidden in the variable name.
- NAME-20
The underscore character (_) is forbidden in the variable name, except for the static final constants.
- NAME-21
The variable name of a single character must be avoided. They are only tolerated for the temporary variable, like the loop counters (i, j, k ...).
- NAME-22
The boolean properties are named with an adjective describing them. The general terms must be avoided, like ok
, etc. Moreover, a boolean property doesn't need to be prefixed by is
: name a variable available
instead of isAvailable
.
- NAME-23
The collection variables are named with a plural, and potentially postfixed with their collection general type (Array, List, Map).
- NAME-24
It's forbidden to use the same name for a method and a variable inside a same Class.
- NAME-25
The names of the constants (static final) are composed of one word or a group of words with an underscore (_) to separate them. The name is written using only upper case letters.
Presentation category
Order
- PRES-01
The declarations in a Java file follow a specific order:
Javadoc of the file Package declaration Imports list Javadoc of the Class Class declaration Constants declaration (static final) Class variables declaration (static) Instance variables declaration Constructor Methods Inner Classes
- PRES-02
Imports are grouped from the second level of their name, and alphabetically ordered.
- PRES-03
Constants and variables declarations are ordered by decreasing visibility (public, package, protected, private).
- PRES-04
Constants and variables declarations of a same visibility follow a logical order, mainly by functionality and role.
- PRES-05
Methods are logically grouped, mainly by functionality and role.
- PRES-06
Without alter the behaviour, order the code instructions to ease the reading and the understanding.
- PRES-07
When several modifiers are used in a declaration, they respect a specific order:
public protected private abstract static final transient volatile synchronized native strictfp
Length
- PRES-08
A file must not contain more than 2000 lines.
- PRES-09
A method or a constructor must not contain more than 50 lines.
- PRES-10
A line must not be longer than 120 characters.
Style
- PRES-11
The indentation is done only with spaces, and an indentation unity corresponds to 4 spaces.
- PRES-12
The code is formatted as the Java standard:
- Opening braces '{' are located at the end of the code line and preceded by a space
- Closing braces '}' are located on a new line with the same indentation level than line containing the corresponding opening brace. It can be followed only by a new line, or a space with an else, a catch or a finally.
- PRES-13
The cases of a switch instruction are located at the same indentation level than the switch. However, their code block is indented with one more level.
- PRES-14
All the control blocks (if, for, while, do, switch,...) must be surrounded by braces, even if it's an empty or a single line block.
- PRES-15
Any useless or unnecessary braces are forbidden.
- PRES-16
The declarations extends, implements and throws must be located on a separated line, indented as the body of the related Class or method.
- PRES-17
If a method contain a lot of parameters, which doesn't fit on a single line, put only one parameter per line. Each line is indented as the body of the method.
- PRES-18
When an instruction doesn't fit on a single line, it is advised to insert a line break after a comma, or after an operator.
Empty line, space and bracket
- PRES-19
The use of empty lines must respect some recommendations:
- A single empty line must be inserted:
- Between a method declaration and its first instruction
- Before a new block
- Between logical section in the body of a method
- Before a line of code comment
- After a block of code linked to a comment, to understand easily the range of the comment
- Between two methods
- A single empty line must be inserted:
- Two empty lines must be inserted:
- Between the different sections of a source file (declaration section, properties section, methods section, etc.)
- Two empty lines must be inserted:
- PRES-20
A space must be inserted before and after any binary operator (except the '.').
- PRES-21
A space must be inserted before an opening brace.
- PRES-22
A space must be inserted between any key word (if, while, for, etc.) and the bracket which follows it.
- PRES-23
A space must be inserted after the commas, in a list of parameters.
- PRES-24
A space must be inserted after each semi-colon in a for loop declaration.
- PRES-25
A space must be inserted after a cast instruction.
- PRES-26
A space must be 'NOT' be inserted between two opening brackets, or two closing brackets.
- PRES-27
A space must be 'NOT' be inserted between the operators '++' or '--' and the affected variable.
- PRES-28
A space must be 'NOT' be inserted a method name and the opening bracket introducing its parameters.
- PRES-29
Use brackets each time an expression can be confused, or to highlight the treatment order of the operators.
For example:
// Avoid if (vNum1==vNum2 && vNum3==vNum4) { vTotal = vNum1 / vNum2 + vNum3 * vNum4; } // Prefer if ((vNum1==vNum2) && (vNum3==vNum4)) { vTotal = (vNum1 / vNum2) + (vNum3 * vNum4); }
- PRES-30
A return instruction must NOT use brackets, except if it's a conditional expression.
Variable declaration
- PRES-31
Declare only one variable per line.
- PRES-32
Group the variable declaration at the beginning of a block of code, without altering the behaviour.
Tips and best practices
Useless code
- TIPS-01
Delete unused imports.
- TIPS-02
Delete any private property, local variable, parameter and private method not used.
- TIPS-03
Do not use generic import (with '*').
- TIPS-04
It's forbidden to import the packages sun.*
- TIPS-05
A Java source file must contain one and only one public Class or Interface.
- TIPS-06
All the Classes must be contained by a package. This means that it must always have a package declaration at the beginning of the source file.
- TIPS-07
The use of inner Classes, Interfaces, and anonymous Classes must be limited to simple treatments.
- TIPS-08
A Class with only private constructors must be declared as final
.
- TIPS-09
A Class with only static methods must not declare any public constructor.
- TIPS-10
A default constructor must always be explicitly declared if it is needed.
- TIPS-11
It's mandatory to call explicitly the inherited constructor when a constructor is overridden by a child Class, using the super
key word.
- TIPS-12
It's recommended to put only the instance property initialisation in a constructor, and put the treatments in dedicated methods called after the instance creation.
- TIPS-13
An Interface is used to define a type, not to gather and share constants.
Methods
- TIPS-14
The parameter declaration must not use concrete types. In case of exception, it must be argued and explained in the method comment.
- TIPS-15
By default the visibility of a method should be protected
.
The visibility private
should be only used if the method must not be overriden, or accessed by setter and getter.
For a method, the more common visibilities are public
and protected
. The protected
visibility must be preferred by default to the others. It is important to limit public
visibility to reduce the dependency points with others Classes, and improve the code flexibility.
- TIPS-16
The methods and constructors must not have more than 5 parameters.
- TIPS-17
The cyclomatic complexity of a method or constructor must not exceed 15, otherwise the method must be split. This metric indicates the number of conditional path (if, else, case, etc.) of a method and thus the theoretical number of unit tests needed to fully validate it. It's a good indication of the code maintainability.
- TIPS-18
In a base Class, do not use abstract method. The undefined methods must be used in Interfaces or abstract Classes only.
- TIPS-19
A Class must not contain a private method with the same signature (name and arguments) than a private method of its parent Class.
- TIPS-20
If a Class redefines the clone
method, it must always call the parent method with super.clone()
.
- TIPS-21
If a Class redefines the finalise
method, it must always call the parent method with super.finalize()
as its last instruction.
- TIPS-22
If a Class redefines the equals
method, it must always do it with the same signature than the equals
method of the Object
Class.
- TIPS-23
If a Class redefines the equals
method, it must also redefine the hashCode
method (and vice versa).
Variables
- TIPS-24
Always use the most restrictive visibility to a property. The properties are generally private and may be read and written by accessors (get
and set
). The constants (final static
) are an exception, as they can be declared public and accessed directly.
- TIPS-25
All property and variable must be explicitly initialised at its declaration, even with the default value.
- TIPS-26
All the method parameters must be declared as final
and thus not modified in the method context. Any exception must be argued and explained in the method comment.
- TIPS-27
An array declaration must be located on the variable type, and not on its name.
- TIPS-28
A collection property must never be initialised as null
.
- TIPS-29
The getter accessors of a collection property must only return a copy of the collection, or an immutable collection, to preserve the encapsulation principle.
- TIPS-30
When a method is overridden, the implicit contract of the super method must be preserved by its redefinition.
For example, the implicit contract of equals
specifies that it is reflexive, symmetric, transitive, and consistent. When equals
is called on an instance, the developer can't simply know if it has been overridden or not, and he expects that the implicit contract is respected.
Expressions
- TIPS-31
Each line must contain a single instruction. Empty instructions and nested instructions are forbidden.
- TIPS-32
The access to a static property or method must be done using the name of the Class which define it, never from an instance.
- TIPS-33
A method must contain at most one return instruction.
- TIPS-34
The cast and conversions must be done explicitly.
- TIPS-35
When possible, use the arithmetic operators with affection (+=, -=, etc.).
- TIPS-36
A for loop parameter must not be re-affected or modified inside the loop body.
- TIPS-37
Do not use an affectation instruction inside a test or a control structure.
- TIPS-38
In the comparison, the constants must be located on the left of the comparison operand.
- TIPS-39
The ternary conditional operator (condition ? if true : if false
) is only tolerated for simple case.
- TIPS-40
Never use the '==' operator to compare two Strings, but call the equals
method.
Control structures
- TIPS-41
A switch instruction must always contain a default
case.
- TIPS-42
A switch case must always finish by a break
, except to group cases with exactly the same behaviour. The default
case must also finish by a break
even if it's redundant.
- TIPS-43
In a switch, try to put the more frequent case first.
- TIPS-44
The number of nested control blocks depth must not exceed 2.
//TO AVOID: if (vCondition1) { ... // Depth 1 if (vCondition2) { ... // Depth : 2 switch (vExpression1) { case value1 : ... // Depth : 2 if (vCondition3) { ... // Depth : 3 } default : ... break; } } }
- TIPS-45
Do not use a while
loop where a do while
is appropriate.
- TIPS-46
The for
loop must be used for any loop corresponding to the progress of at least one variable according to a regular rule. Otherwise, the while
loop is preferred.
- TIPS-47
The continue
and break
instruction are forbidden in the iterative structure (do, while, for
).
- TIPS-48
The labels (goto
) are strictly forbidden.
- TIPS-49
When testing an enumeration, always consider the default
case of a switch
, or the else
of an if
to anticipate the creation of new values.
- TIPS-50
In the declaration of a classic for
loop, the indirect calls, like collection.getSize()
, must be avoided.
- TIPS-51
Whenever it's possible, use a foreach
loop instead of a classic for
loop.
Exceptions
- TIPS-52
When possible, instead of using a return code, use custom exceptions.
- TIPS-53
Do not use exception to quickly go from a code block to another, it's not a goto
instruction.
- TIPS-54
Create custom exceptions, which inherit from the standard exceptions java.lang.Exception
and java.lang.RuntimeException
. The standard exceptions are too general to be used directly, as they can't be easily distinguished.
- TIPS-55
Remember to reuse the simple exceptions defined in the JDK.
- TIPS-56
Functional exceptions must inherit from java.lang.Exception
. Technical exceptions must inherit from java.lang.RuntimeException
.
- TIPS-57
If at a given level we don't know how to treat an exception, the best is to not catch it.
- TIPS-58
When an exception is caught in a catch block, it must not be re-thrown, but encapsulated.
- TIPS-59
When an exception is caught in a catch block, it must not be "digested" (with an empty catch block for example).
- TIPS-60
Always catch the most precise exception: do not catch java.lang.Exception
, java.lang.RuntimeException
or java.lang.Throwable
.
- TIPS-61
Order the exception catch instruction from the most precise to the most general.
- TIPS-62
In a throws clause, an exception must not be declared twice.
- TIPS-63
In a throws clause, an exception which inherits from another one already declared must not be declared.
- TIPS-64
In a throws clause, an exception which can't append must not be declared.
- TIPS-65
An exception must be immutable, it means that all its properties must be declared as final
.
- TIPS-66
The resources release must be done in a finally
block.
Performance
- TIPS-67
Put outside of a loop any invariant or call of a method which is independent of the loop iteration.
- TIPS-68
Foster the use of static, when possible.
- TIPS-68
Foster the use of inlining, when relevant, by keeping the methods simple and short, declaring them final
to ensure that they can't be overridden, and static
.
- TIPS-69
Use the synchronized
keyword only when relevant.
- TIPS-70
To concatenate and manipulate Strings
, use a StringBuilder
instance.
- TIPS-71
Limit the use of MessageFormat
to the access to a properties file, for internationalisation purpose.
- TIPS-72
Limit the indexed access to an array content. If an array content is accessed several times, access it only once and store the value in a local variable if possible.
- TIPS-73
Recursive algorithms must be avoid and replaced by iterative algorithms when it's possible.
General best practices
- TIPS-74
Avoid the use of the "Double-checked locking" mechanism. For instance, this is the recommended way to design a singleton to avoid it:
public final class MySingleton { private static MySingleton sInstance = new MySingleton(); public MySingleton getInstance() { return sInstance; } private MySingleton(){ } }
- TIPS-75
To make comparison use the min and max values defined in the Classes of the package java.lang
, which encapsulate the primitive numeric types.
- TIPS-76
Do not use float
and double
for arithmetic calculation. These primitive types respect the IEEE 754 specification, which normalises the representation of numbers with floating comma. It's made to increase the calculation performance, but doesn't guarantee the result precision.
- TIPS-77
Use the BigDecimal and BigInteger constructor, taking a String as parameter.
- TIPS-78
The use of java.util.Vector
, java.util.Hashtable
and java.util.Enumeration
are forbidden. If a thread-safe instance is needed, use java.util.List
, java.util.HashMap
and java.util.Iterator
, with the methods Collections.synchronizedList()
and Collections.synchronizedMap()
.
- TIPS-79
To work on collections and arrays, use the utilitarian methods available in java.util.Collections
and java.util.Arrays
.
- TIPS-80
To copy an array, use the method System.arraycopy()
.
- TIPS-81
Avoid the use of System.out.println()
and system.exit()
.
- TIPS-82
To initialise complex static properties, use a static
block.
- TIPS-83
In a method signature, and in a variable declaration, it's recommended to use Interfaces and not concrete types.
- TIPS-84
Encapsulate and centralise the management of the date, do not get the system date directly. This can be very useful during a test or validation phase.
- TIPS-85
Do not create a new instance of the Class java.lang.Boolean
, use the existing instances Boolean.TRUE
and Boolean.FALSE
.
- TIPS-86
Do not use literals, as magic numbers or hard coded String, but use named constants. The only tolerated values are -1, 0 and 1, which can appear in control structures.
Comments category
- COMM-01
The use of Javadoc comment is mandatory for the whole project scope, for all the visibility levels (not only the public elements) and for all the declarations types (Class, Interface, method, property, etc.).
- COMM-02
If a Javadoc comment contain more than one line, the first one must contain only the opening tag /**
. The following lines must begin by a star (*) and a space, and all the stars characters must be aligned. The last line must contain only the closing tag */
, preceded by a space to align the stars.
- COMM-03
The opening comment tags /**
and //
are always followed by a space.
- COMM-04
The code comment must always be located at the current code indentation level.
- COMM-05
A file Javadoc, located before the package declaration, is normalised and must respect the Eclipse standards:
/******************************************************************************* * Copyright (c) ${date} ${company}. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ${contributor} (${company}) - initial API and implementation ******************************************************************************/
- COMM-06
A Class Javadoc is normalised and must respect the following template:
/** * First sentence describing the Class role and services. * * Detailed description of the Class behaviour. * * @author $Author$ * @version $Revision$ */
- COMM-07
A method Javadoc is normalised and must respect the following template:
/** * First sentence describing the method role. * * Detailed description of the method behaviour and implicit contract. * * @param pParameterName Parameter description * @return Return value description * @throws ExceptionType Description of the potential cause of exception */
- COMM-08
A Javadoc comment always ends its description by a dot '.'. This is used during the documentation generation to structure the paragraph.
- COMM-09
The description associated to a Javadoc tag (@param
, @return
, etc.) must not end by a dot '.'.
- COMM-10
An empty line must be inserted in a Javadoc comment between the description paragraphs and the Javadoc tags.
- COMM-11
The Javadoc tags must be used only when it's relevant.
- COMM-12
A code is considered as enough documented when the comments correspond to 40% of the number of lines.
- COMM-13
A code block must not be committed as comment, except in an explanation purpose.
- COMM-14
A comment is mandatory in English, and must not contain any accented or special character, as a page break.
Architecture category
- ARCH-01
The project corresponds to a product, thus the releases are delivered to the final user as a whole product, with independent P2 repositories for the optional features.
- ARCH-02
All plug-ins must compile and run with Java 1.7 (Execution Environment = JavaSE-1.7).
- ARCH-03
The build architecture is driven by Maven, thus the Java build folder is target/classes
(and not bin/
).
- ARCH-04
A plugin or feature provider must be Eclipse Modeling Project
- ARCH-05
A plugin or feature version must match the whole product version at each release. The component versions must be qualified, like 0.7.0-qualifier
in the manifest, and 0.7.0-SNAPSHOT
in the POM.
- ARCH-06
A feature name must be: org.eclipse.papyrus.myfeature
.
- ARCH-07
A plugin id must be: org.eclipse.papyrus.parentfeature.myplugin
.
- ARCH-08
A plugin content must respect the following structure:
org.eclipse.papyrus.feature.plugin |- src |- icons |- META-INF |- properties | |- nls |- build.properties |- plugin.xml |- pom.xml
- ARCH-09
The plugins dependencies must be as simple and clear as possible. To build a dependencies graph closed to a tree, this principles must be respected:
- - If a plugin requires another plugin of the project, it must mandatory reexport it with
visibility:=reexport
. - - If a plugin requires an external plugin of the project, it must mandatory reexport it with
visibility:=reexport
. - - If a plugin requires another plugin of the project, it must reference the last release version, as minimal version.
- - All dependencies must be explicitly declared, even if it's required only at runtime, with a required plugin (not an imported package) link.
- ARCH-10
In a feature, the configuration Strings, from feature.xml
, must be externalised in properties file named feature.properties
, and located at the plugin root.
- ARCH-11
In a plugin, the configuration Strings, from MANIFEST.MF
and plugin.properties
, must be externalised in properties file named plugin.properties
, and located in the folder properties
at the plugin root.
- ARCH-12
The code Strings must be externalised in properties file named messages.properties
, located in the folder properties/nls
at the plugin root. If the externalisation is not relevant for a String, for example for debug Strings, it must be tagged using //NON-NLS-$
.
- ARCH-13
Each Eclipse plugin have an Activator explicitly declared, who manage the plugin lifecycle. The activator implementation is encapsulated in an EMFPlugin Class, and is a Singleton. Its concrete type depends of the plugin role, EclipseUIPlugin
or EclipsePlugin
, according to the fact that the plugin contribute to the UI or not.
- ARCH-14
In a plugin context, the build.properties
file describes the files that must be included at runtime. It must include these contents (when it exists):
In 'Binary build' category: META-INF/ about.html icons/, resources/, models/, etc. (All folders containing runtime resources) properties/ plugin.xml schema/ In 'Source build' category: about.html
Pay attention to NOT include the following files:
.classpath .project src/ target/ build.properties
- ARCH-15
In a feature context, the build.properties
file describes the files that must be included at runtime. It must include these contents (when it exists):
In 'Binary build' category: epl-v10.html feature.properties feature.xml licence.html In 'Source build' category: build.properties epl-v10.html licence.html