How a 100k‑Bonus Colleague Writes Elegantly Clean Code
The article explains why clean, well‑structured code matters for team productivity, covering naming, class design, function design, SOLID principles, testing practices such as TDD and the FIRST rule, and shows how tools like SonarLint can help maintain code quality.
1. Why Keep Code Clean?
Untidy code accumulates over time, reducing productivity and leading to hard‑to‑extend code, crashes, overtime, higher hiring costs, and even company failure.
1.1 Start Clean from the Beginning
Write clean code from day one and refactor any messy parts immediately; never postpone cleanup.
later equal never1.2 What Makes Code Clean?
High readability – code should read like prose.
Avoid duplicate code.
Follow design‑pattern principles (SOLID, etc.).
Single Responsibility
Open/Closed
Liskov Substitution
Dependency Inversion
Interface Segregation
Law of Demeter
Composition over Inheritance
2. Naming
Good names improve readability, lower understanding cost, and reduce overtime.
2.1 Bad Naming Example
public interface Animal {
void abc();
}The method name abc gives no clue about its purpose.
Improved version:
public interface Animal {
void cry();
}Now callers understand the method’s intent.
2.2 Naming Pitfalls
Inconsistent prefixes (e.g., queryAllStudent vs findOneById). Refactor to a consistent style:
public interface StudentRepository extends JpaRepository<AlertAll, String> {
Student findOneById(@Param("id") String id);
List<Student> findAll();
}Redundant words (e.g., getXxx for single objects, listXxx for collections). Use concise prefixes.
// Single object
getUser();
// Multiple objects
listUsers();3. Classes
Clean classes should satisfy:
Single Responsibility
Open/Closed
High Cohesion
3.1 Single Responsibility
A class should have only one reason to change. Overly large classes usually violate this.
Lower complexity
Improve readability
Enhance maintainability
Reduce change‑induced risk
Determine if a class is too large by checking whether its name can accurately describe all its duties. Example of a class with multiple responsibilities:
public abstract class Sql {
// SQL operation
public abstract void insert();
// Statistics of SQL operations
public abstract void countInsert();
}Refactor the statistics part into a separate class:
public abstract class CountSql {
public abstract void countInsert();
}3.2 Open/Closed Principle
Software should be open for extension but closed for modification. Adding new logic must not require changing existing code.
Violation example:
public abstract class Sql {
public abstract void insert();
public abstract void update();
public abstract void delete();
}To add a query operation, the class must be modified, breaking the principle.
Refactored version using inheritance:
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 */ }
}Now new behaviours can be added by creating new subclasses without touching existing code.
3.3 Cohesion
When most methods use the same set of variables, the class has high cohesion. High cohesion leads to smaller, single‑purpose classes.
4. Functions
To keep functions clean, ensure:
Do one thing only.
Have descriptive names.
Accept tidy parameters.
Return appropriate values.
4.1 Do One Thing
Example of a bloated function (≈135 lines) handling validation, compression, and result reporting:
public class PicService {
public String upload() {
// validation code (≈80 lines)
// compression code (≈50 lines)
// return status (≈5 lines)
return "0";
}
}Refactor by extracting each responsibility into its own method:
public String upload() {
check();
compress();
return "0";
}
private void check() { /* validation */ }
private void compress() { /* compression */ }4.2 Function Naming
Names should convey intent. Bad example:
public String addCharacter(String originString, char ch);It is unclear whether the character is appended, prepended, or inserted.
Better alternatives:
// Append to the end
public String appendCharacter(String originString, char ch);
// Insert at a specific position
public String insertCharacter(String originString, char ch, int insertPosition);4.3 Parameters
Fewer parameters improve understandability; encapsulate when there are more than three.
public List<Student> findStudent(int age, String name, String country, int gender);
// Encapsulated version
public List<Student> findStudent(Student criteria);Avoid Boolean flag parameters; split into separate methods.
// Flag version
render(Boolean isSuite);
// Refactored
renderForSuite();
renderForSingleTest();Do not use output parameters; let methods return results directly.
public void findStudent() { Student s = new Student(); doSomething(s); return s; }
// Refactored
student.doSomething();4.4 Return Values
Separate commands from queries.
public Boolean addElement(Element e); // mixes action and query
// Refactored
public void addElement(Element e);
public Boolean isAdd(Element e);Prefer exceptions over error‑code returns to avoid deep nesting.
// Error‑code style
if (handle != DeviceHandle.INVALID) { /* ... */ } else { logger.log("Invalid handle"); }
// Exception style
try { tryToShutDown(); } catch (DeviceShutDownError e) { logger.log(e); }4.5 Writing Clean Functions
Start with a working implementation, then refactor immediately—"later equal never".
4.6 Code‑Quality Tools
SonarLint helps discover issues such as duplicate code, potential null‑pointer exceptions, and improper date handling, providing concrete suggestions and enabling metrics like bug rate and duplication rate.
5. Tests
Testing validates code correctness; test code should also be clean.
5.1 Test‑Driven Development (TDD)
TDD is a core agile practice that drives design. Benefits: early usable product, fewer bugs. Drawback: test code can be twice the size of production code.
Write a failing test before production code.
Write just enough test to be non‑compilable.
Develop production code until the test passes.
5.2 FIRST Principle
Fast – tests run quickly.
Independent – tests do not depend on each other.
Repeatable – tests run the same everywhere.
Self‑validating – tests return a boolean result.
Timely – tests are written before production code.
5.3 Given‑When‑Then Pattern
Structure test code as:
Given – set up data.
When – execute the code under test.
Then – verify the outcome.
@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 in IDEA
Two plugins can generate test scaffolding:
SquareTest (paid)
TestMe (free)
6. Conclusion
Writing clean code improves readability and makes the codebase easier to extend.
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.
Programmer XiaoFu
xiaofucode.com – a programmer learning guide driven by the pursuit of profit
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.
