Clean Code Practices: Naming, Classes, Functions, and Testing
This article explains why clean code matters and provides practical guidelines on naming, class design, function design, and testing—including principles, refactoring examples, and tool recommendations—to help developers write more readable, maintainable, and robust Java code.
1 Why Keep Code Clean?
Unclean code reduces productivity over time, leading to hard‑to‑extend code, program crashes, overtime, increased company costs, and even potential failure.
1.1 Start Clean from the Beginning
Write clean code from the start and refactor any messy parts immediately; avoid the mindset of fixing it later.
later equal never
1.2 What Makes Code Clean?
Clean code should be highly readable, avoid duplication, and follow design‑pattern principles such as Single Responsibility, Open‑Closed, Liskov Substitution, Dependency Inversion, Interface Segregation, Demeter, and Composite Reuse.
2 Naming
Good naming improves readability, reduces understanding cost, and lowers overtime.
2.1 Bad Naming Practices
Examples of meaningless names:
public interface Animal { void abc(); }The method name abc gives no clue about its purpose.
Improved naming:
public interface Animal { void cry(); }Now the purpose is clear.
2.2 Inconsistent Naming
Inconsistent method names cause confusion:
public interface StudentRepository extends JpaRepository
{
Student findOneById(@Param("id") String id);
List
queryAllStudent();
}After standardising:
public interface StudentRepository extends JpaRepository
{
Student findOneById(@Param("id") String id);
List
findAll();
}2.3 Redundant Naming
Avoid unnecessary words in names, e.g., using getXxx for single objects and listXxx for collections.
3 Classes
Clean classes should satisfy Single Responsibility, Open‑Closed, and high cohesion.
3.1 Single Responsibility
Classes should be small and have only one reason to change, reducing complexity and improving maintainability.
How to determine if a class is short enough?
If a class cannot be described by a precise name, it is likely too large.
Example of a class with multiple responsibilities:
public abstract class Sql {
// operate SQL
public abstract void insert();
// count inserts
public abstract void countInsert();
}Refactored into two classes:
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() { /* ... */ } }3.2 Open‑Closed Principle
Code should be open for extension but closed for modification; adding new logic should not require changing existing classes.
3.3 Cohesion
High cohesion means methods and variables are tightly related, forming a logical whole.
4 Functions
Clean functions should do one thing, have good names, clean parameters, and clear return values.
4.1 Do One Thing
Before refactoring, a function may handle validation, compression, and result generation in one method:
public String upload() {
// validate image (80 lines)
// compress image (50 lines)
// return status (5 lines)
return "0";
}After refactoring:
public String upload() {
check();
compress();
return "0";
}4.2 Function Naming
Names should be descriptive; for example, appendCharacter vs. addCharacter clarifies intent.
4.3 Parameters
Keep parameters few; encapsulate when exceeding three, and avoid Boolean flag parameters that hide multiple responsibilities.
4.4 Return Values
Separate commands from queries and prefer throwing exceptions over returning error codes.
4.5 Writing Such Functions
Write functional code first, then refactor immediately—"later equal never".
4.6 Code Quality Tools
Tools like SonarLint can detect issues such as duplicate code, potential NPEs, and suggest using LocalDate / LocalTime for dates.
5 Testing
Testing validates code correctness; test code should also be clean.
5.1 TDD
Test‑Driven Development encourages writing failing tests before production code, ensuring rapid feedback.
5.2 FIRST Principles
Tests should be Fast, Independent, Repeatable, Self‑validating, and Timely.
5.3 Test Code Patterns
Use the given‑when‑then pattern for readable tests.
/**
* If an item is loaded from the repository, its name should be transformed to uppercase.
*/
@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 Auto‑Generating Tests
IDEA plugins such as Squaretest (paid) and TestMe (free) can generate unit tests automatically.
References:
Book: <<代码整洁之道>>
https://www.cnblogs.com/sunny3158/p/16353643.html
https://blog.csdn.net/qq_42289636/article/details/108762981
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.