= Equinox Coding Practices ?>
Coding Practices
Equinox covers a reasonably large code base. To ensure coherence and consistency, the team follows a number of coding conventions and practices. For the most part these conventions are supported by the Eclipse tooling (e.g., formatter settings) so its really a matter of setting it up and going from there. Give yourself over to the tooling and forget about formatting. Just let the tools do their work.
Legal
- All committed contributions from non-committers must be tracked. This must be done by using the 'contributed' keyword in bugzilla. A non-committer is someone who is not a committer on the Eclipse Top-Level project
- All classes MUST have the correct copyright notice. See the Foundation's legal page for a template.
- If the code was written in 2003, don't have 2000,2003 in the copyright.
Attribution
Contributors should feel free to identify themselves individually or by company in the code. There are three main places this is done.
- in the copyright line (first line in class comment). Here the first/main entity that legally owns the copyright should be listed first followed by "and others". See the legal notes above.
- in the Contributors section of the class comment. Here we want to capture a rough sense of who (people and/or companies) has made contributions. We do not need to be overly specific about which contributions. General descriptions such as "bug fixes", "performance enhancements" or "continuing development" are fine. This is information is partly to cue the legal process to ensure proper tracking (though the actual tracking is done through Git and Bugzilla) and partly to give contributors visibility and acknowledgment for their contributions. People are free to put their names in this section if they choose however, traditionally we have identified simply identified companies/organizations here. We have opted for this approach to eliminate the continual maintenance of the list. Contributors wanting to have their names in this section are certainly welcomed to do so in their patches.
- in the @author tag in the class Javadoc. For the most part the Eclipse project team does not use @author as there are typically a vast number of people working on and contributing to the code. Maintenance of such a list would be quite cumbersome and poorly maintained authorship lists give a false picture of code evolution.
Use the tools
For the most part you can just use the preference template files supplied here to configure the various tools to do the same as the rest of the team. These preference files are typically found in the .settings directory of a project. To apply the preferences simply copy the template file from here into the .settings folder overwriting the original. Of course, you may choose to merge the settings but beware of varying too far from the standard coding practices. The templates cover code formatting, organize imports, code cleanup wizard settings and enabling these operations to happen automatically on save.
- Equinox JDT Core preferences - template for compiler and code formatting preferences
- Equinox JDT UI preferences - template for editor preferences (e.g., format on save etc.)
Coding style
- Use blank lines sparingly. Group lines of code together as you would group sentences into paragraphs in written text.
- Don't use braces for simple if/for statements. Use braces where it improves code readability and clarity, such as in nested control statements.
- These settings should be done on each Equinox project so that everyone uses the same settings.
- Data type size initialization -> use meaningful values if possible, not things like: new HashSet(65)
- Use interfaces when declaring variable types and in method signatures unless it is necessary to use implementing class
- Use accessor methods, don't access variables on other classes directly
- Exit methods as early as possible by using the "true" case of an "if" clause. For example, if the whole method is inside an "if (!foo) {}" then just say "if (foo) return".
- Ignored exceptions must have a comment saying that they are being ignored on purpose (compiler warning)
- The lines where we create new CoreExceptions and throw them can become quite long. We usually declare the String message on the line previous to make it easier to read.
- Check for null if null could be returned (table look-ups, etc)
- Should use IPath for path logic rather than Strings and concatenation
- IPaths are your friend. Replace "new File(location.toOSString())" with location.toFile();
- Don't catch Exception unless you have to. Try to catch specific exceptions.
- Don't wrap the whole method in a try {} catch {} block. This makes it hard to generate specific error messages
- If you have nested readers/streams you should only have to call #close() on the outside one and all wrapped streams should be closed automatically (note: you may have to call #flush() first)
- Ensure all file I/O is buffered.
- When sharing code with others, ensure that all the code released to the repository at least compiles.
- Compiler tasks. We have 3 that we use as a team (TODO, FIXME, XXX) Do not add your own as this is unnecessary and requires everyone on the team to change their compiler settings in order to see these tasks.
Comments
- Comments are a good thing but are not a substitute for good naming (see next section). Comment all "non-obvious" things whether they be methods, fields, arguments, algorithm steps, ...
- Javadoc on API is essential
- Follow the Javadoc guidelines as well as @since etc recommendations
Naming
- Choose class/method/field names that describe the purpose of the entire method/class.
- Choose names that are semantically useful. Type-based names are taboo! Java is strongly typed, why repeat the type in the name? For example, use setFoo(Foo foo) is not as interesting as setFoo(Foo value).
- Further, the use of semantic names makes cutting and pasting of similar code easier and less error-prone.
- Try for complete words rather than fragments (e.g., getProjectValue is better than getProjVal).
- Avoid generic variable names like "temp" or "index" (Exception: really short methods where usage is very straight-forward an in cases of i, j, etc for loop indexes).
- get/set prefixes should be reserved for real accessors. If the method does real work, it's not an accessor. (Note: we don't always follow this rigorously, but we try. Lazy initialization is one such exception).
- Avoid random word prefixes such as "a" and "the". They don't add value.
Internationalization
- Follow the NLS guidelines and use the Eclipse NLS mechanism.
- All sentences which are displayed to the user must end with a period.
- Include parameters if possible
- Remove unused messages
- Make sure if the message accepts a parameter then you pass one in
Exception handling
- When catching exceptions, consider whether it is some low-level error that the client should not be aware of or will not be able to interpret. Consider wrapping in an exception with a message and API status code that will make sense to the caller.
- Whenever possible let exceptions flow back to the caller through a declared exception specified in API rather than catching and swallowing/logging ourselves. Since our code is typically very low level, the caller often has better contextual knowledge of whether it would more appropriate to log the exception, present to a user, or swallow it.
- Only suppress or log exceptions if irrelevant to the caller and doesn't affect the success of the operation the caller is attempting to perform.
- Should only have empty catch blocks if the exception is truly impossible, or if we completely understand all the cases where this exception can occur and we understand that it has no effect on the success of the operation. When in doubt log it.
- Never throw generic Exception or Error - use a more specific subclass appropriate for the error condition.
- Logged exception messages should not be externalized/translated. If there is any possibility of an exception being propagated to client code it must have externalized messages.