The term ‘Clean Code’ is used to describe source code that is easy to read, understand, and maintain. According to Michael Feathers, clean code always looks like it was written by someone who cared about it.
The concept of clean code was popularised by Robert C. Martin’s book ‘Clean Code: A Handbook of Agile Software Craftsmanship.’ According to him, reducing code duplication, achieving high expressiveness (simple and straightforward code), and creating simple abstractions from the outset are the actions that make code clean. To apply this concept in practice, this article will cover the following topics:
- How to create meaningful names?
- Functions
- Classes
- Comments
- Formatting
Creating Meaningful Names
Use names that reveal their purpose. The name of a variable, function, or class should answer all the big questions. It should say why it exists, what it does, and how it is used. Examples like calculate_area_rectangle(), temperature_celsius, and class_car make the code easier and more efficient to read.
Avoid misleading information. Programmers should avoid passing false clues that confuse the meaning of the code. We should avoid words whose meanings may deviate from what we intend. Let’s say we have a book dictionary whose variable name is booksArray. In this case, the variable name suggests an array and not a dictionary, which is the true content of the variable.
Make meaningful distinctions. Make distinctions in names so that the reader understands the differences. If we define two methods: getSummary(int id) and getSummaryInformation(int id), it is not clear the difference between one method and another. The reader of the code is forced to check the implementation of each function to understand the return of each one.
Use pronounceable names. An example of an unpronounceable name is, for example, ‘private Date genymdhms’. Use examples like ‘private Date StartDate’.
Use searchable names. Long names stand out more than short ones, and any searchable name stands out more than a constant in the code. If using short names, make them clear. Most code editors have text search functionality, and names with clear meanings ensure easier finding and differentiation during search. For example: a variable named first_fruit is much harder to find than the variable first_fruit_banana because first_fruit can list all variables of different fruits.
Pay attention to variable prefixes. The more we read the code, the fewer prefixes we see. In the end, these become invisible parts, indicating old code.
Avoid mental mapping. A difference between a smart programmer and a professional programmer is that the latter understands that clarity is fundamental. Professionals focus on writing code that others can understand, in other words, clean code. Always try to write code thinking about the next developer who will read and use it; avoid using shortcuts or unclear nomenclature that only you understand, such as using ’eml’ for ’email’ in variable declarations.
Choose class names well. Classes and objects should have names with noun(s).
Take care of your method names. Method names should have verbs.
Opt for clarity over amusement. Will programmers know what the function HolyHandsGrenade should do? Sure, it’s funny, but maybe DeleteItems would be easier to understand.
Choose one word per concept. A consistent lexicon is a great advantage for programmers who need to use your code.
Avoid puns. Avoid using the same word for two purposes. Using the same term for two different ideas is basically a pun.
Add meaningful context. There are few names that are meaningful by themselves – most are not. Therefore, you need to use names that are part of the context for the reader. For this, you place them in well-named classes, functions, and namespaces.
Functions
The first rule for functions is that they should be small, around 20 lines at most.
Functions should do one thing only, and they should do it well. One way to know if a function does more than ‘one thing’ is if you can extract another function from it based on its name, which is not just a reformulation of its implementation.
Functions should either do something or answer something, but not both. Your function either changes the state of an object or returns information about it. Doing both tasks often leads to confusion.
Function Parameters
The ideal number of parameters for a function is zero. Then comes one, followed by two. Whenever possible, avoid three parameters, as more than that can complicate code understanding and maintenance. This principle, derived from Robert C. Martin’s book ‘Clean Code,’ emphasises the importance of keeping functions simple and focused on a single task. For example, instead of passing multiple parameters to calculate the average of a list, it is preferable to pass only the list itself, making the function more cohesive and easier to understand.
Boolean Parameters
These parameters are ugly. Passing a boolean to a function is certainly a terrible practice because it immediately complicates the method signature, showing explicitly that the function does more than one thing. It does one thing if the value is true, and another if it is false. An alternative to using boolean parameters would be to create two functions, one for each case.
Classes
The first rule for classes is that they should be small, and the size of the class is measured by its responsibilities. According to Robert C. Martin, the name of a class should describe its responsibilities, respect the single responsibility principle, and that our systems consist of many small classes, not a few large classes. Each small class encapsulates a single responsibility, has a single reason to change, and contributes to a few others to obtain the desired behaviours in the system.
The author of Clean Code states that we have to structure our systems in a way that we mess up as little as possible when we update them. In an ideal system, we would incorporate new features by expanding the system and not by changing the existing code. In other words, we need to support the key class design principle, known as the Open-Closed Principle (OCP).
This principle suggests that a class should be open for extension but closed for modification. In other words, we should be able to extend the behaviour of a class without having to modify its original source code. For example, if we have a class that calculates the shipping cost for different types of products, we can extend this class by adding new specific implementations for each type of product without modifying the existing class. This keeps the code more flexible and less prone to introducing bugs when new features are added. For example, we can have a class ShippingCostCalculator with methods to calculate the shipping cost of different types of products, such as calculatePhysicalProductCost(), calculateDigitalProductCost(), etc. If we need to add a new type of product, such as a perishable product, we can extend this class by adding a new method, calculatePerishableProductCost() without modifying the existing methods.
Comments
According to Robert C. Martin, the proper use of comments allows us to compensate for our failure to express ourselves in code. We should use them because we don’t always find a way to express ourselves without them, but their use is not a reason for celebration. So, when you find yourself in a situation where you need to create a comment, think carefully and see if there is no way to express yourself through the code itself. According to the author of Clean Code, the older a comment is and the farther away from the code it describes, the more likely it is to be wrong. The reason is simple. It is not realistic for programmers to keep them up to date. The author also states that one of the most common motivations for creating comments is bad code. Better than inserting a comment is cleaning up the code!
However, certain comments are necessary or beneficial, such as:
- Legal comments (related to law and legislation);
- Informative comments;
- Comments that explain intention;
- Comments that provide clarification;
- Warnings about consequences;
- TO DO comments: notes left in the source code to indicate that a certain part of the code has not yet been implemented or is incomplete but needs to be worked on in the future;
- Comments to highlight the importance of something.
There are also comments that should be avoided:
- Redundant comments;
- Imperative comments;
- Misleading comments;
- Noisy comments;
- Credits and authorship;
- Code as comments;
- HTML comments;
- Comments with non-obvious connections to the code.
Formatting
To ensure that your code is well formatted, you should choose a set of simple rules that govern your code and then apply them consistently. If you are working in a team, then everyone should agree on a single set of formatting rules. Currently, there are automated tools to help apply these rules.
Recommendations
Each line in our code represents an expression or a structure, and each group of lines represents a complete thought.
These thoughts should be separated by blank lines. Lines of code that are closely related should appear vertically aligned. Obviously, this rule does not work for concepts in separate files. But then, closely related concepts should not be separated into different files unless there is a very good reason.
If one function calls another, they should be vertically close, and the one that calls should be above the one that is called, if possible.
We should strive to keep our lines of code short. According to Robert C. Martin, “The old Hollerith limit of 80 is a bit arbitrary, and I’m not against lines with 100 or even 120 characters. But exceeding this is probably just carelessness… I personally set 120 as my limit.”
Indentation
The author of the Clean Code book recommends indenting the code. According to him, indentation is a way to make the hierarchy of scopes visible by indenting the lines of source code according to their position in the hierarchy.
Clean Code: Final Thoughts
In summary, clarity in choosing names for functions, methods, classes, modules, and variables is crucial for understanding and maintaining the code. Avoiding puns, false clues, and funny names, while prioritising meaningful and pronounceable distinctions, not only facilitates reading but also reveals the underlying purpose of each element. Just as in writing an article, where organising thoughts results in clarity, carefully structuring code makes it readable and robust at the same time.
In the next article, we will address topics such as error handling, unit testing, and other important aspects in the pursuit of excellence in clean code. Don’t miss it!
Let's connect on social media, follow us on X!
Article written by Saulo Guerreiro, and originally published at https://kwan.com/blog/clean-code-a-comprehensive-guide-to-help-you-write-quality-code/ on May 8, 2024.
See you in the next article!
Top comments (0)