Coding Style

A computer program is meant for two audiences: the computer that compiles and runs it, and the people who must read, modify, maintain and test it. Think about writing a program the same way you think about writing a paper: structure, organization, word choice and formatting are just as important as content. A program that works but has a terrible style is unreadable, and therefore useless.

Real-world software development teams use common programming style guides, e.g. PEP 8 Python style guide, Google style guides for various languages. Style guides include things like formatting your source code, comment requirements, how certain constructs should (or shouldn't) be used, variable naming conventions, cross-platform compatibility requirements, and more.

We realize that coding style can be a very personal choice, but in the professional world you will seldom have the privilege of choosing your own style. Regardless of the style you choose, develop, or are forced to use, stick with it. Consistency is a plus!

CS 10 style

For CS 10 assignments involving Java programming, please follow these guidelines:

Always remember: You are writing for clarity and communication, not to show how short and dense you can make your code.

Commenting

Comment your code as you write it: it is much easier to write comments while your intentions are fresh in your mind than to go back later and do it.

Keep comments short, simple, and to the point. Comment wherever the code is not self-describing. Use the // style of commenting for one-line comments, the /* ... */ style for multi-line block comments within a function, and the /** ... */ Javadoc style for comments before a function and at the beginning of a file.

Use four types of comments:

Use them in the following fashion:

Start-of-file-comments. You should place a Javadoc comment at the start of each file. This comment should include the names of programmers (@author), the date the file was written, and a high-level description of the file's contents. For example:

/**
 * GraduateStudent extends Student with an advisor and a lab. 
 * Additionally tracks the hours this student spends in the lab.
 *
 * @author Kate Salesin 6/30/25
 */
public class GraduateStudent extends Student {

Start-of-function comments. Write a Javadoc comment above each function. This comment should include a description of what the function does, the meaning of its parameters (@param), and the meaning of its return value. There are additional tags that can be included here (@throws for what type of error the function throws, @return to describe the return value), which you can include if you wish. For example:

/**
 * Adds hours parameter to the hoursSpentInLab to track time this student spent in the lab.
 * @param hours  Number of hours spent in the lab (must be positive)
 * @return       Total number of hours spent in the lab (after experiment)
 */
public double experiment(double hours) {

You do not need to write Javadoc comments for simple getters and setters.

If a function requires any constraints on its parameters, state them (i.e. "x must be positive"). Similarly, specify any constraints on the output. List all error conditions and what the function does with them. List any side effects.

If the function algorithm is not obvious, name and/or describe it (often a good idea). Also, if you borrow the algorithm from another source, credit the source and author in this comment.

Multi-line comments. If a function is complex enough to be divided into a series of internal steps, such as initialization, reading data, writing output, place a brief multi-line comment before each such section describing what it does.

One-line comments. Place a brief comment where needed to clarify the code. Don't overdo it, but use them to call the reader's attention to subtleties in the code. Align comments to the same level of indentation as the code for that function.

Spacing

Where to put spaces:

Where not to put spaces:

Indenting

Let your text editor help you auto-indent your code. Often, trouble with auto-indentation is a clue to your own syntax mistake (such as forgetting brackets).

When you create or open a file, IntelliJ will know it is a Java file based on the extension. Hitting the TAB key while the cursor is on a given line indents it to the correct level, assuming that the preceding non blank line has been indented correctly. Ending a line with a left bracket and hitting return will automatically indent the next line appropriately. Also, a line beginning with a right bracket will indent to the correct level.

File structure

Although Java allows us to be very flexible with where we put declarations, a standard layout makes it easier to read the code. A good convention is:

import java.util.ArrayList;
...
  
/**
 *  Start-of-file comments
 */
public class ClassName {
    // Static and/or final instance variables
    private final int maxNameLength = 30;
    ...

    // Other instance variables
    String name;
    int id;

    // Constructors
    public ClassName() {
    ...

    // Getters & setters
    public String getName() { return this.name; }
    public int getID() { return this.id; }
    ...

    // Methods
    public doSomething() {
    ...

    public doSomethingElse() {
    ...

    // Main method
    public static void main(String[] args) {
    ...
}

(You do not need to include the comments // Instance variables, // Constructors, etc. above, they are just annotating the file structure here.)

Access modifiers and other decorators

To recap, the following are access modifiers that control who can directly access an instance variable or method (can read and write to object.instanceVariable directly without having to use a getter and setter):

All the files in your cs10 project are within the same package, so there is not much observable difference between public, protected, and package access in this case. However, it is still good practice to protect your variables and methods unless there is a good reason not to. In general, protected access is a reasonable choice for instance variables, with public getters and setters if you want outside users to be able to read and modify those variables. private access may be a good choice for helper variables and helper methods that are meant to only be used within the class. Of course, use public methods for core functionality that you expect a user to call.

final indicates that once that variable is initialized, its value cannot be changed (it is the Java equivalent of const in other languages like C). If you use any "magic numbers" within your code that do not change, e.g. the size of a GUI component, the maximum RGB value, or a condition you check, it might be a good idea to create a final variable for that number at the top of the class.

static indicates a variable or method that is shared among the class as a whole, and is always the same for all objects of the class. A static variable or method can be accessed using the syntax ClassName.instanceVariable or ClassName.method() without needing to create an object of that class first. It is a good choice for variables or methods that are related to a class but do not act on any particular object of that class, often utility functions.

These decorators can be stacked onto one variable or method like so:

private static final int windowWidth = 600; // Width of window in pixels
public static void main(String[] args) {
...

Simplicity

This single most important thing you can do to write good code is to keep it simple. As William of Occam said in the 14th century: "Do not multiply entities without necessity." Simplicity has many aspects; a few of these include:

Make all functions small, coherent, and specific. Every function should do exactly one thing. A good rule of thumb is that you should be able to describe what a function does in a single sentence. You should also be able to see all of it on your screen, i.e. try it keep it under roughly 30 lines long.

Use small parameter lists. Avoid extremely long parameter lists. If you find the parameters to a function growing, ask yourself if the function is trying to do too much, or if the function is too vague in its intent.

Avoid deeply nested blocks. Structures such as if, for, and while define blocks of code; blocks can contain other blocks. Try not to nest blocks too deeply. Any function with more than a couple levels of nesting can be confusing. If you find yourself with deeply nested structures, consider either simplifying the structure or defining functions to handle some of the nested parts.

Use the simplest algorithm that meets your needs. Einstein once said: "Things should be as simple as possible, but no simpler." This is good advice for selecting an algorithm. There are a great many extremely clever, complex algorithms in computer science. Make an effort to know them and use the algorithm that meets your needs for efficiency. Do not shun complex algorithms, but do not choose them without reason.

Be consistent. Consistency can come in many forms. A few of these include:

Practice defensive programming!

It is important you write programs defensively. That is, you need to check the input the program receives, make sure it is as expected (in range, correct data type, length of strings, etc.), and if it is not acceptable, provide appropriate message(s) back to the user in terms of the program usage. The user should never be able to cause your program to adversely impact any aspect of the system it's running on, including system files, other users' files or processes, or network access.

When you detect an error condition, first consider ways to modify the code to prevent the error from happening in the first place. If that is not possible, ask if there is a way the code can recover from the error. If there is no reasonable way of recovering, print an error message and exit the program.

In short, if someone (such as the grader) can crash your program, you lose points, whether in this class or in a future job.

Acknowledgment

This page is based on the style guide for CS 50 written by Prof. Tim Pierson and adapted by Dr. Kate Salesin.