Fundamentals 17 min read

Mastering Clean Code: Naming, Classes, Functions, and Tests Explained

This article explains why clean code matters, demonstrates how meaningful naming, single‑responsibility classes, well‑structured functions, and disciplined testing (TDD and the FIRST principles) improve readability, maintainability, and productivity, using concrete Java examples, refactorings, and step‑by‑step guidelines.

Architect
Architect
Architect
Mastering Clean Code: Naming, Classes, Functions, and Tests Explained

1. Why Keep Code Clean?

Unclean code accumulates technical debt, reducing productivity and increasing the risk of bugs, costly extensions, and even project failure. The author illustrates this with a list of consequences—hard‑to‑extend code, crashes, overtime, and higher hiring costs—supporting the claim that early, continuous cleanup prevents later crises.

2. Naming

Good names increase readability and lower the cognitive load for teammates.

2.1 Bad Naming Practices

Meaningless names, e.g., public interface Animal { void abc(); } where the method name conveys nothing.

Inconsistent naming for the same behavior, e.g.,

public interface StudentRepository extends JpaRepository<AlertAll, String> { Student findOneById(@Param("id") String id); List<Student> queryAllStudent(); }

which should be unified as List<Student> findAll();.

Redundant words, such as prefixes get for single objects or list for collections, which add noise without value.

2.2 Good Naming Practices

Names should be expressive and convey intent, e.g., public interface Animal { void cry(); } clearly indicates the method’s purpose.

3. Classes

Clean classes follow the Single‑Responsibility Principle, the Open/Closed Principle, and high cohesion.

3.1 Single Responsibility

A class should have only one reason to change. The author shows a class with two responsibilities:

public abstract class Sql { public abstract void insert(); public abstract void countInsert(); }

and refactors the counting responsibility into a separate class:

public abstract class CountSql { public abstract void countInsert(); }

This reduces complexity, improves readability, and lowers change‑induced risk.

3.2 Open/Closed Principle

Code should be open for extension but closed for modification. The original Sql class required modification to add a query operation:

public abstract class Sql { public abstract void insert(); public abstract void update(); public abstract void delete(); }

After refactoring, new operations are added by subclassing without touching existing code:

public abstract class Sql { public abstract void generate(); }
public class CreateSql extends Sql { @Override public void generate() { /* ... */ } }
public class UpdateSql extends Sql { @Override public void generate() { /* ... */ } }

The author uses an analogy of a toolbox with many labeled drawers versus a few generic ones to illustrate the benefit of many small, focused classes.

3.3 Cohesion

High cohesion means that a class’s methods operate on a shared set of variables, forming a logical whole. The author advises splitting low‑cohesion classes into smaller ones to preserve single responsibility.

4. Functions

Clean functions should do one thing, have descriptive names, accept minimal parameters, avoid side effects, and return clear results.

4.1 Do One Thing

The author presents a bloated upload method (≈135 lines) that mixes validation, compression, and result handling. Refactoring splits it into:

public String upload() { check(); compress(); return "0"; }

Each helper method now has a single responsibility.

4.2 Naming Functions

Bad example:

public String addCharacter(String originString, char ch);

does not indicate where the character is added. Better alternatives:

// Append to end
public String appendCharacter(String originString, char ch);
// Insert at specific position
public String insertCharacter(String originString, char ch, int insertPosition);

4.3 Parameters

Prefer few parameters; if more than three, encapsulate them into a domain object.

Avoid Boolean flags that create hidden branches; split into separate methods.

Do not use output parameters; instead, return results directly or let the object manage its own state.

4.4 Return Values

Separate commands from queries: replace Boolean addElement(Element e) with void addElement(Element e) and Boolean isAdded(Element e). Use exceptions instead of error codes to avoid deep nesting.

5. Testing

Testing validates clean code and should itself be clean.

5.1 Test‑Driven Development (TDD)

TDD advocates writing a failing test before production code, ensuring tests never pass until the implementation is complete. Benefits include early feedback and reduced debugging time; drawbacks are increased test code volume (often twice the production code).

5.2 FIRST Principles

Fast – tests run quickly.

Independent – tests do not depend on each other.

Repeatable – tests run the same everywhere.

Self‑validating – results are asserted automatically.

Timely – tests are written before code.

5.3 Given‑When‑Then Pattern

Structure tests into three phases: create data (given), execute code (when), verify outcome (then). Example:

@Test
public void shouldReturnItemNameInUpperCase() {
    // Given
    Item mockedItem = new Item("it1", "Item 1", "This is item 1", 2000, true);
    when(itemRepository.findById("it1")).thenReturn(mockedItem);
    // When
    String result = itemService.getItemNameUpperCase("it1");
    // Then
    verify(itemRepository, times(1)).findById("it1");
    assertThat(result, is("ITEM 1"));
}

5.4 Automated Test Generation Tools

The author mentions two IDE plugins (one commercial, one free) that can scaffold test skeletons, but does not promote them further.

Conclusion

Writing clean code—through meaningful naming, single‑responsibility classes, focused functions, and disciplined testing—boosts readability, extensibility, and developer efficiency while reducing overtime and technical debt.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

unit testingsoftware designrefactoringclean codenaming conventionsTDDsingle responsibility
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.