Java Coding Guidelines
Table of Contents
- Java Coding Guidelines
- Code Style and Format
- Naming
- Use of Acronyms
- Member Variables
- Use of final
- Scoping
- Imports
- Indentation
- Line Length
- Brackets
- Variables
- Instance Variables
- Statements
- Modifier ordering
- Comments and JavaDoc
- Hash Codes
- Getting Class Names
- String Concatenation
- Logging
- Exceptions
- Changing Class and Package Names
- Developing Activities
- Tests
- Keep it Clean
- Eclipse Setting
- Code Style and Format
Code Style and Format
Naming
| Item | Name |
| Package | Use root stem uk.org.ogsadai. Do not use underscores and uppercase characters. |
| Class | CapitalizedFirstLetter |
| Method | smallFirstLetterWithSubsequentCapitalization |
| Constant | (static final) FULLY_CAPITALIZED_WITH_UNDERSCORES |
| Member | mFirstLetterWithSubsequentCapitalization |
| Parameter | smallFirstLetterWithSubsequentCapitalization |
| Local Variable | smallFirstLetterWithSubsequentCapitalization |
| Local Final Variable | smallFirstLetterWithSubsequentCapitalization |
| Static Variable | smallFirstLetterWithSubsequentCapitalization |
| Type | smallFirstLetterWithSubsequentCapitalization |
- Only constants may have underscores _ in their names.
Use of Acronyms
- Acronyms in class and method names and variables should be in upper case, e.g. mURL, parseWSDL(), SOAPHandler. This is Sun's convention, e.g. ComboBoxUI.
- For local variables, all lower-case can be used if appropriate, e.g. variables called url and wsdl are acceptable but myurl and somewsdl are not.
Member Variables
- All non-final member variables must be either protected or private, in which case access or change should be supported, if required, by standard getX and setX methods.
- The use of the final keyword is encouraged where applicable.
Use of final
- All method arguments must be marked as final.
- Use of final elsewhere is at a developer's discretion.
Scoping
- Default (package level) scoping in code should be avoided, as this can make readability harder.
- All methods and variables should be specified as private, protected or public.
- If default scoping is required (for example, to restrict method access to other classes within the same package only), it should be clearly commented so.
Imports
- All imports must be single class and explicit.
- Do not use multiple importation (e.g. import .*).
- Do not use duplicate or unused imports.
- Do not explicitly import java.lang classes.
Indentation
- All indentation levels should be exactly 4 spaces.
- Do not use TAB characters - use 4 space strings.
- Source files should look correctly indented when viewed in a simple text editor.
Line Length
- Line length should not exceed 80 columns.
- Continuation lines should be indented to the column just beyond the previous open parenthesis, e.g.
myResult = myObjectName.myQuiteLongMethodName(param1, param2); - If no open parenthesis exists, or there is not enough room left after the open parenthesis to do the above then you may instead indent 4 characters from the beginning of the previous line, e.g.
myResult = myLongObjectName.myQuiteLongMethodName( myLongParmeterName);
Brackets
- Curly brackets { } are put on separate lines, e.g.
for (index = 0; index < length; index++) { } - Do not use empty blocks unless they are commented, e.g.
} catch (Exception e) { // Must put a comment here } - Do not use nested blocks, e.g.
} catch (Exception e) { { } }
Variables
- Do not use abbreviations, e.g. a = b + mVarLen should be avoided and totalLength = partLength + mLength used instead.
- Each variable declaration should appear on its own line.
- Loop variables should be defined inside loop constructs. This allows the JVM to perform optimisations and de-allocate the variables more quickly. It is also more readable, e.g.
for (int i = 0; i < n; i++) { Object someObject = getObject(i); }is preferable toObject someObject = null; for (int i = 0; i < n; i++) { someObject = getObject(i); }
Instance Variables
- Do not usethis. as a prefix when referencing instance variables.
- Use a form that does not require the use of this, for example, mMyVariable = myVariable;.
Statements
- All single line statements should use brackets, e.g.
if (isEmpty) { return; } - Do not use empty statements (e.g. lone semicolons).
- Do not use assignments in sub-expressions (e.g. String s = Integer.toString(i = 2);).
- switch statements should have a default clause, which should come last in the statement.
- Every case containing code should contain a break, return, throw or continue statement.
- Boolean expressions should be as simple as possible, e.g. the following are discouraged:
if (b == true)
orif (b) { return false; } else { return true; }This is equivalent to the, much nicer, return (! b);. - Do not reassign method parameters within the method.
- Method parameters should be declared final for efficiency.
- No unnecessary parentheses (e.g. if((a.equals(b)))).
- Declare arrays as String[] args, not String args[].
Modifier ordering
The order of modifiers should conform to the the Java Language Specification. The correct order is:
- public
- protected
- private
- abstract
- static
- final
- transient
- volatile
- synchronized
- native
- strictfp
Comments and JavaDoc
- All comments must be done in JavaDoc and follow the JavaDoc guidelines http://java.sun.com/j2se/javadoc/writingdoccomments.
- All class comments must have a JavaDoc tag of form:
@author ...FILL IN THE AUTHOR...
- All packages must contain a JavaDoc-compliant package.html file.
- All methods, classes and attributes must be commented.
- No JavaDoc warnings or errors should be thrown by the JavaDoc compiler.
- Methods that implement an interface method can just be commented with
/** * {@inheritDoc} */if there is nothing in the implementation method that a user of the API needs to know. - Classes committed to SVN should not include commented-out code or TODOs without good reason.
- Methods building/parsing XML should state the XML Schema or give an example of the format.
- Class, method, attribute and argument names should be marked up using <code>...</code> (and not <tt>...</tt>).
- Methods that accept java.util.Map, List, Set, etc should specify what types they expect the keys and values in these objects to be, e.g.
* ... List<Activity> * ... Map<String, Request>
- Methods or classes that parse, manipulate or construct XML documents should document the expected/produced XML or contain a reference to the associated XML Schema.
- Methods or classes that perform mappings from one type of "thing" to another (e.g. from one database data-type to another) should explicitly list each of the mappings.
- If code is incomplete or requires extension then comment these with the prefix TODO, e.g.:
// TODO - extend this method.
- JavaDoc for thread-safe classes should state that they are as such.
- JavaDoc for interfaces that expect their implementations to be thread-safe should state this requirement.
- Classes or methods that expect system properties to be set should state the name of the property they use.
Hash Codes
- Whenever writing a equals() method for a class then a hashCode() method must also be written.
- See the java.lang.Object Java API description for the full contract.
- If wrapping another object then an arbitrary value can be added to avoid collisions in HashMaps, e.g.
public int hashCode() { return 31 * 132 + mName.hashCode(); }
Getting Class Names
- someObject.getClass().getName() should be used and not someObject.getClass().toString().
String Concatenation
- String addition is strongly discouraged, e.g.
String bangles = debbie + michael + susanna + michael;
- StringBuffer should be used instead, e.g.
StringBuffer banglesBuffer; banglesBuffer.add(debbie); banglesBuffer.add(michael); banglesBuffer.add(susanna); banglesBuffer.add(vicki); String bangles = banglesbuffer.toString();
Logging
- Do not use System.out or System.err in server-side classes.
- The exceptions to this rule are test classes and classes executable from the command-line where the print statements form part of the command-line interface for a user.
- Classes must use uk.org.ogsadai.exception.DAILogger for logging, not Log4J.
- DAILogger declarations must be of form:
private static final DAILogger LOG = DAILogger.getLogger(ClassName.class);
- Only the DAILogger class can have a Log4J dependency.
- Use of debug and info logging MUST be conditional if there is string concatenation or other work done to build the log message. Compare and contrast:
LOG.debug("The Bangles are a band!"); if (LOG.isInfoEnabled()) { LOG.debug("The Bangles consist of " + "Debbie, " + "Vicki, " + "Susanna, " + " and " + "Michael"); } - Information within OGSA-DAI is logged at the following levels:
- FATAL - service setup or resource access or some serious problem that affects operation of an OGSA-DAI service.
- ERROR - an internal error of concern but which the client cannot do anything about.
- WARN - a problem caused by a client (and details of which are returned to the client) or an intenal problem that we gulp as unimportant.
- INFO - general status information of interest to a service deployer.
- DEBUG - anything useful for debugging.
- Only exceptions can be logged at FATAL, ERROR or WARN levels.
- Only uk.org.ogsadai.common.logging.MessageIDs can be logged at INFO level.
- Any string can be logged at DEBUG level.
Exceptions
- All exceptions must sub-class uk.org.ogsadai.exception.DAIException or uk.org.ogsadai.exception.DAIUncheckedException or existing sub-classes of these, e.g.:
public class PearShapedException extends DAIException { /** Copyright statement. */ private static final String COPYRIGHT_NOTICE = "Copyright (c) The University of Edinburgh, 2007"; /** * Constructor. * * @param thing * Thing that went wrong. * @param blame * Thing to blame. */ public PearShapedException(String thing, String blame) { super(ErrorID.PEAR_SHAPED_ERROR, new Object[] {thing, blame}); } } - Every exception must have an associated uk.org.ogsadai.exception.ErrorID value, e.g.
/** * Raised when something turns pear-shaped. * * Parameter 1: Thing that went wrong. * Parameter 2: Thing to blame. */ public static final ErrorID PEAR_SHAPED_ERROR = new ErrorID("uk.org.ogsadai.PEAR_SHAPED_ERROR"); - Every uk.org.ogsadai.exception.ErrorID must have an error message in a message bundle, either the defaultogsadai_message.properties message bundle or a custom one. e.g.
uk.org.ogsadai.PEAR_SHAPED_ERROR={0} turned pear-shaped and I know \ that {1} was to blame.
- An error message can have zero or more place-holders.
- Place-holders in error messages must be numbered {0} , {1} , {2} , ... in sequential order.
- Note the fact that the number of entries in the array to the call by PearShapedException's constructor to its super-class constructor is the same as the number of place-holders in the uk.org.ogsadai.PEAR_SHAPED_ERROR message.
- All OGSA-DAI messages must be prefixed by uk.org.ogsadai.
- Do not pass English language strings into a constructor - it undermines the whole point of internationalization and ErrorIDs.
- Do not ever pass Exception.getMessage() into exception constructors.
- Only abstract exception classes should allow ErrorIDs in their constructors.
- If you need to pass an ErrorID to an exception constructor then you probably need to define a new exception with an abstract super-class.
- When writing an exception that wraps another exception / takes another exception into its constructor:
- Preserve the causal chain where appropriate using the initCause() method, e.g:
public AnotherPearShapedException(String thing, Exception cause) { super(ErrorID.ANOTHER_PEAR_SHAPED_ERROR, new Object[] {thing, cause.getMessage()}); super.initCause(cause); } - Do not pass the child exception's getMessage() into the wrapping exception's message parameter list.
- Preserve the causal chain where appropriate using the initCause() method, e.g:
- Methods in service classes that are the entry points for service operation calls should always ensure they wrap all calls to other OGSA-DAI components within try-catch blocks.
- As a last-change fail-safe these should catch java.lang.Throwable so no undesired exceptions can slip back to the client as service faults.
- For server-side components that can communicate to clients outwith the services themselves, e.g. servlets, these guidelines also apply.
- Only log an exception when:
- The exception is gulped without being handed-on or wrapped in another exception that is then thrown .
- The exception is handed over for transit to client (e.g. service layer or response document constructor).
- Exceptions should be logged at WARN, ERROR or FATAL levels only
- Continue to use Java RuntimeExceptions (e.g. IllegalArgumentException) where possible
- No internationalization is needed for runtime exceptions such as IllegalArgumentException - these are a programmers fault.
- Do not use SQLException for illegal arguments or unsupported operations if working within implementations of java.sql.ResultSet.
Changing Class and Package Names
- If you make changes to class or package names then you must do a search through the code base as a whole and the user doc and change any occurrences there also.
- Changes to resource classes and activity classes also need to be reflected in configuration files in SVN and the test system.
- The simple rule is if you change a class or package name do a careful search and replace though all Java, XML, HTML, TXT and properties files - a careful search because we have some classes which have the same local name but different package names.
Developing Activities
- Activity classes should be named as follows:
- Server-side activity implementation classes should be post-fixed by Activity, e.g. MyNewDataProcessorActivity.
- Corresponding client toolkit activity classes should not be post-fixed by Activity, e.g. MyNewDataProcessor.
- All activities should have a user doc page:
- See release-scripts/ogsa-dai/doc/src/DocBook/Developer/ActivitiesAppendix.xml and release-scripts/ogsa-dai/doc/DocBook/Developer/Activities/* for the format and the information it needs to contain.
- When you've added an activity you should:
- Add it to release-scripts/ogsa-dai/server-configuration/server-config/activities.txt.
- Add it to local-config/activities.txt.
- Add it to the appropriate resource files in:
- release-scripts/ogsa-dai/server-configuration/server-config/resourceTemplates/*
- release-scripts/ogsa-dai/server-configuration/config-blanks/*
- local-config/resources/*
- local-config/resourceTemplates/*
- When writing or modifying activities, any illegal values that are provided as inputs must not be handled as IllegalArgumentExceptions}.
Tests
- Tests are implemented using JUnit.
- Each class should have a JUnit test suite (set of test cases).
- Do not print out XML fragments via System.out or System.err - ANT outputs test reports in XML and these are then converted to HTML for the test dashboard. Arbitrary XML fragments printed by test classes can break this process.
- The test class should have the same package name as the class being tested with the postfix Test.java:
- e.g. the class Bangles.java has an associated test class BanglesTest.java.
- The tests should cover the black-box functionality of the component including error cases.
- There should also be concise and simple JavaDoc comments completed for each test method in the test.
- All test classes should include a main method:
public static void main(String[] args) { junit.textui.TestRunner.run(BanglesTest.class); } - All testX() methods should throw java.lang.Exception.
Keep it Clean
- If you see that code looks inefficient or could be cleaned up or that JavaDoc is missing or inaccurate then you should e-mail the author rather than silently fixing the problem
Eclipse Setting
if you are going to use eclipse to develop OGSA-DAI code then these are the warning setting we recommend you use with eclipse. To set these find the preferences window:
- Window->Preferences
Most of the settings can be set in
- Java->Compiler->Errors/Warnings
Some are are also to be found in
- Java->Compiler->JavaDoc
Code Style
| non-static access to static member | Warning |
| indirect access to static member | Ignore |
| unqualified access to instance field | Ignore |
| undocumented empty block | Warning |
| access to a non-accessible member.. | Warning |
| method with a constructor name | Warning |
| parameter assignment | Warning |
| non-extrernalizes strings | Ignore |
Potential programming problems
| Serializable class without... | Ignore |
| assignment has no effect | Warning |
| possible accidental boolean assign.. | Warning |
| finally does not complete normally | Warning |
| empty statement | Warning |
| using a char array in string concat | Warning |
| hidden catch block | Warning |
| inexact type match | Warning |
| boxing and unboxing | Warning |
| enum type constant.. | Warning |
| switch case fall through | Warning |
null reference
Naming and shadowing
| field decl... | Warning |
| local variable decl hides | Warning |
| ..include constructor | On |
| type parameter hides.. | Warning |
| method overridden but not pack.. | Warning |
| interface method conflicts | Warning |
Deprecated and restricted API
| All | Warning |
Unecessary code
| local variable is never read | Warning |
| parameter is never read | Ignore |
| ..check overriding.. | On |
| unused import | Warning |
| unused local or private member | Ignore |
| unnecessary else statement | Ignore |
| unnecessary cast | Warning |
| unnecessary declaration of throw.. | Ignore |
| unused break/continue label | Warning |
Generic types
Java 5 does not matter to us
Annotations
Java 5 does not matter to us
JavaDoc
To set these settings go to:
- Java->Compiler->Java Doc
| Process Javadoc comments | On |
| malformed Javadoc comments | Warning |
| Only consider members as visible as | Private |
| ..Report errors in tags | On |
| ..Report non-visible references | On |
| ..report deprecated references | On |
| Missing Javadoc tags | Warning |
| ..Only consider members as visible as | Private |
| ..check overriding and implementing.. | Off |
| Missing Javadoc comments | Warning |
| ..Only consider members as visible as | Private |
| ..check overriding .. | Off |
Back to parent page.
Download in other formats:
© 2013 SourceForge. All Rights Reserved. SourceForge is a Dice Holdings, Inc. company Terms of Use - Privacy Policy - Cookies/Opt Out
