NOTE: This web site is out of date. This is the course web site from a past quarter, Winter 2015. If you are a current student taking the course, this is not your class web site, and you should visit the current class web site instead at http://cs193a.stanford.edu/. If you are already at cs193a.stanford.edu, the web page may not be updated yet for the new quarter. Please be advised that courses change with each new quarter and instructor. Any information on this out-of-date page may not apply to you this quarter.

CS106B Style Guide

These are the general Java style qualities that we expect your programs to have in order to receive full credit. Certainly it is possible to write good code that violates these guidelines, and you may feel free to contact us if you are unclear about or disagree with some of them. But we do expect you to follow these rules (unless there is an error in this document). In most professional work environments you are expected to follow that company's style standards. Learning to carefully obey a style guide, and writing code with a group of other developers where the style is consistent among them, are valuable job skills.

Oracle/Sun's Official Java Coding Conventions are a more comprehensive guide to proper Java programming. The practices outlined on their web site are encouraged for use in CS 106A.

This document is a work in progress.
Last updated Wed 2014/12/24


Whitespace and Indentation
  • Indenting: Increase your indentation by one increment on each brace {, and decrease it once on each closing brace }.

  • Place a line break after every { .

  • Do not place more than one statement on the same line.

    // bad
    int x = 3;  int y = 4;  x++;
    if (a == b) { foo(); }
    
  • Long lines: When any line is longer than 100 characters, break it into two lines by pressing Enter after an operator and resuming on the next line. Indent the trailing second part of the line by two increments (e.g. two tabs). For example:

    int result = reallyLongFunctionOne() + reallyLongFunctionTwo() + 
            reallyLongFunctionThree() + reallyLongFunctionFour();
    
    int result2 = reallyLongFunction(parameterOne, parameterTwo, parameterThree,
            parameterFour, parameterFive, parameterSix);
    
  • Expressions: Place a space between operators and their operands.

    int x = (a + b) * c / d + foo();
    
  • Blank lines: Place a blank line between methods and between groups of statements.

    public void foo() {
        ...
    }
                              // this blank line here
    public void bar() {
        ...
    }
    
Naming and Variables
  • Names: Give variables descriptive names, such as firstName or homeworkScore. Avoid one-letter names like x or c, except for loop counter variables such as i.

  • Capitalization: Name variables and methods with camel-casing likeThis, name classes with Pascal casing LikeThis, and name constants in uppercase LIKE_THIS.

  • Scope: Declare variables in the narrowest possible scope. For example, if a variable is used only inside a specific if statement, declare it inside that if statement rather than at the top of the method or at the top of the class.

  • Types: Choose appropriate data types for your variables. If a given variable can store only integers, give it type int rather than double. Do not declare variables of Java's wrapper types such as Integer or Character; use the corresponding primitive type instead. (A collection such as List<Integer> is okay.)

  • Collections: If you declare a variable or parameter that is a collection, declare it using the ADT interface type, not the specific implementation type.

    ArrayList<String> names = new ArrayList<String>();  // bad
    List<String> names = new ArrayList<String>();  // good
    
  • Generics: If you declare a variable or parameter that is a collection, always write the type of its elements in < >.

    List names = new ArrayList();  // bad
    List<String> names = new ArrayList<String>;  // good
    
  • Constants: If a particular constant value is used frequently in your code, declare it as a final class constant, and always refer to the constant in the rest of your code rather than referring to the corresponding value.

    private static final int DRINKING_AGE = 21;
    
  • Avoid static global variables: Never declare a modifiable static global variable. The only static class variables in your code should be final constants.

    // bad
    private static int veryBad = 42;
    ...
    veryBad++;
    
Basic Java Statements
  • for vs while: Use a for loop when the number of repetitions is known (definite); use a while loop when the number of repetitions is unknown (indefinite).

    // repeat exactly size/2 times
    for (int i = 0; i < size / 2; i++) {
        ...
    }
    
    // repeat until there are no more lines
    while (console.hasNextLine()) {
        ...
    }
    
  • break and continue: In general, you should avoid using the break or continue statements in loops unless absolutely necessary.

  • if/else patterns: When using if/else statements, properly choose between various if and else patterns depending on whether the conditions are related to each other. Avoid redundant or unnecessary if tests.

    // bad
    if (grade >= 90) {
        System.out.println("You got an A!");
    }
    if (grade >= 80 && grade < 90) {
        System.out.println("You got a B!");
    }
    if (grade >= 70 && grade < 80) {
        System.out.println("You got a C!");
    }
    ...
    
    // good
    if (grade >= 90) {
        System.out.println("You got an A!");
    } else if (grade >= 80) {
        System.out.println("You got a B!");
    } else if (grade >= 70) {
        System.out.println("You got a C!");
    }
    ...
    
  • Boolean zen 1: If you have an if/else statement that returns a boolean value based on a test, just directly return the test's result instead.

    // bad
    if (score1 == score2) {
        return true;
    } else {
        return false;
    }
    
    // good
    return score1 == score2;
    
  • Boolean zen 2: Don't ever test whether a boolean value is == or != to true or false.

    // bad
    if (x == true) {
        ...
    } else if (x != true) {
        ...
    }
    
    // good
    if (x) {
        ...
    } else {
        ...
    }
    
  • Exception handling: Don't ever catch an exception with an empty catch block.

    // bad
    try {
        foo();
        bar();
    } catch (NullPointerException npe) {}
    
Redundancy
  • Minimize redundant code: If you repeat the same code two or more times, find a way to remove the redundant code so that it appears only once. For example, place it into a helper method that is called from both places. If the repeated code is nearly but not entirely the same, try making your helper method accept a parameter to represent the differing part.

    // bad
    foo();
    x = 10;
    y++;
    ...
    
    foo();
    x = 15;
    y++;
    
    // good
    helper(10);
    helper(15);
    ...
    
    public void helper(int newX) {
        foo();
        x = newX;
        y++;
    }
    
  • if/else factoring: Move common code out of if/else statements so that it is not repeated.

    // bad
    if (x < y) {
        foo();
        x++;
        System.out.println("hi");
    } else {
        foo();
        y++;
        System.out.println("hi");
    }
    
    // good
    foo();
    if (x < y) {
        x++;
    } else {
        y++;
    }
    System.out.println("hi");
    
  • Method structure: If you have a single method that is very long, break it apart into smaller sub-methods. The definition of "very long" is vague, but let's say a method longer than 40-50 lines is pushing it. If you try to describe the method's purpose and find yourself using the word "and" a lot, that probably means the method does too many things and should be split into sub-methods.

Efficiency
  • Use StringBuilder when creating long strings: When you are going to create a long string (such as the toString of a collection with many elements), use a StringBuilder object rather than performing a lot of += operations on Strings. Every time you do += on a String, it has to make an entirely new copy of the string's characters, so this becomes very slow for large collections. Also notice how in the code below we call append twice to avoid doing the + on two strings each time through the loop.

    // bad
    String s = "";
    for (int i = 0; i < myArray.length; i++) {
        s += myArray[i] + ", ";
    }
    return s;
    
    // good
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < myArray.length; i++) {
        sb.append(myArray[i]);
        sb.append(", ");
    }
    return s;
    
  • Save expensive call results in a variable: If you are calling an expensive method and using its result multiple times, save that result in a variable rather than having to call the method multiple times.

    // bad
    if (list.indexOf("abc") >= 0) {
        list.remove(list.indexOf("abc"));
    }
    
    // good
    int index = list.indexOf("abc");
    if (index >= 0) {
        list.remove(index);
    }
    
Comments
  • Class header: Place a descriptive comment heading on the top of every file describing that file's purpose. Assume that the reader of your comments is an intelligent programmer but not someone who has seen this assignment before. Your comment header should include at least your name, course/section, and a brief description of the assignment. If the assignment asks you to submit multiple files, each file's comment header should describe that file/class and its main purpose in the program.

  • Method/constructor headers: Place a comment heading on each constructor and method of your class. The heading should describe the method's behavior.

  • Parameters/return: If your method accepts parameters, briefly describe their purpose and meaning. If your method returns a value, briefly describe what it returns.

  • Preconditions/assumptions: If your method makes any assumptions, such as assuming that parameters will have certain values, mention this in your comments.

  • Exceptions: If your method intentionally throws any exceptions for various expected error cases, mention this in your comments. Be specific about what kind of exception you are throwing and under what conditions it is thrown. (e.g. "Throws an IllegalArgumentException if the student ID passed is negative.")

  • Inline comments: Inside the interiors of your various methods, if you have sections of code that are lengthy or complex or non-trivial, place a small amount of inline comments near these lines of complex code describing what they are doing.

  • Implementation details: Comment headers at the top of a method or class should describe the method's behavior, but not great detail about how it is implemented. Do not mention language-specific details like the fact that the method uses a if/else statement, that the method declares an array, that the method loops over a collection and counts various elements, etc.

  • Wording: Your comment headers should be written in complete sentences, and should be written in your own words, not copied from other sources (such as copied verbatim from the homework spec document).

  • TODOs: You should remove any // TODO: comments from a program before turning it in.

  • Commented-out code: It is considered bad style to turn in a program with chunks of code "commented out". It's fine to comment out code as you are working on a program, but if the program is done and such code is not needed, just remove it.

  • Javadoc: You can use Javadoc (/** ... */) comment style if you like, but it is not required for this class. A style of commenting using // or /* ... */ is just fine.

Here is a decent overall example of a good comment header on a method. Not every comment header needs to be this long, but since this method takes a parameter and returns something, it needs to mention several things.

    public class Person {
        ...
        // Sets this person to be engaged to the given other person.
        // If either this person or other were previously engaged, their previous
        // engagement is called off and the previous partner is set to be single.
        // Returns true if this person was previously engaged before the call.
        // Assumes that other != null and other is of the opposite gender.
        public boolean engageTo(Person other) {
            ...
Class Design
  • Properly encapsulate your objects by making any data fields in your class private.

    public class Student {
        private int homeworkScore;
        ...
    
  • Avoid unnecessary fields; use fields to store important data of your objects but not to store temporary values only used within a single call to one method.

  • Initialize fields in constructors, not where they are declared.

    public class Student {
        private int homeworkScore = 10;
        private int homeworkScore;
        
        public Student() {
            homeworkScore = 10;
        }
    
  • Avoid empty zero-argument constructors. If you don't need to do anything to initialize your object, just omit the constructor.

    public class Student {
        ...
        public Student() {}
    }
    
  • If you declare a field, local variable, or parameter that is a collection, declare it using the ADT interface type, not the specific implementation type.

    public class FratGuy {
        private ArrayList<FratGuy> friends;  // bad
        private List<FratGuy> friends;  // good
    
  • Helper methods: If you add a method to a class that is not part of the homework spec, make it private so that other external code cannot call it.

    public class Student {
        ...
        private double computeTuitionHelper() {
            ...
        }
    
  • Instance vs. static: A static member of a class is a single occurrence shared by that class and all of its objects. An instance member is one that is replicated into each object of that class. When designing your class, any data that should be individual to each object should be non-static. This still holds even if the assignment's client program only happens to construct one object of your class.

    public class Student {
        private static int homeworkScore;   // all students share one homework score (bad)
        private int homeworkScore;          // each student has his own homework score (good)
        
        public Student() {
            homeworkScore = 10;
        }
    
This document and its content are copyright © Marty Stepp, 2015. All rights reserved. Any redistribution, reproduction, transmission, or storage of part or all of the contents in any form is prohibited without the authors' expressed written permission.