Table of Contents
"Follow a common coding standard, so that all the code in the system looks as if it was written by a single — very competent — individual. The specifics of the standard are not important: what is important is that all the code looks familiar, in support of collective ownership." | ||
--Ron Jeffries XProgramming.com |
Coding Standards are a good idea. Every team should adopt a coding style and standard, and stick to it. The code produced by that team should have a consistent look and feel that is devoid of individual preferences and fetishes. | ||
--"Uncle" Bob Martin ObjectMentor website |
The primary goal of this chapter is to provide common conventions, as well as guidelines that aim at ensuring a high level of quality (with respect to maintainability, extensibility, modularity, security, testability, documentation, etc.) throughout the Nuxeo project.
As such, it is primarily written for the platform's developers, both "core" developers and contributors, and developers that write extension modules that will someday find a place in the Nuxeo codebase.
If you're working on your own project with no plan to contribute code to the Nuxeo platform, you will probably be still interested in reading this chapter, and adapt the conventions stated here to your company's or organization's own coding standards.
Rewriting a whole coding standard for the Nuxeo project would be a poor use of our time, since there are already several documents and books that do a fine job in this respect.
We've opted for a more pragmatic, two-pronged approach:
The official coding standard for the project is: "The Elements of Java Style" [Vermeulen2000] which is a little book that can be bought from Amazon or other book dealers.
If a PDF suits you better, you can download an earlier version of the book from here.
Note however that these guidelines have been written in 2000 (last century!) and some of the recommendations need the be updated in light of this millenium's experience.
There are also architectural guidelines that need to be followed. At this moment, they are written here (section 4 - "Guidelines")
Readability counts. | ||
--Tim Peters The Zen of Python |
Java code should be formatted using Sun's Code Conventions for the Java Programming Language.
Regarding code formatting (which is just one small part of the book and PDF mentioned above), we'll be using the standard Eclipse default style, with a couple of minor tweaks (see this README.txt for how to configure Eclipse to support this style).
The major points are:
regarding code block, we are using 1TBS ("One True Brace") style:
Bad:
if (xxx) { yyy }
Good:
if (xxx) { yyy }
make a block even for only one statement:
Bad:
if someThing() doSomething; if someThing() doSomething;
Good:
if someTest() { doSomething; }
Don't prefix your instance variables by "this." when it's not mandatory.
Why? Because with modern IDEs, instance variables are typeset in a different color than local variables, hence you don't need the extra information provided by the "this." prefix to recognize which is which.)
XML code should also be formatted, using 2 spaces for each indent level (not 4 spaces).
Badly formatted XML code can be reformatted using the Eclipse formatter.
Always check that the result is better than the original, and tweak afterwards if needed.
Use interfaces every time it is possible instead of concrete classes.
Ex: declare a variable or argument as a "Map", not as a "HashMap".
Why? Using interfaces makes it possible to use several different implementations. Actually, interfaces are the basis of component-oriented programming.
But don't overdo it if it's not necessary.
Why? The more code we have, the more expensive maintainance is.
Avoid cyclic dependencies.
Why? This is a common design principle, called the "Acyclic Dependency Principle" or "ADP".
How? use JDepend or a JDepend plugin for you IDE (ex: http://andrei.gmxhome.de/jdepend4eclipse/) or look at the JDepend report by Maven.
More info:
If it's not tested, it's broken. | ||
--Bruce Eckel |
Write unit tests. A lot.
How? Learn how to use JUnit. Use tests in existing modules as examples. Remember that well-tested modules have at least as many lines of test code than not test code.
Check that your unit tests have a coverage of most of the critical parts of your code.
How? Look at the Cobertura report by Maven, or use the TPTP or EMMA (http://www.eclemma.org/) plugins for Eclipse or use the native code-coverage function of IDEA.
Design your API so as to make unit testing possible and easy.
Some cosmetic remarks related to writing unit tests:
Use "assertEquals(constant, value)", not "assertEquals(value, constant)"
Why? Because one has to choose a convention and this one
Use "assertNull(value)", not "assertEquals(null, value)"
Why? Because code is shorter and looks cleaner this way.
Don't use underscores ("_") in variables, methods or class names, use camelCase notation instead.
Why? Because it is the Java convention.
Check some good articles on naming things, like Ottinger's Rules for Variable and Class Naming.
It is especially important that we all use the same words (in case there is an ambiguity) to refer to the same concepts (like "fetch" vs. "retrieve", for instance).
Minimize the accessibility of classes and members (for instance by making them "private" unless you have a reason to believe that they will be used from other classes, and more generally by using the weakest access modifier ), so as to keep you API clean and easy to understand for other developers.
Reference: "Effective Java" [Bloch2001], item 12.
Use java 5's generics.
Why? This will improve the amount of static checks done by the compiler.
Follow this piece of advice from Alex Miller:
My opinion is that there are 4 log levels that matter for general program logging (specialized logs like audit and performance have their own rules). I dont care what you call them so feel free to replace these with the names of your choice.
The first three levels (ERROR, WARNING, and INFO) should always be on. If your logs grow rapidly with these levels on, something is wrong. You should be able to run in production with these levels for weeks without a problem (but you should really use a rolling log writer just in case). DEBUG should be used only during development for debugging.
Reuse is something that is far easier to say than to do. Doing it requires both good design and very good documentation. Even when we see good design, which is still infrequently, we won't see the components reused without good documentation. | ||
--D. L. Parnas The Mythical Man-Month: Essays on Software Engineering |
Always use comments to document what is not obvious.
Why? Otherwise, it will be harder for others (even you!) to maintain or extend your code. Some people may even end up refactoring your code under wrong assumptions.
See for instance item #28 of Bloch's "Effective Java" [Bloch2001] for more insight, including this most important principle:
The doc comment for a method should describe succinctly the contract between the method and its client. With the exception of methods in classes designed for inheritance, the contract should say what the method does rather than how it does its job.
Write javadocs according to the javadoc manual and the official Sun javadocs guidelines.
Why? Because javadocs are compiled by a standard tool, you must conform to the syntax mandated by this tool.
Common javadoc guidelines that are often forgotten include:
Proofread carefully (including checks for spelling and grammar errors) and check that your javadocs provide useful information for third-party developers (or your teammates) by actually reading the generated doc.
How? See either "Project -> Generate Javadocs" from Eclipse, or "mvn javadoc:javadoc" from the project root and browse the docs.
Remember that you can see a preview of how your javadoc will look like from Eclipse by using the "Javadoc" tab in the Java perspective.
Don't mix Javadoc comments with implementation comments.
Javadocs comments are intended to be read by clients of the API, implementation comments by people who need to review you code or who will end up maintaining it (including yourself).
For instance, don't put "TODO" markers in your javadoc because they are intended for yourself or other people co-developing or maintaining your code, not clients of the API.
Start by documenting the most important and less obvious things.
If you don't have enough time to document everything, document first the API part of your code (usually, the interfaces), because that's what third-party developers are going to use.
Also documenting the non-obvious (like giving an overview of a package or an important class) is more important than writing for instance, that a "getTitle()" method "@returns the title".
Write package-level javadocs.
Package-level Javadoc (just package.html
files in your
source code) are the most important javadocs you have to write,
because that's what people reading the javadoc-generated site will
read first, and because that's where the information is usually the
less obvious.
Sign your code (in the modules headers).
It is very important that people who will read / maintain your code know that you are the author, so that they can ask you questions, give you feedback, etc.
When you've borrowed code from another open source project, always document it so that:
Put markers as (inline) comments to document parts of your code that will need further work.
Look critically at the javadoc-generated site and try to improve it.
Either go to http://maven.nuxeo.com/apidocs/ and check the apidoc for your project, or run mvn javadoc:javadoc locally and browse the generated apidoc, and ask yourself the simple question: "if I was a third-party developer, would I understand how to use the API by reading this".
Don't use deprecated features (= API), either from Java or third-party libraries, or from the Nuxeo framework.
Hint: they should appear as stroked-out in your IDE.
Here are a few points and tips to keep in mind.
Modern IDEs (+ adequate plugins, if necessary) include many code-checking functions that help find out issues:
For Eclipse, the simplest plugin to use is TPTP.
How?
You should also use the Checkstyle and FindBugs Eclipse plugins to ensure minimal bug count and maximal coding style coherence.
See these great slides from JavaOne 2007 for instance.
Read Improving code with Eclipse plugins on developerWorks for more background information on the subject.
From the article:
This article covers what I consider to be the "big five" code analysis areas:
- Coding standards
- Code duplication
- Code coverage
- Dependency analysis
- Complexity monitoring
These analysis areas can be uncovered using a number of the following slick Eclipse plugins:
- CheckStyle: For coding standards
- PMD's CPD: Enables discovering code duplication
- Coverlipse: Measures code coverage
- JDepend: Provides dependency analysis
- Eclipse Metrics plugin: Effectively spots complexity
NB: Coverlipse may or may not work correctly, an alternative is EclEmma which is very similar.
When something looks wrong in the code ("smell"), refactor it, but make sure you don't break anything.
How?
Here is a list of useful stuff to read: