About this guide

This guide is an (informal) style guide for CSE 142 and 143, and contains a list of rules we expect you to follow on your homework assignment. To learn more about a particular rule, click the "expand" button.

Please note that this guide is not necessarily comprehensive. We've done our best to include all the different style rules we can think of, but there's always the case we might have missed one.

You can also filter and search for specific rules based on content, chapter, or assignment using the filters to the right.

Why do we care about style?

Programming is a very collaborative activity, so it is very important for humans to be able to read and use your code. It is very difficult to collaborate with with and trust a programmer who writes code that has bad style.

The fundamental principles of style

Good style is not about memorizing a list of rules – every rule can be derived from the same core set of principles. If you understand those principles well, you should be able to independently predict and derive nearly every rule in this guide.

How this guide is organized

The content in this guide is arranged primarily by category – you can filter by category, assignment, and book chapter using the drop-down menu to the right.

We recommend you filter the guidelines by either book chapter or assignment, especially for CSE 142 students or students in the first half of CSE 143x. Many of the style guidelines are meant more for CSE 143 students, and will not be immediately relevant or understandable.

This section of the guide contains some basic rules we expect you to follow throughout the quarter. These are not really "style guidelines", but are still important to follow.

Academic Integrity

Programming HW must be completed individually; all code you submit must be your own work. Please consult the syllabus for more details.

Advanced material

Do not use material that you haven't been taught. When in doubt, ask.

An important aspect of good style is having code that is formatted cleanly. Cleanly formatted code will greatly help enhance readability.

Indentation and nesting

When you see a matching set of opening and closing curly brackets, indent all lines of code in between by one additional level. Be consistent in how big each indent is.

Indentation and comments

Comments should be indented to the same level as the thing they are commenting.

Curly bracket and indent style

There are many different conventions regarding how exactly to go about formatting and placing your curly brackets. We strongly suggest you stick to the standard Java conventions, but you are free to pick whichever convention you want, as long you consistently follow it (and the convention you pick isn't too bizarre).

Expand for details on our recommended style.

Long lines

Do not have lines of code that over 80 characters wide, including indents and comments. Expand for strategies on handling long lines which you cannot shorten.

Blank lines

Leave a single blank line between each significant chunk of code. At minimum, leave one blank line between each method. Do not write multiple consecutive blank lines. Do not leave a blank line after an opening curly brace, or before a closing curly brace.

One statement per line

Place each statement on its own line.

Spacing

Place spaces to enhance readability. Be sure to place spaces such that your code is neither too cramped nor too expansive. Expand for a list of specific spacing rules with examples.

Printing and newlines

If you want to print a newline, always do System.out.println() instead of System.out.print("\n") or System.out.println(""). With a few rare exceptions, avoid using the \n or \r newline escape characters.

Descriptive variable names

When naming variables, fields or methods, be descriptive and succinct. With a few rare exceptions, you should never use create a variable or method with a single-letter name or an overly long name. Expand for more specific guidelines.

Java naming conventions

Variables, methods, and fields should be in lowerCamelCase, classes should be in UpperCamelCase, and constants should be in SCREAMING_CASE.

Always include curly brackets

Always include curly brackets, even for one-line if statements or for loops.

Besides formatting, another important aspect of writing code with good style is making sure that the actual flow of logic within your method is clean and sensible.

Variable type

Choose the type which is most appropriate for the data you are trying to represent. Use an int when you only need whole numbers, doubles when you need decimal precision, booleans for when you need a binary true or false value, Strings for arbitrary text, and so forth.

Constants and magic numbers

Use constants whenever you want to define a single value that won't change during the execution of your program. In particular, whenever you have an arbitrary number or value in your code (a "magic value"), you should use a constant instead. Declare all constants to be public static final.

Variable phobia

Make liberal use of variables, especially to eliminate redundant and repeated expressions.

On looping

Java lets you "loop" through values in several different ways. Though many of these looping constructs are, to a certain extent, mechnically interchangable, they each have a different meaning and use. Which looping construct you use will imply multiple things about your code. Use the one that best fits your overarching intent.

For loops

Use a for loops when you know exactly how many times you need to loop before entering the loop. Do not use loops when you end up always looping only once.

While loops

Use a while loops when you do NOT know exactly how many times you need to loop, and can only find out in the middle of looping – when you need a potentially infinite or indefinite loop.

Do-while loops

We do not expect you to know about or use do-while loops in CSE 14x – consider them optional material. You may use do-while loops once we have taught you about regular while loops, if you wish.

Single-iteration loops

You should never write a loop (for loop or while loop) that will either never run, or will always runs exactly once. If a loop will never run, that loop should be deleted entirely. If a loop always runs once, you don't really need a loop to begin with.

Special-casing specific iterations

Likewise, you should avoid structuring the contents of a loop so that a segment of it runs only during a specific iteration. For example, avoid adding in an if statement into a loop that will always run only during the first iteration, or only during the second and third.

Break and continue

Do NOT use break or continue statements.

Note: If you don't know what break and continue are, that's fine. We deliberately do not teach you about them, but some students find out anyways.

Branching semantics

Java allows you to combine if/else statements and branch in several different ways. Select the method that best suits what kind of branch you want to execute. Expand for more details.

Factor out common code

If you have common code at the beginning or end of a conditional, you should pull that out so you don't end up duplicating the code and end up with redundancy.

Unnecessary tests

Avoid unnecessary tests. If you already know that something is true, then you shouldn't bother to have a test for it. Such tests just make your code longer and harder to understand.

Empty blocks

You should never have empty blocks in your code – never have at set of curly braces that contain nothing inside.

Switch-case

We do not expect you to know about or use switch-case in any of your assignments and exams. We don't explicitly forbid you from using it, but we strongly encourage you to use if/else statements instead.

Do not compare a value to true

You should never need to compare a boolean against another boolean – just directly use the boolean itself. This is because comparing a boolean against a boolean will produce yet another boolean, which is redundant and needless.

We call doing this sort of comparison bad boolean zen.

Use the negation "!" operator instead of comparing to false

As an extension of the previous rule, you should never do value == false or value != true – this would also count as bad boolean zen. Instead, do !value instead.

Be careful when returning or setting a boolean

When writing a method that returns a boolean be very careful to make sure that your code has good boolean zen. If you need an if statement to decide if something should be true or false, you can often simplify away the entire if statement.

Foreach loops

Use a foreach loop when you want to iterate over some sort of collection such as an array or a list, and work on the collection one element at a time. Prefer using foreach loops over for loops when possible.

Note: Foreach loops are CSE 143-only material.

Iterators

Use iterators when you want to use a foreach loop, but also want to simultaneously modify the collection you are iterating over. Prefer using foreach loops whenever possible.

Note: Iterators are CSE 143-only material.

Recursion

Use recursion when none of the above appear to be a good fit when looping, and when simple iteration will not suffice. For example, recursion is often a good fit when dealing with branching data structures such as trees.

Note: Recursion is a CSE 143-only topic.

Higher-order functions

Do not use higher-order functions (streams, lambdas, map, etc).

Checked vs unchecked exceptions

If you are writing a method that could potentially throw an exception, you should only include that exception as a part of the method header if your code will not compile if you omit it.

Exception checks and if statements

Exception checks should always be placed into individual if statements with no attached else statements.

Fail early

You should perform your exception checks as soon as possible – move them to as close to the top of a given method as possible. Think of your exception checks as gatekeepers that prevent corrupt data from entering your method. You want gatekeepers to be stationed close to the gate, not in the middle of your castle.

Custom error messages

Although this is not strictly speaking required, you should always include a custom error message for every exception you throw.

As the problems and the programs you write grow increasingly complicated, you'll soon find that trying to cram all of your logic and code into a single method will result in very nasty and difficult-to-work with code.

To prevent that from happening, it's valuable to understand how to go about decomposing and breaking apart a problem into smaller pieces and components, how to use things like methods to help arrange, structure, and organize your code on a broad scale, and how to divide responsibility between the different pieces of your program.

What is redundancy?

You should aim to eliminate as much logical redundancy from your code as possible. If you need to repeat a task, don't copy-and-paste the code. Instead, take the common lines and refactor them into a helper method.

A large part of this class and of your grade will be oriented around being able to detect and eliminate redundancy.

Detecting redundancy

Sometimes, it can be hard to tell when something is worth refactoring or not. If you have 6-8 identical lines of code, it's pretty obvious that should be refactored, but what about 1-2 lines of code? What about expressions like 'a' + 1? Where does the boundary lie?

When considering this sort of question, you should ask yourself how many "operations" you'll end up saving if you refactor something into a method. If you end up with a net gain after refactoring something, it was probably the correct decision.

Use methods to help provide structure and organization

Besides using methods to help reduce redundancy, you should also use methods to help structure and organize your code into distinct sections to enhance readability.

A good rule of thumb is to try and write methods that contain a single primary responsibility. Try and avoid trying to do too many things at once: use helper methods to divide and delegate subproblems.

Main methods should be a summary

Your main method should be a summary of your entire program – like a table of contents. This is an extension of the previous rule.

Trivial methods

You should never write a method which does only a single operation or is composed of only a single component. Instead, you should just perform that operation directly and skip the middle-man.

Minimize your parameters

Your method should accept only the bare minimum parameters that it needs in order to successfully complete its task.

Early returns

Stylistically, we're indifferent as to whether or not you have only a single return in your method or if you have multiple. The only time we require you to return early from a method is if doing so would benefit efficiency (for example, returning a value from the middle of a loop).

Method chaining

Do not chain your methods together. If you have a sequence of tasks that are meant to be linear, you should keep them linear. If you need data to flow from one method to another to yet another, you should return that data instead of directly passing it some method.

Note that what method chaining is and isn't can be subtle. You'll probably need to read the expanded explanation for this one.

Minimize your fields

You should keep the number of fields in your class to a bare minimum needed to successfully complete your assignment without compromising on the other principles of style. If it is possible to perform a task via passing data around via parameters and returns instead of using a field, you should do so.

Make all fields private

You should always make all your fields private. This prevents the client from looking at and tinkering with the internal details of your code. The client should only ever interact with your object through a carefully-defined set of public methods to prevent subtle bugs from occurring.

There are a few exceptions to this rule, but we will explicitly tell you when that is the case.

Field initialization

Always initialize your fields inside your constructor, not outside.

Extra public functionality

You should not include extra public methods beyond what the spec instructs you to include. Any helper methods you make must be kept private.

this

You should always use the this keyword whenever it's possible to do so. Doing so will make the difference between local variables/static methods vs fields/instance methods very clear.

Duplicate constructors

When writing classes with multiple constructors that share many similarities, you should always try and structure your constructors such that they all delegate to one single, general constructor instead of repeating your initialization logic.

Method independence

When writing objects, you should take care to ensure that no single method relies on any other method being called first, or in any particular order.

The only thing you may assume is that one of your constructors will be the very first thing that is run. Apart from that, anything goes.

What are comments?

Why comments are useful

Expectations for CSE 142 vs 143

Class header comments

You must always include class header comments for every class you write. Your class header comment must include metadata (your name, date, assignment, TA, etc), and a description of the class as a whole. Assume that whoever is reading the description is unfamiliar with the assignment.

Do not plagarize

Your comments should be written in your own words. You should not directly copy-and-paste any text from the spec.

Note: this section of the guide covers our expectations for commenting methods in CSE 142 and the first half of CSE 143x. Our expectations are stricter in CSE 143.

Know your audience

When commenting your methods, be sure to keep in mind who exactly your comments are addressed to. You should assume that your reader is competent, does not know anything about the assignment, and does not care about how your code works, only what it does.

Comment every method

You must comment every single method in your class. Your comment should describe what that method does (but not how it does it).

Exception: Commenting your main method is optional

The only method you are not required to comment is your public static void main(String[] args) method (though you can, if you want to).

What to comment on

When writing a method header comment, focus on describing your parameters, any return values, and any interactions your program will have with the outside world (printlns, reading or writing to files, getting input from the user, etc).

Formatting your comments

You may format your comments however you wish as long as it's readable and the information we're looking for is there. Expand for suggested formatting styles.

Method header vs inline comments

There are three different kinds of comments you can write: class header comments, method header comments, and inline comments (which are comments that go inside your method).

It's important to note that what we expect from inline comments are somewhat different from what we expect from class/method header comments.

Inline comments

Use inline comments to describe complex pieces of code – to explain your implementation. You may also use inline comment to help delineate distinct "sections" of your method. Do not overcomment and leave excessive amounts of inline comments.

Formatting inline comments

There are no hard-and-fast rules for formatting inline comments. However, you should generally place inline comments on the line directly before the thing you are commenting.

Note: This section is for CSE 143. We do not expect you to follow these guidelines in CSE 142 (though feel free to do so if you like).

Expectations in CSE 143

Our expectations for CSE 143/the second half of 143x are higher then they were in CSE 142. In addition to what we previously expected from you, we now expect you to always include information about your preconditions and postconditions in your method header comments, and to never include any implementation detail.

It's important to note that the rules for commenting that we teach you do not contradict what you were taught in CSE 142 in any way. Rather, we're being more rigorous about what exactly is expected.

Preconditions and Postconditions

When writing a method header comment, focus on describing the preconditions and postconditions for that method.

Implementation detail

Your method header comments should never include implementation detail – information about how exactly the method or class works.

One useful way of determining if something would count as implementation detail is to ask yourself if your code would survive a total internal rewrite. If it doesn't, odds are it contains implementation detail.

Assumptions about the client

Your comments should never make any assumptions about the behavior of the client.

Retain only useful information

We do not enforce any sort of length requirement or restriction of comments. You are free to make your comments as long or short as you'd like, so long as don't omit any important information and all the information included is actually useful.

Note: this section is for CSE 143 only.

Previously, we stated that there are three kinds of methods: class header comments, method header comments, and inline comments.

We are going to extend this model further by taking a look at the differences between public method header comments, and private method header comments. We expect slightly different things from the different types of method headers.

Public comments

The client of a public method is somebody who might want to use your code. As a result, you should avoid including info about how exactly your class and methods work and instead focus on commenting external behavior.

Private comments

The client of a private method is somebody who wants to add a new public method to your class, and will potentially use your private method to do so. As a result, it's ok to talk about some internal details such as your fields, but still not ok to talk about how your method works.

Redundancy in comments

While having redundancy in code is very bad and should be avoided whenever possible, redundancy in comments is sometimes unavoidable and is not as big of a deal.

Comment your exceptions

Whenever you have a method that could potentially throw an exception (IllegalArgumentException, FileNotFoundException, etc), you should mention that your code could throw this exception, and under what conditions.

Unlike the previous sections, which focused primarily on topics such as readability, concision, and modularity, this section focuses almost exclusively on efficiency, and guidelines for writing efficient code.

Write algorithmically efficient code

In this class, when we're considering efficiency, we're primarily interested in the behavior of your algorithm in the long run, and are not particularly concerned with micro-optimizations.

More specifically, when trying to write code to solve a problem, you should focus on making the time-complexity of your algorithm as low as possible

Minimize the data structures you use

Besides trying to minimize the time complexity of your code, you should also minimize the number of data structures you are actively using at any given time.

This section of the style guide isn't particularly well-integrated. It mostly contains a variety of miscellaneous style things related to specific data structures and objects that you'll be using during your assignment.

Most, if not all of the style issues we mention in this section will already be explicitly mentioned in the spec, but for completeness, they're also all listed here.

Arrays should be homogeneous

You should use arrays to store a related sequence of data which has all the same type. Do not try and use arrays has a hack to store multiple pieces of unrelated data. You should use loops to process arrays whenever possible.

Token and line-based processing

Do not try and mix together token and line-based processing with the same scanner. Doing so will almost always result in hard-to-debug bugs.

Interfaces

When declaring or initializing an object, you should always make the declared type an interface, not a concrete object.