Java Coding Conventions considered harmful
Tjuvholmen seen from a boat |
2.2 Common File Names:
GNUmakefile
The preferred name for makefiles. We usegnumake
to build our software.
gnumake
to build Java projects? ant is considered old-school, so is maven. Who uses make
to build WARs, JARs, generate JavaDocs...?3.1.1 Beginning Comments:
All source files should begin with a c-style comment that lists the class name, version information, date, and copyright notice:Putting a class name in the comment starting a file? What if I change my mind and rename the class later? And what should that "date" represent? Some people use various placeholders to insert last modification time of a file automatically by version control system. Well, VCS is there to tell you when the file was created or last modified - and modifying the same line over and over again makes merging a huge pain.
4 - Indentation:
Four spaces should be used as the unit of indentation. The exact construction of the indentation (spaces vs. tabs) is unspecified. Tabs must be set exactly every 8 spaces (not 4).Probably the most counterintuitive part of the document. Some prefer spaces, others (including me) - tabs. A matter of taste and team arrangements. But this guide suggests to use both and replace spaces with tabs, sometimes. It's "unspecified". My advice: use tabs and let each developer configure his IDE to have as big or as small indentations as desired.
4.1 Line Length:
Avoid lines longer than 80 characters, since they're not handled well by many terminals and tools.
80 characters? My laptop can easily fit three times as much. Strive for 120-140 characters in one line, but don't use hard-wraps. Personally I just display vertical margin and the right line length is dictated by readability. BTW here are few examples of classes from various libraries and frameworks:
SQLIntegrityConstraintViolationException
(JDK 7, 40 characters)
AbstractInterruptibleBatchPreparedStatementSetter
(Spring framework, 50 characters)
AbstractDataSourceBasedMultiTenantConnectionProviderImpl
(Hibernate, 56 characters)
PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails
(Spring Security, 58 characters)
5.1.2 Single-Line Comments:
if (condition) {Just in case the code is not self-descriptive enough, I suggest even better comment:
/* Handle the condition. */
...
}
if (condition) {
/* This block is executed if condition == true. */
...
}
5.1.3 Trailing Comments:
if (a == 2) {Did you mean (and don't tell me it's less readable, even without comments)?
return TRUE; /* special case */
} else {
return isPrime(a); /* works only for odd a */
}
return a == 2 || isPrime(a);
6.1 Number Per Line:
int level; // indentation levelWhy use descriptive variable names, when we have comments! Consider this instead:
int size; // size of table
int indentationLevel;Later in that section:
int tableSize;
In absolutely no case should variables and functions be declared on the same line. Example:Sure it's wrong, it doesn't even compile. I'm surprised that "don't put spaces in variable names" is not mentioned as a good practice...long dbaddr, getDbaddr(); // WRONG!
6.3 Placement:
Put declarations only at the beginning of blocks. [...] Don't wait to declare variables until their first use; it can confuse the unwary programmer [...]This is how the coding conventions want you to write your code:
int min; //inclusiveAnd this is how it should be written to avoid confusion:
int max; //exclusive
int distance;
List<String> list; //one per each item
min = findMin();
max = findMax();
distance = max - min;
list = new ArrayList<>(distance);
//...
final int minInclusive = findMin();Besides we can finally (nomen est omen) use
final int maxExclusive = findMax();
final int distance = maxExclusive - minInclusive;
final List<String> listOfItems = new ArrayList<>(distance);
//...
final
keyword. Later in this section code sample is shown with class fields missing private
modifier (default, package private access). Package private field?7.3 return Statements:
return (size ? size : defaultSize);Maybe you haven't noticed, but from the context we can tell that both
size
and defaultSize
are of boolean
type. That's right, size
and defaultSize
can be either true
or false
(!) How counterintuitive is that! From such a document I would expect not only syntactical correctness, but also meaningful code and good practices! Moreover, the expression can be greatly simplified, step-by-step:size ? size : defaultSize
size ? true : defaultSize
size || defaultSize
7.5 for Statements:
An empty"emptyfor
statement (one in which all the work is done in the initialization, condition, and update clauses) should have the following form:for (initialization; condition; update);
for
statement"? Why would you ever use an empty for
statement? This is confusing and should be avoided, not encouraged and described in the official language guide.Bonus quiz: what's the purpose of this code in C?
while(*dst++ = *src++);I believe every computer programmer should understand the code snippet above. Even if you program in Ruby or TSQL.
7.8 switch Statements:
Every time aI understand the intentions, but the approach is wrong. Instead of documenting unexpected and error-prone code-fragments, just avoid them. Don't depend on fall through, don't use it at all.case
falls through (doesn't include abreak
statement), add a comment where thebreak
statement would normally be.
8.1 Blank Lines:
One blank line should always be used in the following circumstances:Looks like the authors suggest using blank lines to separate "logical sections of a method". Well, I call these sections: "methods". Don't group statements inside methods in blocks, comment them and separate from each other. Instead extract them into separate, well named methods!
[...]
- Between the local variables in a method and its first statement
- Before a block [...] or single-line [...] comment
- Between logical sections inside a method to improve readability
Placing a blank line between variable declarations and the first statement sounds like taken from a C language book.
8.2 Blank Spaces:
This doesn't even compile in Java...[...]
- All binary operators except
.
should be separated from their operands by spaces. Blank spaces should never separate unary operators such as unary minus, increment ("++
"), and decrement ("--
") from their operands. Example:while (d++ = s++) {
n++;
}
9 - Naming Conventions (only in PDF version):
char *cp;A good name for a
char
pointer in Java is cp
. Wait, WAT? char
pointer in Java?10.1 Providing Access to Instance and Class Variables:
Don't make any instance or class variable public without good reason.Really, really good reason! Did I ever used
public
field?10.4 Variable Assignments:
if (c++ = d++) { // AVOID! (Java disallows)Great advice: please avoid using constructs that do not even compile in Java. This makes our lives so much easier!
...
}
10.5.2 Returning Values:
if (booleanExpression) {
return true;
} else {
return false;
}
should instead be written as
return booleanExpression;Holy cow, I AGREE!