Java Notes: Programming Style Guideline

Contents

  1. Motivation for programming guidelines
  2. Comments, indentation, spacing, braces, ...
  3. Naming conventions
  4. Methods
  5. Error Handling and Exceptions
  6. Visibility and storage type
  7. GUI Design
  8. Object-Oriented Programming
  9. Misc.
  10. References

1. Motivation for programming guidelines

Maintainability. If there's one idea that could serve as a guide to good programming, it's maintainability.

Low cost and more fun. Most of the cost of software, 80% is a frequently used number, is in the maintenance phase: fixing bugs, adding enhancements, adapting it to new systems, etc. That would be a good enough reason to aim for maintainability, but that's not really why I'm saying it. The same things that make software maintainable also make it easier and more pleasant to work on in the first place. Sometimes it takes a few extra key strokes or an extra moment of thought, but those are usually quickly repaid.

If a program is useful, it has to be changed!

If a program is useful, users want enhancements, bug fixes, etc. It's also necessary to update programs regularly because the computing environment continuously changes.

Someone has to change them, and surprisingly often, it isn't the original programmer. Therefore, one of the most important characteristics of real programs is that they must be readable and have a style that allows changes.

Factors. Three topics that cover a lot of the maintainability territory are:

  1. Readability - There is an astounding range of readability. Always keep it in mind.
  2. Simplicity - Don't add unnecessary complication and duplication. KISS.
  3. Convention - Program using standard conventions as much as possible. In addition to standard conventions, you may have some conventions of your own. Be consistent in the use of these conventions. See RH story.

2. Comments, indentation, spacing, etc

Comments

Header Comments

Put comments at top of each source file; include:

  • Name and purpose of the program. Identify the class and assignment, and what the program does. A single line is sufficient for most student programs. If you write a program that is not a fixed assignment, the documentation will have to be much more extensive.
  • Your name.
  • Date.

This information should be included at a minimum. The format is flexible.

"Paragraph" comments

Statements are should divided into clear sections (like paragraphs), separated by a blank line, and a comment at the beginning telling what this "paragraph" does. Put the comments at the beginning or on the statements they apply to, not at the end of the section.

Avoid useless comments

Don't write comments unless they help explain why something is being done, or explain something that is not immediately obvious to the reader. Just paraphrasing the action of the Java statement makes the program harder to read. For example, the following comment is very bad, even tho it is a true statement.

area = width * length;  // Multiple width by length to compute area.  BAD COMMENT
Document "tricks"
Document any tricky lines of code.
Space methods, inner classes, etc
Put lines between between major elements (methods, classes, etc) of a program.
Line length and continued statements
Some advise that source lines shouldn't be longer than 80 characters. This may appear to be a legacy from 80 column punched cards, but practical advice for printing in portrait mode on US letter or A4 (slightly narrower) paper. For printing, you can always use landscape mode, but this may not be a solution if you need to show the code on a web page.

No horizontal scrolling. You must not have lines longer than the width of the IDE editor window.

Double indent continued lines. When you continue a long statement onto the next line, use two indent levels for the continued part so it doesn't look like a following statement. I often break the statement at a point where the first character of the continuation will be something that can not start a statement (like a "," or "+") so the reader can immediately see that it's a continuation.

Use javadoc for big programs
For larger programs, the systematic use of javadoc style comments is necessary.

Indentation

Programmers universally agree that good indentation is required.

Indent size 4
Four spaces are probably the best choice for each indentation level. Programmers use 2, 3, or 4 spaces for indentation, but 4 is the most common and the most readable.
Blanks, not tabs
Use multiple blanks instead of tabs. Because there is no fixed specification of how big a tab is, when someone else looks at your program on their system, the alignment of statements is often quite different (and wrong). You would think that relative indentation would be preserved, but in practice the indentation is usually a mix of spaces and tabs, and the result is bad. Some editors, like NetBean's editor, has a reformat source command that will fix everything. Many text editors have a "soft tab" option which replaces tabs by blanks. Use it if you have it.
Use an IDE
Statements must be indented correctly. Every experienced programmer insists on this. Good IDEs perform will clean up the indentation with the click of a button.
Continued statements
Statements that must be continued over more than one line should indent the continued part two indentations.

Spaces and newlines

There are standard ways to use white space (blanks, and newlines) to make programs easier to read.

Method calls and keywords, and the left parenthesis
  • No space between method name and the "(". Eg, "y = f(x)", not "y = f (x)".
  • One space between keywords and "(". Eg, "if (a < b)", not "if(a < b)".
Spaces in expressions
I've seen a number of rules about spaces in expressions. Use them to make expressions more readable. More specific guidance is needed here.
Aligning adjacent statement parts
Readability is often improved by aligning elements in related, adjacent statements. For example,
int x = 0;   // Horizontal coordinate.
int y = 0;   // Vertical coordinate.
int width = 100;  // Width of method box.
String text = "(default)";  // Initial text to display in box.

Improve the readability by aligning one or more of: variable name, the "=" and the "//".

int    x      = 0;      // Horizontal coordinate.
int    y      = 0;      // Vertical coordinate.
int    height = 100;    // Width of method box.
String text   = "main;  // Default method name to display in box.

Declarations

Declare local variables (1) at first use or (2) at front with comments.

There are two good styles for declaring variables, and one bad style.

  • Good. Declaring variables when they are first used.
  • Good. Declaring variables at the beginning, one per line, with comments. This style is only useful if you have a story to tell about the variable.
One variable declaration per line

Putting as many variables as you can on a line saves space (good), but at the expense of readability (bad). Variables declared on their individual lines are easier for a programmer to find, and allow writing a brief common following them. For example,

// Poor style -- No information about the variables, and hard to find them.
int averageRain, n, currentVal, max;

Might better be written as follows

int averageRain;   // Average rainfall over all time periods.
int n;             // Number of time periods.
int currentVal;    // Amount of rain in the current time period.
int max;           // Maximum rain in any time period.

If you're not going to explain a variable, and if the names are good, it's not always necessary to comment them, you should simply declare them at the first use. There's no reason to spread out the references more than necesarily.

One per line
Declaring one variable per line allows you to add // comments to variables whose meaning isn't clear from their names, or where their range of values is important to understand, or there is something else important to know about the variable. Textbook authors are under pressure to reduce the length of their programs so sometimes compress their declarations on one line. This is not good style and all coding standards want one declaration per line.
Declare instance variables near front of class.
You can declare instance variables (fields) anywhere in a class, but almost all programmers declare them at the front of the class. Use this convention. One well-known author likes to declare them at the end of the class, but this is not natural for more programmers.
Declare local variables where they are first used.
You may see advice that local variables should be declared at the beginning of a method. Some older languages required this style, which is perhaps the origin of this rule in the Sun programming guidelines.

Minimize distance between declaration and use. It is easier to read code if the distance between declaration and use is minimized. This argues for declaring variables at their first use.

Innermost scope. Generally variables should be declared in the block that they are used it, not in a block outside that. Making them visible outside invites accidentally referencing them outside. This is why a for loop variable should be declared in the loop header if its value isn't need after the loop terminates. All local variables are allocated when a method is entered, even if they are in an inner block, so there is no extra allocation cost when repeatedly entering a local block as is sometimes mistakenly claimed. Of course, if a variable is assigned in an inner block, but used later in an outer block, it's necessary to declare it first at the outer level.

See Programming in the small - variable declarations (ivan.truemesh.com/archives/000596.html) for a discussion of this. Another discussion can be found at http://www.javapractices.com/Topic126.cjp Don't declare local variables before use.

Don't reuse variable names
Never use a variable for more than one purpose. New variables are are basically immeasurably cheap in terms resources (CPU and memory), so don't make the program hard to read by reusing one for another purpose.

Braces to group statements

Always use braces, even for one statement
Braces should always be used to enclose the bodies of the control flow statements, even if there is only one statement in the scope. This is a common rule. The reason is that the it's more error prone and harder to read if the use of braces is erratic. There are cases where this might be violated, but they should be few.
K&R or Allman style
Sun's guidelines specify K&R style braces (opening brace on end of statement), but the Allman style (opening brace directly below first character of statement) is also OK. Beginning programmers often like the Allman style better because it's easier to match beginning and end. Experienced programmers often prefer the K&R style because more of the program is visible on the screen/page and the visually disruptive blank line doesn't separate the if from the true clause. Many IDEs (eg, NetBeans) will indent the program either way for you.

Wikipedia has a good summary of indentation styles: Indent style.

3. Naming conventions

Naming is perhaps the single biggest contributor to readability.

Names should be meaningful
. Don't use meaningless or misleading names. Certain short names are used by convention in loops. Eg, i and j for integer counters/indexes, iter for iterators, s for string value in an extended for loop, etc.

If names are well chosen, comments aren't so important.

Don't use Main as your class name, even tho NetBeans defaults to it.

Classes are nouns; methods are verbs
Generally classes represent nouns, so should have a noun-like names. Method names are usually verb-like.
Case
  • Start with lower case, continue in camel case : variables, methods, packages. Eg, fishWeight.
  • Start with upper case, continue in camel case : classes, interfaces. Eg, FishCalculator.
  • All upper case, separate words with underscore : constants. Eg, MINIMUM_FISH_SIZE. See Evan Summer's blog entry A Case Against Uppercase for a counter opinion.
Instance variable prefixes
Prefixes are commonly used to distinguish them from other local/class variables. Typical choices are ("_", "i", "m", "m_", or "f"). Other terms for instance variables are member variables or fields, hence the use of those letters. I often use "_", altho this is sometimes criticised as violating the Java standard. Don't get too attached to one special way - if you go to work for an organization, they often have a rule about naming instance variables, and you'll have to use that rule.
Plural names for arrays, collections, ...
Use plural names, or names that stand for a collection of things, for arrays and other data structures. This makes them easier to identify in code.
Parameter names
Method and constructor parmamters are essentially implemented as local variables, but with a preinitialized value, and conventionally programmers use the same naming conventions for parameters.

Prefix "p"? Because it's good to know that a variable is a parameter, an argument can be made that the names should look different to make that obvious. The most common convention, and it's not very common, that I've seen is to prefix parameters with "p" and uppercase the next letter (eg, "pName", "pAddress", ...). I haven't used this, but it's quite a plausible idea.

In, out, inout. A convention what was popular earlier was to indicate how each parameter is used with one of three keywords: "in" means the value of the parameter is used and not changed, "out" means the value is changed and not used, and "inout" means that the value is used and changed. Most programming languages don't support these keywords, and the practice of adding a comment to each parameter declaration was too cumbersome so most programmers and textbooks have stopped using it.

In this spirit Andrew Meyenn has suggested suffixing parameter names with "In", "Out", or "InOut" (I thing he prefers all capitals), which is another very interesting idea. Because almost all parameters are "in" parameters, it might be more interesting to only mark the uncommon cases: "out" and "inout".

Unused. Another convention is to give a special name to parameters which are not used. You might wonder why there are such parameters, but sometimes implementations have changed so that a parameter is no longer needed but the code that calls the method can't be changed. Or perhaps someone else is calling your code and supplies values that you don't need. I've seen the name "unused" or "ignored" used for such parameters. For example, the main methods's args parameter is rarely used. Using "unused" instead of "args" for the normal case would alert the reader when they saw "args".

    public static void main(String[] unused)

4. Methods

Method overloading

5. Error Handling and Exceptions

"Happy Trails" Programming

Real world programs must handle problem cases, such as illegal input, but beginning students may ignore problem cases unless specifically required to do so. The more advanced the course, the more emphasis is put on handling errors.

Error checking

5. Visibility and storage type

The general rule is that variables should be private, and methods public. That's a good starting point.

Static/class
Other than constants (static final), you should rarely have static variables. Static methods are appropriate if they don't depend on instance variables.
Instance
Instance variables should almost always be declared private, or perhaps protected.
Local variables
should be used instead of an instance variable if they work just as well. Local variables are visible only within the method they are defined in.

6. GUI Design

Look at typical user interfaces
You will see how they are arranged. Most programs use a standard system of grid, gaps, subpanels, and borders.
Window borders
An empty border is almost always appropriate around a window. When you drag components near the edge, NetBeans will automatically suggest a good placement.
Gaps
As with borders, NetBeans will suggest reasonable gaps between elements. Gaps between components are typically about 5 pixels, Between separate logical groups the gap should be larger.
Variable grid design
A typical design technique is to use a grid of rows and columns. Each row and column can be a different size, but all elements in a given row will be the same size, and similarly for columns. Elements may span several rows/columns (like rowspan or colspan if you know HTML).
Subpanels
Not only does the use of subpanels help layout related components, but the subpanels can easily be moved around to make the window layout easy to change. Sometimes a titled border on subpanels can make them more useful to the user.
Expandable
If the design contains elements that should naturally expand, please make sure they expand correctly.
More help
  • Sun has put their Java Look and Feel Design Guidelines (2nd Edition) book online at java.sun.com/products/jlf/ed2/book/. The Chapter 4 Layout and Visual Alignment section is very useful. Similar guidelines are available from Microsoft and Apple.
  • A good book is GUI Bloopers: Don'ts and Do's for Software Developers and Web Designers by Jeff Johnson.
  • NetBeans has some good tutorials on the use of their GUI editor. Take a look at www.netbeans.org/community/releases/50/index.html. There are links to tutorials on several other pages too, so you might want to navigate around a bit.

7. Object-Oriented Programming

  1. Don't have an empty constructor. NetBeans automatically creates a constructor when you define a new Java class. If you don't need a constructor, just erase this default, empty constructor.
  2. Don't use instance variables when local variables would do.
  3. Don't make everything a class. If a primitive value is adequate, you don't have to define a class that holds it; you can just use the primitive value.
  4. If you have a class that has no methods other than getters and setters, you should question it's existence. It may be valid as a so-called "value" class, a class that is just used to represent a value. For example, you might have a value class for an Address. But perhaps there are operations that are being performed on it that should be moved into the class.
  5. Interface specifies minimum. When you write a class that implements an interface, the interface specifies the minimum number of methods that need to be implemented, not the maximum. Add other public methods to the class if you want to extend the functionality. If there is a specified interface, then others will very likely only use the methods of that interface and won't have access to the extensions, but that shouldn't be a problem.

    It's also sometimes useful to define additional private utility methods in the class. Additional methods don't conflict with the implementation of an interface.

  6. Liskov Substitution Principle states that all method of a superclass should be available when using an object of that subclass. That is, a subclass can override or add behavior, but must not remove behavior.

8. Misc

  1. DRY (Don't Repeat Yourself) / Once and only Once
    DRY - the small version. If you have several copies of the same (or nearly identical) code, you have violated the DRY principle -- Don't Repeat Yourself.

    Having multiple copies of code is an accident waiting to happen when the code is updated.

    You can typically solve this by writing a loop, method, or some other technique. Related to A good programmer is a lazy programmer.

    DRY - the bigger principle. The idea is not just to have only one copy of code, but to have only one place where a feature, value, etc is represented or implemented. This allows changes to be made in one place. It's about orthogonal programming and reducing coupling. Read more in the interview with Andy Hunt and Dave Thomas at Orthogonality and the DRY Principle. They're the authors of the "DRY" acronym, but the idea has been around for a long time. See also the Wikipedia article Don't repeat yourself and Ward Cunningham's Dont Repeat Yourself.

    Once and only once is another way of saying pretty much the same thing. See Once And Only Once at c2.com.

  2. See No magic numbers - use named constants.
  3. Make conversions explicit -- don't rely on implicit conversions. Implicit conversions may work, but the reader may not believe you know what you're doing.

Optimization

9. References