The java programming language offers a number of ways to format code. Many programmers abuse this freedom and write unreadable (and thus incomprehensible and unmaintainable) code. While there is more than one way to properly format code, here is a set of guidelines which have been found useful in practice. Note that marks will be taken off for poor formatting (more marks deducted as the term goes on). Some of these guidelines may seem amazingly anal, but they really make a difference when reading code. Remember: you are writing code not just for the compiler, but for other people to read as well. The other person reading your code will most likely be you six months from now, so making sure that your code is readable is extremely important.
In the following, each item has a code associated with it to the left of the description of the item. This code will be used to specify the problem when correcting your code. It is up to you to match the code with the item. Hopefully this will encourage you to read this style guide :-) As a general rule, the earlier items in a section are more important than the later ones and/or represent more common errors.
In order to make life easier on you, we are supplying you with an automatic style checker. It won't catch all of these errors by any means, but it will catch a lot of them. You will be required to run your code through the style checker before you submit it; if it fails, it won't be graded (unless you can convince us that the style checker itself has a bug, which is possible). The java style checker is an executable script which is written in python, which is available on the CS clusters. You should download the style checker script, put it in your "~/bin" directory (create one and put it in your path if you haven't done so already) and then do:
% chmod +x ~/bin/java_style_checkThen, to style-check your file "foo.java", do:
% java_style_check foo.java("%" is the unix prompt here.) Don't be alarmed if there are a lot of errors reported; just go through the file and fix them. Some lines will probably have multiple style violations; you should fix all of them. You'll probably hate us for writing this program at first, but your code will become much more readable as a result. If you think you've found a bug in it, let us know at once; this is a work in progress. Note that the style checker will sometimes be too stupid to know when it's in the middle of a comment or a literal string, so it may report errors that aren't really errors in those cases. If so, just disregard them. Note that the style checker can also handle multiple java source code files, so you can do:
% java_style_check *.javainstead of having to specify each file individually.
Never, ever, ever use the tab character (ascii 0x9, unicode u0009)! Different people use different tab settings, and code that looks just fine with a tab width of 2 becomes illegible with a tab width of 8. Unfortunately, many text editing programs will stick in tab characters without making it obvious that they're doing it. If you use emacs for text editing (which we recommend) put this in your .emacs file:
(setq java-mode-hook '(lambda () (progn (set-variable 'indent-tabs-mode nil) ;; other customizations, if any, go here )))When you hit the tab key while editing java code in emacs, it will automatically indent the code to a reasonable point on the line. When you put the preceding code (which is emacs-lisp code, but never mind that) into your .emacs file, it will make sure that hitting the tab key doesn't actually put any tab characters in your code, but instead just puts in spaces.
Use a single space to separate variable names from operators, i.e. write
a = b + c * d;instead of
a=b+c*d;The only exception to this rule is for array subscripts e.g.
b = a[i-1] // not a[i - 1]but you can put the spaces in here too if you want. Unfortunately the style checker currently complains if you don't put the spaces in. Don't worry about the warning in this case.
Always put a space after a comma. There are no exceptions to this rule.
If you are using a formatting style where the opening curly brace of a block is on the same line as an if, while, or for statement, make sure that there is a space between the close paren on the line and the open curly brace, e.g. do
for (i = 0; i < n; i++) { // code goes here }instead of:
for (i = 0; i < n; i++){ // code goes here }because the latter is hard to read. Similarly, leave a space between an else keyword and an opening curly brace if they're on the same line (also before the else if there's a close curly brace before it).
Don't write lines that are longer than 78 characters long. Long lines tend to be wrapped, or worse, to be truncated when printing out the source. Printing out source code is a valuable way to review your code. It is almost never necessary to have long lines, even for long strings; you can always break up a string like this:
System.out.println("this is a really, really, really, " + "really, really, really, really, " + "really, really, really, really, " + "really long string.\n");
Avoid putting a large number into a file which has no obvious relevance to the surrounding code. This is known as a "magic number" and is often found when setting the size of arrays, e.g.:
int my_array[4096]; // 4096 is a magic numberThe reason for avoiding this is twofold:
The right thing to do is usually to define a class-specific constant like this:
class Foo { public static final int BUFSIZE = 4096; ... void someMethod() { int my_array[BUFSIZE]; // ... } }Note that because
BUFSIZE
is public
, you can use it
outside the class as Foo.BUFSIZE
. The final
declaration means that you can't change the value of BUFSIZE
once it's assigned to.
Do not put in code that has no function or no effect. If it is debugging code, it should be clearly marked as such. It's OK to leave debugging code in, but please comment it out.
If a program is called with incorrect arguments, it should detect that and print a usage statement to the terminal. The usage statement should include the program name:
class MyClass { public static void main(String[] args) { // Here we assume that the program takes two arguments, // representing an input and an output filename; // substitute as necessary for your program. // Also substitute the class name as necessary. String usage = "usage: java MyClass input_filename output_filename\n"; if (args.length != 2) { System.err.println(usage); return; } // ... } }Note that the names of the arguments in the usage function are mnemonic names. Don't write the usage message multiple times. Note also that the
args
array doesn't include "java MyClass"; it starts after
that.
Also, make sure that you and print to System.err
(the error
output stream) instead of System.out
which prints to the normal
output stream. Normally, both print to the terminal, but they can be
independently redirected by your shell.
As a general rule, any error that involves the user supplying invalid command-line arguments should give rise to a usage statement like the ones described above. You should try to make your usage statements comprehensive enough so that one statement will work for all such errors. If necessary, you can include an additional message with information about a specific error that occurred, but always include the usage statement as well.
Never put more than one statement on a line. It makes for unreadable code. So instead of this:
i = 1; j = 2; k = 3;do this:
i = 1; j = 2; k = 3;Some programmers seem to get some kind of perverse thrill out of cramming as much code as possible on a single line. If you are like this, please outgrow this habit; it makes life miserable for anyone unlucky enough to have to maintain your code later.
Use parentheses to show operator precedence in all cases except that of multiplication/division over addition/subtraction and assignment statements.
Do not put large numbers of empty lines (> 2) between code sections unless there is a clear need to distinguish different sections of the code. Conversely, do put an empty line between logical sections in a single function. An example of this is between the type declarations and the first line of actual code. Another example is at the end of a block in curly braces (though this is a judgment call). Long functions that have no blank lines in them are really hard to read.
Use curly braces for the body of all if statements, even if the body
is only a single statement. Do the same for else, else if,
for, and while statements. The reason for this is twofold:
first, it makes the code more readable, and second, it makes it easier to add
System.out.println
statements for debugging in the body of the
expression (which you will frequently have to do).
If you are using a formatting style where the curly braces of a block are on a separate line (which we encourage), make sure that the column of the curly braces match e.g. do this:
for (i = 0; i < n; i++) { // code goes here }instead of:
for (i = 0; i < n; i++) { // code goes here } // braces don't line up
Don't put code on the same line as an open curly brace. For instance, this is bad:
if (a != 0) { a = b + c; // ugly printf("a is now: %d\n"); }Keep the curly braces on their own lines; this makes the code easier to read. Unfortunately, you often see code written like that in books about programming; the reason is that they have to cram as much code as possible onto a single page. You don't. Instead, write this as:
if (a != 0) { a = b + c; printf("a is now: %d\n"); }
Do not put an entire block on a single line, and most especially do not put it on the same lines as an if, while, for etc. E.g. change
if (i < 10) { break; }to
if (i < 10) { break; }
Lines within a block should be indented relative to lines outside a block.
Lines at the same level of a block should start at the same column.
Do not try to do complex calculations in the testing or increment parts of for loops. Don't try to impress me with how clever you are; clever code is a maintenance disaster.
Make variable names descriptive as much as possible; avoid one or two character names unless it's for something trivial like a loop index. It's perfectly OK (and usually desirable) to have longer descriptive names for variables. When you do this with names that are actually multiple words, use one of two conventions:
Either convention is OK as long as you're consistent. Normal java style is to use the capwords convention.
The normal java convention for class and method names is to use the capwords convention as follows:
likeThis
LikeThis
This is the single most common style mistake. If a comment is a phrase or sentence, its first word should be capitalized, unless it is an identifier that begins with a lower case letter (never alter the case of identifiers!), and it should end in a period. We prefer comments that are complete sentences. You should use two spaces after a sentence-ending period.
Bad:
// go through the loop and make sure that all the array elements // have been set to zeroGood:
// Go through the loop and make sure that all the array elements // have been set to zero.That wasn't so hard, was it?
When you need to refer to identifiers, put them in surrounding single quotes, e.g.
// The variable 'nitems' represents the number of items in the stack.
If a comment is very short, it doesn't have to be a full sentence or end in a period e.g.
int i = 1; // loop indexThis is called an "inline comment". Use these only when describing something i.e. in the above code snippet you're saying "The variable 'i' represents a loop index."
Comments should be grammatically correct. In particular, incorrect spelling is unacceptable. We hate to sound like your high school English teacher, but it's a pain to read code with tons of spelling mistakes. Use a spell checker if you have to.
Put a space after the open-comment symbol and before the close-comment symbol i.e. do this:
// This is a comment that is easy to read.and not this:
//This is a comment that is harder to read.This is also incredibly common, for reasons that escape me.
If your comment is at the beginning of a class or method and explains what the class or method is for, use the "documentation comment" style:
/** * This is a documentation comment. * This class/method does blah blah blah... */These kinds of comments can be automatically extracted from your code by various tools, and can serve as documentation for other people who want to use your code without having to read every line. You should almost always put a documentation-style comment immediately before each method describing what it does, what arguments it takes, what it returns, etc. The only exception to this rule is when the method is extremely trivial (e.g. an accessor method) or when you have a series of very similar functions which are written out one after another, and where the first comment applies (suitably modified) to all of them. Use documentation-style comments ONLY for this kind of comment. Also write a similar comment before the class as a whole.
See this page for more information on how to write documentation comments.
This kind of comment is by far the most important kind of comment, because even if the person reading your code has no idea how a given class or method works, the comment will at least tell him/her what it does and how to use it. You may also want to describe the algorithm used, its efficiency, and any other relevant factoids. An example:
/** * IntArrayAlgorithm * * This class includes several useful algorithms that operate on * arrays of integers. * */ public class IntArrayAlgorithm { /** * bubble_sort: * This method takes an array and sorts it using the bubble * sort algorithm. This algorithm has a time complexity of O(n^2) * where 'n' is the size of the array, which is not very efficient. * Therefore, for large arrays use a more efficient algorithm such as * quicksort. * * @param arr The array to be sorted. * @return A new array which contains the same elements as the * original array, but sorted. The original array is * not modified. * */ public static int[] bubble_sort(int[] arr) { /* code */ } }Notice the tags "@param" and "@return" for arguments and return value respectively. There are several other tags that can be used; see this page for a full description of these. We only insist on "@param" and "@return", although "@throws" or "@exception" for methods that throw exceptions is also desirable.
Block comments generally apply to some (or all) code that follows them, and
are indented to the same level as that code. Each line of a block comment
starts with a //
and a single space (unless it is indented text
inside the comment). Paragraphs inside a block comment are separated by a
line containing a single //
. Block comments are best surrounded
by a blank line above and below them (or two lines above and a single line
below for a block comment at the start of a a new section or function
definition). We always like to start and end a block comment with a line
containing a single //
; this is a matter of personal
preference. In other words, a block comment looks like this:
// // The first line comes after an empty line. // // Separate paragraphs are also separated by an empty line, // and there's an empty line at the end. //
Write comments for anything that isn't completely obvious from the context. In particular, write comments for any tricky algorithm or code you are using. When in doubt, comment more rather than less.
Conversely, don't make completely redundant comments, e.g.
i = 1; // Set i to 1.What constitutes redundancy is often a judgment call. If in doubt, comment more rather than less.
Don't make meaningless comments e.g.
// i i = 1;Don't laugh; I've actually seen this sort of thing.
Comments that contradict the code are worse than no comments. ALWAYS MAKE A PRIORITY OF KEEPING THE COMMENTS UP-TO-DATE WHEN THE CODE CHANGES!
Always indent your comments to the same degree as the surrounding code.
Try to line up inline comments where convenient. In other words, don't do this:
x = x + 1 // some cool comment about x y = y + 1 // some even cooler comment about yInstead, do this:
x = x + 1 // some cool comment about x y = y + 1 // some even cooler comment about y
Do not write comments that apply to the preceding code if you can possibly avoid it. Try to write comments that refer to the current line of code or to the lines of code which immediately follow. For instance, this is bad:
int res; // 'res' contains the result of the program. It will normally be 0, // unless an error occurs, in which case it will be 1.and this is good:
// 'res' contains the result of the program. It will normally be 0, // unless an error occurs, in which case it will be 1. int res;
Please separate your method definitions by at least two blank lines. Otherwise it's hard to find where a method definition begins.
Start the line that begins a method one indent level in from column 0, which is generally column 4.