Mappa Via Marconi 20, Bussolengo (VR)
Email info@devinterface.com

Writing clean code: best practices and fundamentals

Index


Writing code does not only mean making a programme work, but also making it readable, maintainable and efficient. The concept of ‘Clean Code’ is based on a set of principles and good practices that enable developers to write code that is clear, intuitive and easy to edit. In this article, we will explore the basic principles of Clean Code, taking a cue from Robert C. Martin's famous book, "Clean Code - A Handbook of Agile Software Craftsmanship".



A foundation called Clean Code

Under the title ‘Clean Code - A Handbook of Agile Software Craftsmanship’, Robert C. Martin, also called Uncle Bob, writes in over 450 pages about the ways and means of writing good code. The book was published by Prentice Hall in 2008 and has since sold more than 160,000 copies in the English version alone.

The 17 chapters cover topics such as naming variables, writing tests and the structure of functions and classes. Each chapter has further subsections that follow a similar structure: A negative example is used to explain a messy code practice and then how to proceed in its place.

Moreover, there are summary chapters on more complex topics, such as software architecture or concurrent programming.

Code examples in the book are written in Java, so prior knowledge of the language is an advantage. Nevertheless, this is not absolutely necessary, as many of the examples are easy to understand and can be transferred to other programming languages.



What is clean code?

Clean code is code that is easy for any developer to read and understand. Each part of the code should clearly communicate its function without requiring too much effort for interpretation. Clean code is not only functionally correct, but is also structured in such a way that anyone can easily modify and extend it.

A famous quote by Grady Booch states: ‘Clean code reads like well-written prose.’ This means that the code should be intuitive and self-explanatory, reducing the need for superfluous comments.

But how can one improve the readability of code and make it accessible to other developers? Robert C. Martin's book answers this question by providing a number of best practices, such as using clear names for variables and methods, reducing complexity and writing functions with one responsibility. Even small details, such as avoiding returning null or abusing switch statements, can make a big difference in the quality of the code.

Let us consider the following code:

ListName list = new ListName();
list.add(‘Alice’);
list.add(‘Bob’);

if (list.size() > 0) {
    System.out.println("First element: ’ + list.get(0));
}

At first glance, the code seems to work correctly, but it can be improved. Instead of, for example, manually checking the size of the list before getting the first element, we could delegate this logic directly to the ListName class:

How about directly providing a method to get the first element without having to manually check the size of the list?

ListName list = new ListName();
list.add(‘Alice’);
list.add(‘Bob’);

System.out.println("First element: ’ + list.first());

In this way, the code becomes more readable and intuitive. Furthermore, the logic for handling the absence of elements can be hidden within the ListName class, reducing the risk of errors and making the code more maintainable.



Clean code principles

How do you write clean code? It is a matter of taking into consideration certain guiding principles of programming. These are less about specific instructions on what one should programme in a certain situation and how, and more about a reflective look at one's own working practice as a developer. The significance of clean code is therefore controversial within the developer community: what is ‘clean’ for one group of programmers may be considered ‘dirty’ by others. The degree to which a code is clean is therefore always, to a certain extent, subjective. Below we present some established principles of clean code that most developers find useful.


Simplest possible code: KISS

KISS (Keep it simple, stupid) is one of the oldest principles of code cleaning. It was used by the US military in the 1960s. KISS reminds programmers to design code as simply as possible. Unnecessary complexity must be avoided. In programming, there is never only one way to solve a problem. A task can always be expressed in different languages and formulated with different commands. Programmers following KISS must therefore always ask themselves whether they can solve a given problem in a simpler way.


Avoid unnecessary repetition: DRY

DRY (Don't repeat yourself) is, in a manner of speaking, a concretisation of KISS. A clean code according to the DRY principle means that a function must have a unique and therefore unambiguous representation within the overall system. Duplication must be avoided at all costs, so that the same code does not have to be rewritten several times. This way, development time is saved and errors can only be corrected once.

Please note: The opposite term to DRY is WET (We enjoy typing). Code is called WET when unnecessary duplications occur in the code.

The following example illustrates the DRY-Clean-Code principle. Let us imagine that we have to calculate the discount on two types of products in an online shop. 

public class Discount {
    public static double calculateDiscountElectronics(double price) {
        return price - (price * 0.10); // 10% discount on electronics
    }

    public static double calculateDiscountElectronics(double price) {
        return price - (price * 0.15); // 15% discount on clothing
    }
    
    public static void main(String[] args) {
        double priceElectronics = 1000;
        double priceClothing = 200;
        
        System.out.println("Electronics discount price: ’ + calculateDiscountElectronics(priceElectronics));
        System.out.println("Discounted price clothing: ’ + calculateDiscountClothing(priceClothing));
    }
}
The problem here is repetitive code that is difficult to maintain. If we have to change the logic for calculating the discount, we have to modify each method separately. Now we see an improved version, which follows the DRY principle and makes the code more maintainable:

public class Discount {
    public static double calculateDiscount(double price, double percentageDiscount) {
        return price - (price * percentageDiscount / 100);
    }

    public static void main(String[] args) {
        double priceElectronics = 1000;
        double priceElectronics = 200;
        
        System.out.println("Electronics discount price: ’ + calculateDiscount(priceElectronics, 10));
        System.out.println("Discounted price clothing: ’ + calculateDiscount(priceClothing, 15));
    }
}
In the latter case, there is no more duplication, because the logic of the discount is centralised in one method. If we need to change the discount formula, we only do so in one place. Finally, we can easily add new discounts without writing new methods.


Single Responsibility Principle (SRP)

This principle is quickly explained: each unit of code must have a clearly defined task. This increases readability and simplifies testability. 

For better understanding, here is an example: let us imagine a class that is responsible for handling orders and printing invoices. According to the principle of single responsibility, this class should be divided into two separate classes: 

  • Order - handles orders.
  • Invoice printer - prints invoices.
In other words, each class has only one task. This makes the code clearer and easier to maintain.


Single Level of Abstraction (SLA)

The Single Level of Abstraction (SLA) states that a function should operate at a single level of abstraction. Mixing different levels within the same function can compromise readability and make the code difficult to understand.

As an example to illustrate this concept, let us imagine the driving function of a car. A method called drive() should deal exclusively with driving logic, such as accelerating, braking and steering. Yet, if low-level implementation details, such as engine activation or combustion management, were to be included within the same method, different levels of abstraction would be mixed in, making the code more complex to read and maintain.

A convenient indication of different abstraction levels is the presence of code blocks separated by comments or spacing. By moving such blocks into separate functions, the structure and readability of the code can be improved.



Composition by inheritance

While inheritance is a fundamental concept of object-oriented programming, its improper use can make code rigid and difficult to test. If a parent class is too dependent on its child classes, the code becomes more fragile and prone to maintenance problems.

An effective alternative is composition, which achieves the same code reuse without introducing excessive dependencies between classes. Rather than extending a class, it is preferable to create independent classes that collaborate with each other through well-defined interfaces.



Coherence in the code

Observing the principles of the Clean Code is not sufficient if the code is not consistent. A code in which different styles or inconsistent conventions are adopted becomes difficult to read and maintain. For ensuring consistency, it is important to define and adhere to clear standards, including:


  • Uniform naming conventions for variables, methods and classes.
  • Predictably organised code structure.
  • Use of recurring design patterns for similar problems.

Consistency makes it easier to understand the code and reduces the time needed to familiarise oneself with new designs.


Conclusion

Writing Clean Code is not just a matter of aesthetics, but a fundamental practice to ensure that software is readable, maintainable and scalable over time. Following principles such as KISS, DRY, SRP, SLA and favouring composition over inheritance, developers can improve the quality of their code and reduce maintenance costs.