Skip to content
Study Hall
Lesson 4 of 7Software Development & the CPT
Unit 7 · Lesson 4 of 7

Code Style, Conventions and Maintainable Code

The naming, layout, constant and comment conventions that make Java readable, how to refactor messy code safely one step at a time, and the version-control habits that keep a program maintainable.

6 min read10 practice questionsAsk AI about this →

Key things to remember

  1. 1Classes use UpperCamelCase, methods and variables use lowerCamelCase, and constants use UPPER_SNAKE_CASE.
  2. 2Indent one level (usually four spaces) per block so the layout on screen matches the logic.
  3. 3Replace magic numbers with final named constants, declared once, so a change of value is a one-line edit.
  4. 4Comments explain WHY; every file gets a header comment and every method a Javadoc comment (/** ... */ with @param and @return).
  5. 5Refactoring changes structure without changing behaviour: one small change at a time, re-testing after each.
  6. 6Commit small, working versions with messages that say what changed and why, and use branches for risky changes.

A program is read far more often than it is written. You read it while you debug it, a partner reads it when you split the work, and you read it again three months later when a new feature is needed — by which point you remember almost nothing about why you wrote it that way. Maintenance, the work of fixing and extending software that already runs, is the longest stage of the life cycle, and its cost depends almost entirely on how readable the code is. Java programmers share a set of conventions for exactly this reason. None of them changes what the program does; the compiler ignores names, spacing and comments. They exist so that a person can understand the code quickly and change it without breaking something else.

Naming and layout conventions

Kind of nameConventionGood examplesAvoid
ClassUpperCamelCase noun, matching the file nameCheckoutTotal, StudentRecordcheckout, s, Program1
MethodlowerCamelCase, starting with a verbsumPrices, applyDiscount, printReportSum, doStuff, method2
VariablelowerCamelCase noun saying what it holdssubtotal, passCount, studentNamet, x2, temp3, data
BooleanReads as a yes/no questionisValid, hasPaid, foundflag, check
ConstantUPPER_SNAKE_CASE, declared finalHST_RATE, MAX_STUDENTShstrate, Rate
Single letters are acceptable for loop counters such as i and j, where the meaning is universal and the scope is a few lines.

Layout matters for the same reason. Indent one level, usually four spaces, for every block inside braces, so the shape of the code on screen matches its logic: you can see at a glance which statements are inside the loop and which are inside the if. Put one statement per line, leave spaces around operators (total = total + price;, not total=total+price;), and use blank lines to separate the steps of a method the way paragraphs separate ideas. Choose a brace style and use it everywhere. Most editors will re-indent a file automatically, so there is no excuse for misleading indentation — and misleading indentation is dangerous, because a line indented as though it were inside an if will still run every time if it is outside the braces.

Every Java program lives inside a class, and the work starts in main.public class HelloWorld { public static void main(String[] args) { System.out.print("Hi!"); }}12341class declarationfile: HelloWorld.java2the main methodevery program starts here3one statementa semicolon ends every one4closing bracesevery opening { needs a }The main method signature, part by partpublicany code maycall itstaticno object has toexist firstvoidhands nothingback to the callermain(String[])the exact namethe JVM looks forThe public class name and the file name must match exactly, capital letters included.Class HelloWorld in a file called helloworld.java will not compile.
Fig 1The parts of a Java program: class header, main method, statements and braces, each indented one level deeper than what contains it.

Constants and comments

A magic number is a literal value buried in code with no explanation, such as 0.13 or 35 in the middle of a calculation. It causes two problems. The reader has to guess what it means, and when the value changes — a tax rate, a class size, a passing mark — you must hunt down every copy and hope you neither miss one nor change an unrelated 0.13 by mistake. A named constant fixes both: declare it once with final, so the compiler refuses any attempt to reassign it, give it a name that explains it, and use the name everywhere. Values like 0, 1 and 100 in a percentage are usually fine as they are; the test is whether a reader would ask "why that number?". Comments follow a similar rule. The code already says WHAT it does, so a comment should say WHY, or explain something the code cannot. Every file should open with a header comment, and every method other than main should have a Javadoc comment, which starts with /** and uses tags such as @param and @return so tools can turn it into documentation.

/*
 * CheckoutTotal.java
 * Calculates what a customer owes for a cart of items: a volume
 * discount is applied first, then Ontario HST.
 * Author: J. Singh   Last changed: 2026-10-01
 */
public class CheckoutTotal {

    static final double DISCOUNT_THRESHOLD = 35.00;   // dollars, before tax
    static final double DISCOUNT_RATE = 0.10;
    static final double HST_RATE = 0.13;

    /**
     * Takes the volume discount off a subtotal that reaches the threshold.
     * @param subtotal the pre-tax total, in dollars
     * @return the subtotal after any discount
     */
    public static double applyDiscount(double subtotal) {
        if (subtotal >= DISCOUNT_THRESHOLD) {
            return subtotal * (1 - DISCOUNT_RATE);
        }
        return subtotal;
    }
}
A header comment, named constants, and a Javadoc comment. When the discount rule changes, exactly one line needs editing.

Refactoring a messy program step by step

public class s {
public static void main(String[] args) {
double[] a = {19.99, 5.49, 12.00, 3.75};
double t=0;
for(int i=0;i<a.length;i++){t=t+a[i];}
if(t>=35){t=t-t*0.1;}
t=t*1.13;
System.out.println("Total: "+Math.round(t*100)/100.0);
}
}
This compiles and prints Total: 41.93. It is correct, and it is very hard to maintain.
  1. Make sure it runs and record the current output (Total: 41.93). Refactoring means changing the structure WITHOUT changing the behaviour, so you need something to compare against.
  2. Reformat: indent every block and space the operators. Run it again — same output.
  3. Rename: the class becomes CheckoutTotal (and the file CheckoutTotal.java), a becomes prices, t becomes subtotal or total. Run it again.
  4. Replace the magic numbers 35, 0.1 and 1.13 with DISCOUNT_THRESHOLD, DISCOUNT_RATE and 1 + HST_RATE. Run it again.
  5. Extract methods for each job: sumPrices, applyDiscount, roundToCents. main now reads like a summary of the steps. Run it again.
  6. Add the header comment and Javadoc, run the full test set one last time, then commit the working version.
public static void main(String[] args) {
    double[] prices = {19.99, 5.49, 12.00, 3.75};

    double subtotal = sumPrices(prices);
    double discounted = applyDiscount(subtotal);
    double total = discounted * (1 + HST_RATE);

    System.out.println("Total: " + roundToCents(total));   // still Total: 41.93
}
After refactoring, main tells the story in four lines. The output is identical, which is the whole point.
Debugging is a routine, not a talent. Follow the same five steps every time.1Reproducefind the exact input that makes it fail, every single time2Read the errorthe message names the line number and the kind of fault3Isolatetrace table or println at each step — find the first wrong value4Change one thingthe smallest edit that could explain what you actually saw5Re-testrun the failing case and the cases that used to workStill broken? Go back to step 3 with what you just learned — and never change two things at once, or you cannot tell which one helped.
Fig 2Change one thing, then re-test. Small steps mean that when something breaks, you know exactly which change did it.

Version-control habits for maintenance

  • Commit small and often, and only when the program compiles and passes its tests, so every saved version is one you could safely return to.
  • Write commit messages that say what changed and why: "Apply discount before tax, not after" beats "fixed stuff".
  • Use a branch for an experiment or a risky change, and merge it only once it works. The main version stays runnable throughout.
  • Before starting work, pull the latest version; when a bug appears, compare the current code with the last version that worked (a diff) to find the change responsible.
  • Never commit passwords, keys or large generated files, and keep refactoring commits separate from feature commits so each one is easy to review.
Refactor and add features in separate steps
If you rename variables and change the discount rule in the same edit and the output changes, you cannot tell whether the new number is the intended new behaviour or a mistake from the renaming. Refactor first, confirm the output is unchanged, commit; then change the behaviour and commit again.

Worked examples

Reveal one step at a time and try to beat it to the next line.

Example 1
Rename the identifiers in this method to follow Java conventions: public static int Count(int[] X, int m) { int c = 0; for (int v : X) { if (v >= m) { c++; } } return c; } It counts marks at or above a cutoff.
Example 2
A grading program contains if (mark >= 50) in four places and mark * 0.7 + exam * 0.3 in two. Replace the magic numbers properly.
Example 3
Refactor the messy checkout program from this lesson into maintainable code, explaining what you check at each stage.
Example 4
Two weeks after a release, a user reports that a 32-dollar cart received the volume discount, even though the threshold is 35 dollars before tax. Use version-control habits to find and fix the bug.

Where marks get lost

  • Naming variables a, t or temp2, which forces every reader to reverse-engineer what they hold.
  • Leaving the same magic number in several places, then updating only some of them when the value changes.
  • Writing comments that repeat the code, such as i++; // add 1 to i, instead of explaining why.
  • Indenting a statement as if it were inside an if when it is outside the braces, so it misleads the reader and runs every time.
  • Refactoring and changing behaviour in one edit, or committing code that does not compile, so no saved version is safe to return to.

Flashcards 9

Naming convention for a Java class
Naming convention for methods and variables
Naming convention for a constant
What is a magic number?
+ 5 more

Practice

1
Which identifier follows Java conventions for a constant?
2
Match each kind of identifier to a name that follows its convention.
Class
Method
Boolean variable
Constant
3
Which Java keyword stops a variable from being reassigned after it is first given a value?
4
Which Javadoc tag describes one of a method's parameters?
5
Which comment is the most useful?
6
Using CheckoutTotal (discount 10 percent at 35 dollars or more, then 13 percent HST), what total is printed for a cart whose prices add up to 30.00 dollars? Give the answer to 2 decimal places.
dollars
7
Using the same rules, what total is printed for a cart whose prices add up to 50.00 dollars? Give the answer to 2 decimal places.
dollars
8
Put one safe refactoring cycle in order.
  1. 1Commit the working version with a clear message
  2. 2Confirm the output matches the recorded output exactly
  3. 3Re-run the program on the same input
  4. 4Run the program and record its current output
  5. 5Make one small structural change, such as renaming a variable
9
Which commit message is most useful to someone maintaining the code later?
10
The value 0.13 appears in six places in a program. The rate is stored instead as static final double HST_RATE = 0.13;. If the rate changes, how many lines must be edited?

Spot a mistake on this page? Let us know