Fundamentals 20 min read

Clean Code: Principles and Practices for Writing Maintainable Software

The article argues that clean code—characterized by readable naming, minimal comments, short single‑purpose functions, simple control flow, and well‑encapsulated classes—is essential for maintainable software, contrasting it with design patterns and architecture, and demonstrates its benefits through practical refactoring examples and a real‑world case study.

JD Retail Technology
JD Retail Technology
JD Retail Technology
Clean Code: Principles and Practices for Writing Maintainable Software

Entering the 21st century, many fundamental software engineering problems have not improved despite advances in the field. This article advocates the "beauty of code" to encourage developers to simplify and create high‑quality products.

Clean code can be discussed from many angles—high‑level languages, frameworks, algorithms, operating‑system kernels, middleware—but here we focus on the often‑overlooked discipline of code cleanliness.

From the comparison of two buildings we can see that system cleanliness is not strongly correlated with system size; it starts with the mindset.

2.1 What Is Clean Code?

Some may think discussing code basics is low‑level, but real‑world systems still suffer from code‑related failures. Clean code, as described in Robert C. Martin’s Clean Code , emphasizes readability, reduced cognitive load, single responsibility, and making development enjoyable.

2.2 Concept Comparison

2.2.1 Clean Code vs. Design Patterns Clean code aims at readability, while design patterns aim at extensibility. They are related but focus on different dimensions.

2.2.2 Clean Code vs. Clean Architecture Clean code concerns the code layer; clean architecture concerns the design layer and module boundaries.

2.2.3 Clean Code vs. Rapid Code Ideal clean code evolves with the project; it is not a static perfect artifact.

2.3 How to Achieve Clean Code

Techniques include design‑pattern usage, refactoring, code reviews, coding standards, and tooling.

2.3.1 Naming

Names for variables, functions, and classes are the foundation of clean code. Meaningful names improve readability and trust.

Examples of good and bad naming are illustrated with side‑by‑side code snippets (left: vague, right: self‑describing).

2.3.2 Comments

Comments should only exist when code cannot express intent clearly. Bad comments duplicate information, act as separators, mislead, or comment out dead code. Good comments provide legal info, intent explanations, warnings, TODOs, or API documentation.

2.3.3 Functions

Key principles: keep functions short, single‑purpose, and operate at one abstraction level. Example of a JavaScript function that mixes validation, rendering, and DOM manipulation is refactored into smaller helper functions.

function renderContent(renderInformation) {
    const element = renderInformation.element;
    if (element === 'script' || element === 'SCRIPT') {
        throw new Error('Invalid element.');
    }
    let partialOpeningTag = '<' + element;
    const attributes = renderInformation.attributes;
    for (const attribute of attributes) {
        partialOpeningTag = partialOpeningTag + ' ' + attribute.name + '="' + attribute.value + '"';
    }
    const openingTag = partialOpeningTag + '>';
    const closingTag = '</' + element + '>';
    const content = renderInformation.content;
    const template = openingTag + content + closingTag;
    const rootElement = renderInformation.root;
    rootElement.innerHTML = template;
}
function renderContent(renderInformation) {
    const element = renderInformation.element;
    const rootElement = renderInformation.root;
    validateElementType(element);
    const content = createRenderableContent(renderInformation);
    renderOnRoot(rootElement, content);
}

Function parameters should be minimized: zero, then one, then two; avoid three or more.

function saveUser(email, password) {
    const user = { id: Math.random().toString(), email, password };
    db.insert('users', user);
}
saveUser('[email protected]', 'test-pass');
class User {
    constructor(email, password) {
        this.email = email;
        this.password = password;
        this.id = Math.random().toString();
    }
    save() {
        db.insert('users', this);
    }
}
const user = new User('[email protected]', 'test-pass');
user.save();

2.3.4 Control Logic

Reduce deep nesting by using guard clauses and exceptions. Example of a heavily nested transaction processor is refactored with early returns and helper methods.

void processTransactions(List<Transaction> transactions) {
    if (isEmpty(transactions)) {
        showErrorMessage("No transactions provided!");
        return;
    }
    for (Transaction transaction : transactions) {
        processTransaction(transaction);
    }
}

void processTransaction(Transaction transaction) {
    if (!isOpen(transaction)) {
        showErrorMessage("Invalid transaction status!");
        return;
    }
    if (isPayment(transaction)) {
        processPayment(transaction);
    } else if (isRefund(transaction)) {
        processRefund(transaction);
    } else {
        showErrorMessage("Invalid transaction method!");
    }
}

2.3.5 Classes & Data Structures

Apply the Law of Demeter: a class should know as little as possible about other classes. Example of a well‑encapsulated Database class versus a violation where internal members are exposed.

class Database {
    private String uri;
    private Provider provider;
    private Connection connection;

    void connect() {
        try {
            connection = provider.establishConnection(uri);
        } catch (Exception e) {
            log.error("Failed to connect!");
        }
    }

    void disconnect() {
        connection.close();
    }

    void storeData(Data data) { /* ... */ }
}

const Database db = new Database("mysql-db:8100", sqlEngine);
db.connect();
db.storeData(data);
db.disconnect();

Class size should be small and responsibilities single. Cohesion can be measured by how many member variables each method uses.

3 Practical Case

A real‑world service method is examined for code smells: deep nesting, excessive parameters, misleading naming, duplicated code, and redundant comments. The analysis demonstrates how refactoring improves maintainability.

public ServiceResponse<List<List<Long>>> batchQueryBelongedIdsFromGivenCrowdIds(QueryCrowdIdsBatchReqDTO batchReqDTO) {
    // ...
    for (int index = 0; index < batchReqDTO.getBatchReq().size(); ++index) {
        // complex String.format with many arguments
        // duplicated "index + '_' + jimdbKey" expressions
        // ...
    }
    // ...
}

4 Conclusion

Code cleanliness directly impacts readability, project quality, and developer experience. Pursuing clean code is a continuous practice that requires regular reflection and improvement.

"The best time to plant a tree was ten years ago; the second best time is now."

software engineeringBest Practicescode qualityrefactoringclean code
JD Retail Technology
Written by

JD Retail Technology

Official platform of JD Retail Technology, delivering insightful R&D news and a deep look into the lives and work of technologists.

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.