Difference between revisions of "PKI Java Coding Style"
(→Naming Conventions) |
(→Naming Conventions) |
||
Line 19: | Line 19: | ||
'''Exception Names''' | '''Exception Names''' | ||
− | * Exception names should begin with "E". For example, | + | * Exception names should begin with "E". For example, EFCSException. |
− | * Exceptions should have their own hierarchy in each certificate server subsystem. (This implies that each subsystem should define a new exception that extends the base exception | + | * Exceptions should have their own hierarchy in each certificate server subsystem. (This implies that each subsystem should define a new exception that extends the base exception EFCSException). |
'''Class Names''' | '''Class Names''' |
Revision as of 22:19, 12 June 2007
This manual contains the Java coding standards and guidelines for Fedora Certificate System and Fedora Directory Server contributors.
These projects have evolved over a very long time (see History). As a result not all of the existing code conforms to these standards. All new Java code should adhere to these standards but please do not go back and make wholesale formatting changes to the old code. It just confuses things and is generally a waste of time.
Contents
General Coding Rules
Naming Conventions
Package Names
- Package names should be single lowercase words.
- Fedora Certificate System-specific packages should be sub-packages of "com.netscape.certsrv".
Interface Names
- Interface names should begin with "I". For example, IConfigStore.
Exception Names
- Exception names should begin with "E". For example, EFCSException.
- Exceptions should have their own hierarchy in each certificate server subsystem. (This implies that each subsystem should define a new exception that extends the base exception EFCSException).
Class Names
- Concrete classes should use natural descriptive names, begin with a capital, and have mixed case. For example, FooBarReader.
- Abstract classes should begin with "A". For example, ABaseClass.
Member Function Names
- Method ("member function") names should begin with a lowercase letter with each subsequent new word in uppercase, and subsequent letters in each word in lower case.
- Methods for debug-only implementations should begin with "debug".
- Static methods should begin with a capital letter with each subsequent new word in uppercase, and subsequent letters in each word in lower case.
public class MyClass { void doSomethingNeat(int aValue); void debugDumpToScreen(); static void SomeClassMethod(int aValue); }
Component Factory Names
A component factory is a public class that implements only static methods. These static methods are "Factory functions" or "component constructors". Factory class names should include the word "Factory". Factory method names should start with the word "Make." For example:
public class WidgetFactory { static Button MakeButton(int aButtonType); static ListBox MakeListBox(); }
Function Naming Patterns
- Get and set methods should begin with "get" / "set" and return the appropriate object type.
- Boolean get methods should use "is" or "can" as a prefix, such as "isUndoable()" rather than "getUndoable()".
Constants
- Constants will use all uppercase and will have words separated by underscores.
General Varibles and Paramters Names
- Variables and parameters will begin with a lower case, and have mixed case. For example, fooBarReader.
- Member variables should begin with "m". For example, mMemberVariable.
Commenting Code
- All interfaces and public classes should have JavaDoc comments. See the "Javadoc API" page for more information.
General Coding Gudelines
Java Grammar
- Wherever appropriate, avoid code that embeds many operations in a single line. For example, avoid:
someObject.doThis(i++, otherObject.someField.doThat(), x?y:z)
This kind of code is error prone, difficult to decipher, and hard to maintain.
Debugging
- First and foremost, go read Writing Solid Code. Now go back and reread the java programming language reference documentation to refresh your memory on the precedence order of operators.
- Now go read the <A HREF="ErrorHandling.html">Abnormal Condition Handling</A> document.
- You can never do enough coverage testing. Make sure every path of execution through your code has been thoroughly tested. Here's a neat idea: try actually stepping through each line! While you're hard at work testing your code, be sure to throw invalid inputs at every public interface you provide. The last thing we want to do is crash because your routine didn't handle invalid inputs from ours. Never ever break the build (except by prior agreement of all members of the team, for a specified purpose and duration.)
- Want to know the secret to fast code? Calculate those comparison values once: reuse them often. Avoid global variables too, since they can wreak havoc with the pre-fetch instruction queue.
Orthodox Cannonical Form
Don't forget to adhere to our Orthodox Canonical Form. This is a template that, when followed, guarantees that you have all the default methods your class needs to be a good java citizen. See Standards.java on the magellan site.
It is our policy to produce code that can test itself to the greatest extent possible. To that end, we encourage the use of three debugging techniques:
- asserts,
- pre/post conditions, and
- self testing methods.
- String copyString(String aOtherString)
- {
- Assert.PreCondition(NULL != aOtherStr, "Null string given");
- ...
- Assert.PostCondition(fSelfString.length() >=aOtherString.length(), "lengths don't match after copy.");
- }
1. Asserts
It is highly recommended that assert methods (warnings/errors) be used to aid in debugging, especially to verify assumptions made in code. This will be the technique used for reporting run-time errors and warnings. There is a full suite of assert technology provided in mg.util.Assert.java.
<P>We've worked through many of these issues, and they can be found in the Abnormal Condition Handling document on the Magellan site.
2. Pre and Post Conditions
In order to bulletproof your code, you should use asserts to test all boundary conditions. You aren't doing anyone any favors by "defensive" programming practices that allow clients of your code to make improper calls.
In other words, it is better to blow up (in debug builds) if you are given bad data than to try to "fix" the data and therefore hide bugs. <DIR>example <DIR> <DIR> </DIR> </DIR>
<DIR> </DIR> </DIR>
We do not want debug code to be included into release builds. Therefore, all assertions are removed by the compiler (the java equivalent of #defines) by flipping the debug flag in the Assert class.
3. SelfTest Methods
Each package will include a SelfTest class. This class should have routines to thoroughly unit test every class in the package. If appropriate, the SelfTest class may also contain methods for integration test between the classes in this package, and between the classes in this package and their dependancies in other packages.
<P>Here is the rule. When you design your class, you should design its unit test. When you design your package, you should design your integration test. You are NOT done with the implementation of a class until its unit test is implemented and can be run successfully. You are NOT done with your package implementation until all unit test are coded and run successfully, and the integration tests (if appropriate) are coded
and run successfully.Parentheses
<P>1) are recommend for Boolean expressions to ensure proper evaluation
<P>example:
TIP: Place constants on the left side of your expressions; assignment,
boolean and otherwise. This technique can catch assignment (versus equality)
errors, as well as promote constant factoring for poor quality compilers.
This is the preferred way to write expressions, though (especially in Java where mistakes are generally caught by the compiler) the "traditional" method where constants are on the right side is acceptable. Remember, though, your code may be ported to C++ someday...
<P>Constants
Constants should be used when the same values needs to used in several
places, and the actual values is either arbitrary or subject to possible
change. For example, if in a number of places you are using buffers,
and you expect to try tuning the buffer size for best performance, then
use a constant because you expect to change the value. Another example
is exception ids where the value itself does not matter, and the constant
identifier is far more mnemonic and readable. Constants should not
be used for values that you know will be referenced only once (e.g. ID_FOR_EXCEPTION_THIS_METHOD_THROWS)or
for values that are not (reasonably) expected to change (e.g. NUMBER_OF_SUPREME_COURT_JUSTICES,
or NUMBER_OF_DAYS_IN_WEEK). If you think the calculation needs clarification,
include this information in comments, but adding constant identifies in
some cases simply slows the compiler and makes the code harder to read.
This is a really tough judgement call, so think carefully.
<A NAME="Source Code Style"></A>Source Code Style Guidelines |
Copyright Notice
This text, as a minimum, should be places at the top of all source files
which are not made publicly available:
* Copyright (c) 1997 Netscape Communications Corporation
* ======================================================
- /
<P>Method Orderings
<P>The methods in a class should be grouped, and ordered in the following format:
- Constructor
- finalizer (Destructor)
- public methods
- private methods
- debugging methods
Each group of methods can be optionally attached with comment block in addition to individual method comment. For example,
- /* ======================================================= *
- /
CONSTRUCTOR METHODS (OPTIONAL)
* =======================================================
/**
* Constructs a certificate server
*/
public CertificateServer() {
...
}
Line Spacing
<P>Line width should not ordinarily exceed 80 characters. Use your best
judgment.
Tab sizes are to be set equal to 4 spaces. Tabs should be expanded
to spaces.
<P>Braces
<P>The starting brace can be optionally at the end of the condictional
or on the next line aligned with the conditional. The ending
brace must be on a separate line and aligned with the conditional.
It is strongly recommened that all conditional constructs
define a block of code for single lines of code.
<P>We give some options below to accommodate the vast majority of programmer's
styles. HOWEVER, be consistent! When
you pick a style, stick to it. When editing another person's
code, use your own judgement. As a default position, mimic the
style of the coder if you are just changing a small amount of code
within some existing function. Use whatever style you feel
appropriate when writing new methods.
<P>Parentheses
<P>1) are recommend for Boolean expressions to ensure proper evaluation
<P>example:
if (((someValue<foo(theParm))
&& anotherValue) || todayIsMyBirthday)
TIP: Place constants on the left side of your expressions; assignment,
boolean and otherwise. This technique can catch
assignment (versus equality) errors, as well as promote constant factoring
for poor quality compilers. This is the preferred
way to write expressions, though (especially in Java where mistakes
are generally caught by the compiler) the "traditional"
method where constants are on the right side is acceptable.
<P>If / Else
<P>Place the IF keyword and conditional expression on the same line. Always
use the braces around the statement block, even if
it is only one line. Put the starting brace after the expression
on the same line. If you have an else, but the closing brace, the
else, and the opening brace on the same line.
<P> example:
if (expression) {
statement;
} else {
statement;
}
<P>WHILE
<P>The WHILE construct uses the same layout format as the IF construct.
The WHILE keyword should appear on its own line,
immediately followed by the conditional expression, and finally by
the opening brace. Always use braces, even if the body is
only a single line. Indent the body 4 spaces.
<P> example:
while (expression) {
statement;
}
<P>
do (expression) {
statement;
} while (expression);
<P>SWITCH
<P>The SWITCH construct uses the same layout format as the if construct.
The SWITCH keyword should appear on its own
line, immediately followed by its test expression and then the opening
brace. The case expressions may be indented, but need
not be. The lines between the case expression should be indented
4 spaces.
example:
<P>
switch (expression) {
case n:
statement;
break;
default: //always add the default case
statement;
break;
}
<P>Try/Catch/Finally
<P>The try/catch construct is similar to the others. TRY keyword
should appear on its own line; followed by the open brace on
the same line; followed by the statement body; the close brace should
be on the same line with the CATCH. Any number of
CATCH phrases are next consisting of the closing brace, the CATCH keyword
and the exception expression, the opening
brace; followed by the CATCH body; followed by the close brace.
The FINALLY clause is the same as a CATCH.
<P>
try {
statement;
} catch (expression1) {
statement;
} catch (expression2) {
statement;
} finally {
statement;
}
<A NAME="Documentation for Methods and Functions"></A>JavaDoc Comments |
All interfaces and public classes should have JavaDoc comments. Here are some guidelines:
- spend some time describing the class and what it is expected to do. This is the most important doc.
- If you know of notable subclasses, try to link them in since navigating down is difficult without it
- next, time permitting, write javadoc descriptions of the methods. Include a short description of each parameter.
- finally, once all above is done, document the instance and static variables.
- DO NOT write "content free help", e.g. a comment that simply reiterates the name of the function, or the return type, is worse than no comment at all. Leave the comment empty if you can not add anything more than the method name and/or return type.
You may want to check some <A HREF="http://warp/client/xena/devcentral/docs/Javadoc_Basics.html">JavaDoc Basics</A> available on warp, or the official <A HREF="http://www.javasoft.com/products/jdk/1.1/docs/tooldocs/win32/javadoc.html">JavaDoc documentation</A>.
Method Documentation
The following standard has been established for the documentation of methods and functions. Optional items are to be included only where applicable. A complete description of each section in the routine documentation follows.
<P>The header is designed to be easy to use. Many items are optional, and may be omitted where they are not applicable. Each line item begins with an asterisk, and ends with blank space. You do not place an asterisk next to each line in a multiline component, only the topmost, next to the title. All subsequent lines in multiline component are to be indented so that they line up vertically with the previous line.
<P> example:
- <Detailed description of method.>
- @param <Description of each parameter>
- @return <explain each return type>
- @exception <explain each exception>
- @author <your name> <04-22-97
3:57pm>
- /
<P>Here are a list of points that you may want to cover when writing the
description of the method:
- intent of method
- pre and post conditions
- side effects
- dependencies
- implementation notes
- who should be calling this method
- whether the method should or should not be overridden
- where to invoke super when overriding
control flow or state dependencies that need to exist before calling