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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
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.
