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

<span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">interface</span> <span style="font-weight:bold;color:#fff;">Animal</span> {<br/>    <span style="color:#f92672;font-weight:bold;">void</span> abc();<br/>}

The method name abc gives no clue about its purpose.

Good naming:

<span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">interface</span> <span style="font-weight:bold;color:#fff;">Animal</span> {<br/>    <span style="color:#f92672;font-weight:bold;">void</span> cry();<br/>}

Now callers understand the method’s intent.

2.2 Naming consistency

<span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">interface</span> <span style="font-weight:bold;color:#fff;">StudentRepository</span> <span style="color:#f92672;font-weight:bold;">extends</span> <span style="font-weight:bold;color:#fff;">JpaRepository</span><AlertAll, String> {<br/>    Student findOneById(@Param("id") String id);<br/>    List<Student> queryAllStudent();<br/>}

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

<span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">interface</span> <span style="font-weight:bold;color:#fff;">StudentRepository</span> <span style="color:#f92672;font-weight:bold;">extends</span> <span style="font-weight:bold;color:#fff;">JpaRepository</span><AlertAll, String> {<br/>    Student findOneById(@Param("id") String id);<br/>    List<Student> findAll();<br/>}

2.3 Redundant naming

// getXxx() – get a single object<br/>getXxx();<br>// listXxx() – get multiple objects<br/>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.

<span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">class</span> Sql {<br/>    // operate SQL<br/>    <span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">void</span> insert();<br/>    // count SQL operations<br/>    <span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">void</span> countInsert();<br/>}

Extract counting to a separate class:

<span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">class</span> CountSql {<br/>    <span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">void</span> countInsert();<br/>}

3.2 Open‑closed principle

Software should be closed for modification but open for extension.

<span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">class</span> Sql {<br/>    <span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">void</span> insert();<br/>    <span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">void</span> update();<br/>    <span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">void</span> delete();<br/>}

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

<span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">class</span> Sql {<br/>    <span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">abstract</span> <span style="color:#f92672;font-weight:bold;">void</span> generate();<br/>}<br/><br/><span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">class</span> CreateSql <span style="color:#f92672;font-weight:bold;">extends</span> Sql {<br/>    @Override<br/>    <span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">void</span> generate() { /* implementation */ }<br/>}<br/><span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">class</span> UpdateSql <span style="color:#f92672;font-weight:bold;">extends</span> Sql {<br/>    @Override<br/>    <span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">void</span> generate() { /* implementation */ }<br/>}

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

<span style="color:#f92672;font-weight:bold;">public</span> <span style="color:#f92672;font-weight:bold;">class</span> PicService {<br/>    <span style="color:#f92672;font-weight:bold;">public</span> String upload() {<br/>        // validate image – ~80 lines<br/>        // compress image – ~50 lines<br/>        // return status – 0/1 – ~5 lines<br/>        return "0";<br/>    }<br/>}

Refactor into smaller steps:

<span style="color:#f92672;font-weight:bold;">public</span> String upload() {<br/>    check();<br/>    compress();<br/>    return "0";<br/>}

4.2 Function naming

<span style="color:#f92672;font-weight:bold;">public</span> String addCharacter(String originString, <span style="color:#f92672;font-weight:bold;">char</span> ch);

Better names indicate intent:

// append to end<br/>public String appendCharacter(String originString, <span style="color:#f92672;font-weight:bold;">char</span> ch);<br>// insert at position<br/>public String insertCharacter(String originString, <span style="color:#f92672;font-weight:bold;">char</span> ch, <span style="color:#f92672;font-weight:bold;">int</span> 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);<br/>// after wrapping<br/>public List<Student> findStudent(Student student);

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

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

4.4 Return values

Separate commands from queries:

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

Prefer exceptions over error‑code returns.

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

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<br/>public void shouldReturnItemNameInUpperCase() {<br/>    // Given<br/>    Item mockedItem = new Item("it1", "Item 1", "This is item 1", 2000, true);<br/>    when(itemRepository.findById("it1")).thenReturn(mockedItem);<br/>    // When<br/>    String result = itemService.getItemNameUpperCase("it1");<br/>    // Then<br/>    verify(itemRepository, times(1)).findById("it1");<br/>    assertThat(result, is("ITEM 1"));<br/>}

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.

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.

testingbest practicesclean 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

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.