Coding Style
Introduction
When writing a computer program it is important to keep in mind that
the program should not only run correctly, but also be written in a clear
way so that other people can understand it. A program that "works" is not
necessarily a good program; A good program is a program that is written
in a comprehensible, modular, and readable style. For a small program such
as the ones you write in your first steps, the way in which the program
is written may seem unimportant and meticulous. However, in real life programmers
often work as part of a group on a program of hundreds of thousands of
lines. Moreover, the life-cycle of a program is usually long and the program
should be maintained long after its original creators have left the project.
As a result a programmer often finds herself maintaining a program
of thousands of lines written by several generations of programmers she
is not familiar with. Understanding a computer program written by another
person is always a hard task, but if the program is written in poor style
the task is best described as a nightmare.
Most programmers would define 'style' as the things which relate to
the appearence of the program, or in other words, how the program "looks":
the naming of the various entities in the program (variables, classes,
methods, etc.), the documentation and comments that appear in the program,
the indentation that is used in the program, and other technical details
which relate to the structure of the program. It would perhaps be better
to think about style as "the things in a program which a compiler doesn't
really care about - but (most) programmers really do". Whether or not
you chose the best name for your variable, added documentation, or indented
your program - the compiler would be tolerant. Other programmers (and -
believe it or not - even you, when you re-encounter your good old code)
would definetly not.
The intention of this document is to present you with several guidelines
that (we hope) will give you good programming style habits. You should
keep in mind one thing: as the old jewish joke goes, if you ask 100 programmers
to define their style guidelines, you'll get 100 (and perhaps even more
than 100) different opinions. Well, the situation is not that liberal,
but there's one golden rule about style: being consistent. If you
decide upon a certain style scheme (and as a beginner we don't leave you
much choice in deciding), use this scheme throughout your program, and
maintain it throughout every program you write. It would have been nice
if all programmers would have agreed upon style conventions, but as we
have argued, this is not always possible. C++ programs, for example, have
a wide variety of style conventions, depending on the literature and education
the programmer has been raised upon. The great thing about Java, is that
an agreed upon convention (or at least a minimal set of conventions) had
quickly evolved. These conventions are adpoted by most Java programmers
(and originate at the book The Java Language Specification
by
Gosling, Joy and Steele.)
Indentation
Read the discussion about white space characters in Lewis & Loftus
p. 36.
The purpose of indentation is to emphasise the structure of the program
- its division into blocks.
We recommend the following indentation rules:
-
Use tab spaces of 4 characters
-
The brackets ({) opening a block are placed
at the same line of the statement or method that open this block
-
The closing brackets (}) are placed at the
same column as the beginning of the statement/method declaration that opens
the block
-
The content of the block always starts at a new line, shifted one tab (4
chars) to the right
Class
Names
Picking up good names for your program elements (classes, methods, variables,
...) is a very important part of the documentation of your program. A good
name for a class is the fastest way to describe what the class used for.
Naming is particularly important for classes, because often people will
use your classes as a whole (without looking in their implementation).
If the names of your classes are not well chosen, it will be difficult
to find the class, understand the relationship between the different classes
the program consists of, and to remember the name of the class when it
is needed.
For many of the exercises, we will tell you the name of the classes
you should use (we must have consistent names to enable automatic checking
of the exercises, and this is also true in real-life programming). However,
it is important that you should be aware of the guidelines for naming classes
and you will need them for some of the exercises.
Here are several rules for naming classes:
-
Class names must always begin with a capital letter: Lincoln,
Pentagon, Bucket, Bulb.
-
If the name of the class consists of several words, they should be written
in a mixed form: OutputWindow, InputRequestor, QuadraticFunction.
The first letter of each word is written as uppercase and the other as
lowercase.
Important: the course
book uses a different convention for class names consisting of several
words: there the words are separated by a '_' (e.g. Input_Requestor
instead of InputRequestor). The widespread
convention is different.
-
Don't use the characters '$' and '_' in class names, they have special
use in Java.
-
The name of the class must be meaningful. It should describe the use of
this class. It is helpful to have a real-world analogy for the class and
use its name as the name of the class.
Positive example: InputRequestor
represents an object that requests input from the user.
Negative examples: IRqst is
not meaningful whatever the class is used for.
-
The name should be a combination of words in English. Do
not use Hebrew words in your names - Java is meant to used as an Internet
programming langauge which will enable class sharing across the network.
Imagine your friend in Kamchatka trying to figure out what KoreNetunim.class
is...
Positive examples: Knight, Employee.
Negative examples: Sus, Oved.
-
It is best to use short class names when they express exactly what you
want to express (for example it is better to use RoundButton
than AButtonWhoseShapeIsRound). However,
you should not force the name to be short if the shorter name loses its
meaning. For example ElectronicGate
is better than Gate, because another
person will not be sure to which one of the concepts you are referring
to (see also the note about abbreviations below). Don't be afraid of typing
long names (use cut and paste). Just for illustration look at the name
ArrayIndexOutOfBoundsException
from the Java API (it is not the longest, there are longer names in Swing).
-
As a rule don't use abbreviations. There is only one way to write
the full name of something, and there are many more ways to write abbreviations.
If you use abbreviations you (and surely someone else) will never remember
which abbreviation you've used. For example use the name MessageHeaderAttribute
and not MsgHeadAtr, MsgHAttr,
MsgHdrAttrib,
or whatever. This rule has as exception; there are some abbreviations which
are so common in general, and in computer world in particular, that they
are almost taken as the actual words. For example - min, max, temp are
considered as words and are accepted as part of names. For example TemporaryFile
vs. TempFile, both are ok (only be
consistent!).
-
You can use acronyms when they are very well known ones. For example, it
is better to use TCPConnectionHandler
than TransportLayerProtocolConnectionHandler.
If you are designing a package and there is a common concept appearing
in many of your classes you can consider to invent a new acronym for it.
Be sure to emphasis this in your documentation.
-
Use a dictionary while programming. Programming is yet another way of communication,
and style is important here as in spoken languages.
Variable
Names
-
Variable names in Java always start with a lowercase letter. Examples:
size, width, turtle, output
-
If a variable name consists of several words, it should be written in a
mixed form where the first letter is a lowercase, every first letter from
any of the additional words is written as an uppercase, and the other letters
are lowercased. Examples:
numberOfElements, currentTime, rightmostPoint
-
Important: as in class names, the textbook
uses a different convention, but we stick to the Java conventions.
The rules for meaningfulness of class names apply also for variables. There
are several additional notes.
-
Don't use the characters '$' and '_' in variable names, they have special
use in Java (in inner classes and JNI).
-
In some cases it is ok (and even desirable) to use a single letter name
for a variable. For example if a method computes the factorial of a number,
the name of the parameter (a type of variable) it receives can be called
n.
It makes sense because factorial is an arithmetical function, and in mathematics
we are used to denote the argument of an arithmetical function by n.
Choosing a longer name would be useless - surely number
or
argument is not any better. Similarly
the name of a method for computing sin would be x,
and the arguments of a method for computing the greatest common divisor
of two numbers can be a and b.
This applies not only for mathematical functions. Using single letter variable
is usually appropriate inside a short method that involves few variables
of the same type and there is no other meaningful names for them. For example
in a method that does operations on 3 buckets the buckets can be named
a,
b and c
rather than bucket1,
bucket2
and bucket3 (which is also fine).
-
The variable name i is usually used
for loop counters.
for (int i=0; i<salaries.length; i++) {
salariesSum += salaries[i];
}
When using an outer and inner loop often the variables i
and j are used.
If the loop variable is used only as an index and has no other special
meaning, it is preferable to use the conventional names i
and j. In some cases you would want
to use other names. For example if you go over the pixels of an image,
you might use the variables x, y
instead of i, j.
row, column is another example.
-
For constants (final variables) use all capital letters seperated with
an underscore between words. Example: MAX_LENGTH
Methods
-
We use the same conventions for method names as for variable names.
-
A method should not be very long. The preferable size of a method is 5-20
lines of code. A method of 35-40 lines is too long. The only exceptions
to this rule are method that consists of a switch statement with many cases
(in which case each case should be at most 1-5 lines) or methods for defining
a GUI appearance.
-
When a method of yours become too long, consider dividing it into several
methods.
-
Each method should have a (single) well defined role. If you cannot describe
the functionality of the method in a single short sentence, it is an indication
that the role of the method is not clear to you and that you should change
your division into methods.
-
If you use the word 'and' in your description of the method or in the method
name, it is an indication that you should divide the method into two.
-
Don't be afraid of very short methods. A method of 1 or 2 lines is perfectly
OK if it has a well defined role. Often you have a code segment that appears
in many places of your program which is very short; in such a case define
a method for this code segment.
-
Avoid methods that receive too many parameters. Methods should normally
have 0-4 parameters. If you declare methods with too many parameters it
is hard to remember which parameters the method gets and in which order.
Lots of parameters are often an indication that the method does too much
and should be divided into several methods. If a method must get many parameters,
consider defining an object that encapsulates all the information the method
should get. Use such an object only if you have a clear notion of what
it represents.
-
Like methods, constructors should not have too many parameters. If you
need to specify a lot of information for the creation of an object, you
can give the important information in the parameters of the constructor
and the rest in setter methods.
Implementation
Comments
There are two types of comments in Java: implementation comments
and documentation comments.
Implementation comments are intended for the programmer who maintain the
code, he/she needs to understand how does the code work. Documentation
comments on the other hand, are intended for programmers who want to use
the code as a whole. They are not interested in understanding the inter
working of the code.
There are 3 forms for writing comments in Java:
-
In-line comments: the text from the // symbol till the end of
the text line is a comment. In-line comments are usually used to describe
the use of a variable you declare or to give a short explanation for an
unusual statement.
-
Block comments: the text between the opening /* symbol and until
the closing */ symbol is a comment. Block comments can spread
across lines. Block comments are usually used to describe a section of
code that needs clarification and for temporary hiding of code while debugging.
-
Documentation comments: the text between the opening /** symbol
and until the closing */ symbol is a documentation comment. We
discuss documentation comments later.
Here are some guidelines about implementation comments (some of the guidelines
below are taken from Lewis J. & Lottus W. / "Java software
solutions" pp. 605):
-
Write all documentation as if the reader is computer literate and is familiar
with the Java language. The documentation in the examples below is redundant
because it just explains the statement in words and adds no extra information
for the reader who understands Java:
if (a>b) { // if a is greater than b ...
//
this loop will be executed while the stopping flag is true
while
(stopFlag != true) {
// ...
}
-
Add a comment only if it contributes to the understanding
of the code. Keep in mind that in a good program, the code is obvious.
Do
comment tricky parts, things that are not apparent at first glance, and
any other fact you think would be useful to understanding the code or maintaining
it in the future.
-
Assume the reader knows almost nothing about what the program is supposed
to do. Remember that a section of code that seems intuitive to you when
you write it might not seem intuitive to another reader or to yourself
later.
-
Your comments must be accurate. Otherwise the comment can do more damage
than help. If a comment stop from being accurate because a change is made
to the source code, remove the comment or correct at once.
-
Use simple language while documenting. It is always easier to read something
written in a simple language. Remember that the readers of your code may
know only basic english.
-
Every method should have a comment block describing the method. If the
method is part of the interface of the class (it is public or protected)
you should use a documentation comment, otherwise use an implementation
comment.
-
If you have a method which is not simple and requires massive explanation,
try to put all the explanation in one block at the beginning of the method.
It is easier to understand the explanation as a whole and the code as a
whole.
Documentation
Comments
Documentation Comments are special Java comments used to describe the
API of a class or an
interface. Documentation Comments can appear before each class or interface
declaration and
before each method, constructor or field declaration. A documentation
comment begins with /**
and ends with */. Below is an example of a class definition
which includes documentation
comments.
/**
* A FIFO queue that can hold arbitrary objects.
*
* @author Shmulik London
*/
public class Queue {
/**
* Constructs an empty queue.
*/
public Queue() {
// some code here
}
/**
* Inserts an item to the queue.
* @param item The item to be inserted.
*/
public void enque(Object item) {
// some code here
}
// some code here
}
Documentation Comments may include plain text, HTML, and some special tags.
For a detailed
description of Documentation Comments refer to chapter 18 in James
Gosling, Bill Joy, Guy Steele, The Java Language Specification.
For details on using the javadoc
tool for generating automatic API documentation look here.
Documentation Comments are intended for generating API documentation
for your class. This means that they are intended for programmers who wish
to use your class as a whole and need to understand its interface. They
are not intended for the programmer who maintains the code! (for those
we use regular comments) In this sense Documentation Comments in Java have
a similar role as header files (.h files) have in C modules.
Use Documentation Comments only for entities that are part of your class
public interface:
-
Before a class or an interface definition.
-
Before any (and only) public or protected methods. (One way for programmers
to use your class, is by subclassing it; in this case they need to know
how to use its protected methods)
-
Before any (and only) public or protected fields.
The class comment should open with a short sentence describing this class
(its purpose), followed by a more detailed description of the use of the
class. The implementation of the class should not be documented here,
unless it affects the API of the class (in which case you should add a
short note indicating this). If the use of the class is not obvious from
the API, it is recommended to give an example for its use. At the end of
the class documentation block, you should denote yourself as the author
of the class and (if needed) add references to related classes or methods.
Another example:
package games.card_games;
/**
* A Deck of cards. This class is intended for use in card games.
* Each player holds a Deck (or more) of cards containing several
* cards. The content of the Deck changes along the game.
* <P>
* Example:
* <PRE>
* Deck dealerDeck = Deck.createFullDeck();
* dealerDeck.suffle();
* Deck deck1 = new Deck();
* Deck deck1 = new Deck();
* while(!dealerDeck.isEmpty()) {
* deck1.addCard(dealerDeck.drawCard());
* if (!dealerDeck.isEmpty()) {
* deck2.addCard(dealerDeck.drawCard());
* }
* }
* </PRE>
*
* @author <A Href=mailto:londons@cs.huji.ac.il>Shmulik London</A>
* @see games.card_games.Card
* @see games.card_games.BridgePlayer
*/
public class Deck {
// ...
}
Every public and protected method must be preceded with a documentation
comment. The comment should begin with a short sentence describing the
method, ending with a period ('.'). Only the first sentence (until the
period) is displayed in the API's method index. The rest of the comment
appears in the detailed list of methods (together with the first). If the
first sentence is not enough for describing the use of the method, you
can add several sentences of explanations. Explain only what the method
does and NOT how it does it!. Avoid long documentation.
If you cannot describe the method in a single sentence (because it
does more than one thing), it may be a good sign that you should split
it into several methods, or reconsider your design.
// class deck continued
/**
* Adds a card to the top of the deck.
*/
public void addCard(Card card) {
// ...
}
If the method gets more than one parameter or if the role of this variable
is not clear from its name, use the @param tag to document the
parameters of the method. In any case, document all the parameters
in the same order they appear in the method's signature. If two parameters
are related you can document them in the same line.
// part of class Figure
/**
* Constructs a new Figure.
* @param x,y The location of the top-left corner of the Figure.
* @param width, height The dimensions of the Figure.
*/
public Figure(int x, int y, int width, int height) {
// ...
}
When documenting the parameters of a method that is not void (and is not
a constructor), also document its return value with the @return
tag.
Do not worry if the sentence describing the method seems to add no information
(Unless this sentence is not clear) - it probably indicates that your choice
for the name of the method is good (This frequently happens for the constructors
of the class).
// from class Deck
/**
* Shuffles the Deck.
*/
public void shuffle() {
// ...
}
If the method throws an exception (in particular if it is a RuntimeException
you may expect) document the exception with the @exception tag.
// from class Deck
/**
* Draws a card from the top of the Deck.
* @return A card from the top of the Deck
* @exeption DeckEmptyException If the Deck is empty
*/
public Card drawCard() {
// ...
}
In general most of the fields of a class will usually be private. Public
fields make sense if they denote a public constant or they are part of
a class which is a wrapper for several values (such as java.awt.Point).
You should have a reason for defining a field as protected and a good one
for defining it as friendly. In any case before every public or protected
field you must put a short documentation comment. If you cannot describe
the function of the field in one sentence it may be a good indication that
it is not suitable for it to be public or protected (consider an access
method instead). The style of documenting a field is as follows:
/**
* The double value that is closer than any other to pi, the ratio of the
* circumference of a circle to its diameter.
*/
public static double PI = 3.14159265358979323846;