Phase 5 · Professional DevelopmentModule 33~40 min read

Clean Code & Object-Oriented Design

Write code humans love to read with SOLID principles, cohesion, and refactoring.

What you'll learn

Code is read far more often than it's written — usually by a future version of you. Clean code is code that others (and future-you) can understand and change safely. This module distils the timeless principles that separate maintainable software from a mess.

By the end you'll be able to:

  • Choose meaningful names and write small, focused functions
  • Apply the SOLID principles of object-oriented design
  • Follow DRY, KISS, and YAGNI
  • Recognise code smells and refactor them away

Meaningful names

Good names are the cheapest, highest-impact way to make code readable. A name should reveal intent — what it is and why it exists — so the reader doesn't need a comment to decode it. Classes are nouns (InvoiceGenerator), methods are verbs (calculateTotal), booleans read as questions (isValid):

Naming.java
// ✗ Cryptic — what do these mean?
int d;
List<double[]> list;
if (u.f == 1) { ... }

// ✓ Intention-revealing — the code reads like prose
int elapsedDays;
List<double[]> flaggedCells;
if (user.isActive()) { ... }

Small functions

A function should do one thing and do it well. Short functions with descriptive names turn code into a readable outline — you understand the flow without reading every detail. If you need the word "and" to describe what a function does, split it:

Functions.java
// ✗ One function doing three jobs
void handle(Order o) {
    // validate
    if (o.getItems().isEmpty()) throw new IllegalArgumentException();
    // calculate
    double total = 0;
    for (Item i : o.getItems()) total += i.price();
    // save
    database.save(o, total);
}

// ✓ Each function does ONE thing, named for it
void handle(Order o) {
    validate(o);
    double total = totalOf(o);
    save(o, total);
}

Tip

Aim for functions that fit on one screen, take few parameters, and operate at a single level of abstraction. The refactored handle above reads like a summary; the details live in well-named helpers.

The SOLID principles

SOLID is five design principles that keep object-oriented code flexible and maintainable. You don't need to apply all five everywhere — but knowing them shapes better designs and helps you explain why one design beats another:

SOLID
S

Single Responsibility

A class should have one reason to change.

O

Open / Closed

Open for extension, closed for modification.

L

Liskov Substitution

Subtypes must be usable through their base type.

I

Interface Segregation

Many small interfaces beat one fat one.

D

Dependency Inversion

Depend on abstractions, not concrete classes.

Note

The most impactful in daily work are Single Responsibility (small, focused classes) and Dependency Inversion (depend on interfaces, inject implementations — the foundation of testable code and the DI you'll meet in Module 37).

DRY, KISS & YAGNI

Three short mantras carry a lot of wisdom:

  • DRY — Don't Repeat Yourself. Every piece of knowledge should have one home; duplication means bugs hide in the copies you forget.
  • KISS — Keep It Simple. The simplest solution that works is usually the best.
  • YAGNI — You Aren't Gonna Need It. Don't build for imagined future requirements; solve today's problem.
Dry.java
// ✗ Duplicated logic — change it in one place, forget the other
double areaOfLawn = length * width;
double areaOfPatio = pLength * pWidth;

// ✓ Extract the shared idea once
double area(double length, double width) {
    return length * width;
}

Watch out

DRY has a limit: don't force unrelated code together just because it looks similar. Duplication is cheaper than the wrong abstraction. Extract shared logic only when it truly represents the same concept.

Code smells & refactoring

A code smell is a surface sign of a deeper problem — long methods, huge classes, long parameter lists, duplicated code, deeply nested conditionals, or comments explaining confusing code. Refactoring is improving the code's structure without changing its behaviour — and it's only safe when you have tests (Module 29) to prove you didn't break anything.

Key idea

Also lean on immutability and composition over inheritance (Module 9): immutable objects are simpler and thread-safe, and composing small objects stays more flexible than deep inheritance trees. These habits compound into codebases that stay pleasant to work in for years.

Recap & quick check

Key takeaways

  • Names should reveal intent — classes are nouns, methods verbs, booleans questions.
  • Functions should do one thing; small, well-named functions read like an outline.
  • SOLID keeps OO code flexible; Single Responsibility and Dependency Inversion matter most day-to-day.
  • DRY (no duplication), KISS (stay simple), YAGNI (don't build for imagined futures).
  • Refactor away code smells — safely, backed by tests; favour immutability and composition.

Quick check

1. What makes a good variable or method name?

2. The 'S' in SOLID stands for…

3. What does DRY mean?

4. What is refactoring?

5. A very long method that does many things is an example of…

Great — you now write code humans love to read. Next up: Module 34 — Design Patterns.