Fundamentals 22 min read

Clean Code Principles: Naming, Classes, Functions, and Testing Best Practices

This article summarizes key clean‑code practices—including the importance of readable naming, adhering to SOLID principles for classes, writing single‑purpose functions, avoiding redundant parameters, and employing test‑driven development and code‑quality tools—to help developers produce maintainable, extensible software.

Top Architect
Top Architect
Top Architect
Clean Code Principles: Naming, Classes, Functions, and Testing Best Practices

Hello, I am a senior architect.

This article is a study summary of "Clean Code" and explains why clean code matters to projects, companies, and developers, and how to write it.

1. Why keep code clean?

Untidy code accumulates over time, reducing productivity and leading to hard‑to‑extend code, crashes, overtime, increased hiring costs, and even company failure.

One picture says it all:

1.1 Start clean from the beginning

Write clean code from the start; if you find messy code, refactor it immediately. Never postpone.

later equal never

1.2 How to write clean code?

Clean code should be:

Highly readable – like prose, the intent is obvious.

Free of duplication.

Follow design‑pattern principles.

Single responsibility.

Open‑closed.

Liskov substitution.

Dependency inversion.

Interface segregation.

Demeter’s law.

Composition over inheritance.

2. Naming

Good names improve readability, reduce understanding cost, and increase efficiency.

2.1 Bad naming examples

public
interface
Animal
{
void
abc();
}

The method name abc gives no clue about its purpose.

Good naming:

public
interface
Animal
{
void
cry();
}

Now callers understand the method’s intent.

2.2 Naming consistency

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

Inconsistent method names findOneById and queryAllStudent cause confusion. After standardising:

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

2.3 Redundant naming

// getXxx() – get a single object
getXxx();
// listXxx() – get multiple objects
listXxx();

3. Classes

Clean classes should satisfy:

Single responsibility.

Open‑closed.

High cohesion.

3.1 Single responsibility

Classes should be small and have only one reason to change.

Reduces complexity.

Improves readability.

Enhances maintainability.

Lowers change‑risk.

Determine class size by its responsibilities; if a class cannot be named precisely, it likely does too much.

public
abstract
class
Sql {
// operate SQL
public
abstract
void
insert();
// count SQL operations
public
abstract
void
countInsert();
}

Extract counting to a separate class:

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

3.2 Open‑closed principle

Software should be closed for modification but open for extension.

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

Adding a query operation would require modifying Sql , violating the principle. Refactor by introducing a generic generate method and concrete subclasses:

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

3.3 Cohesion

High cohesion means most methods use the same set of variables, forming a logical whole. Split low‑cohesion classes into smaller ones.

4. Functions

Clean functions should:

Do one thing.

Have good names.

Have clean parameters.

Handle return values properly.

4.1 Do one thing

public
class
PicService {
public
String upload() {
// validate image – ~80 lines
// compress image – ~50 lines
// return status – 0/1 – ~5 lines
return "0";
}
}

Refactor into smaller steps:

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

4.2 Function naming

public
String addCharacter(String originString,
char
ch);

Better names indicate intent:

// append to end
public String appendCharacter(String originString,
char
ch);
// insert at position
public String insertCharacter(String originString,
char
ch,
int
position);

4.3 Parameters

Prefer few parameters; wrap many into a domain object.

public List<Student> findStudent(int age, String name, String country, int gender);
// after wrapping
public List<Student> findStudent(Student student);

Avoid Boolean flags that create two code paths; split into separate methods.

// flag version
void render(Boolean isSuite);
// split version
void renderForSuite();
void renderForSingleTest();

4.4 Return values

Separate commands from queries:

// bad – returns status
public Boolean addElement(Element e);
// good – two methods
public void addElement(Element e);
public Boolean isAdd(Element e);

Prefer exceptions over error‑code returns.

try { tryToShutDown(); } catch (DeviceShutDownError e) { logger.log(e); }
private void tryToShutDown() throws DeviceShutDownError {
DeviceHandle handle = getHandle(DEV1);
retrieveDeviceRecord(handle);
pauseDevice(handle);
clearDeviceWorkQueue(handle);
closeDevice(handle);
}
private DeviceHandle getHandle(DeviceID id) {
// ...
throw new DeviceShutDownError("Invalid handle for:" + id);
}

5. Testing

Testing validates code correctness; test code should also be clean.

5.1 TDD

Test‑Driven Development writes a failing test first, then production code just enough to pass, and refactors iteratively.

5.2 FIRST principles

Tests should be Fast, Independent, Repeatable, Self‑validating, and Timely.

5.3 Given‑When‑Then pattern

@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"));
}

6. Conclusion

Writing clean code improves readability, extensibility, development efficiency, reduces overtime, and raises developer skill level. Everyone should read "Clean Code" to enhance coding ability and mindset, and practice clean coding continuously rather than postponing refactoring.

TestingBest Practicessoftware designclean codeSOLID
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login 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.