If you’ve followed us for a while, you most likely noticed that we changed the way we describe what we do: from “code quality” to “continuous code inspection,” then “code quality and code security”… It feels like in the last couple of years, we finally managed to settle on what we had been looking for from the beginning: Clean Code.
But what is Clean Code, and what does it encompass?
This is about causes and (clean) code
The problem that we solve at Sonar is a big problem, which also has a lot of ramifications. We help to improve productivity, reduce risk and downtime, and increase code ownership. We impact the source code but also, of course, indirectly, the software itself.
In the past, when describing what we do, we mixed all of these descriptions, leading to inconsistencies (in the best case) and difficulty connecting the dots for our community. Around two years ago, we decided to solve this issue and launched an internal initiative to explain better what we do.
To make a (very) long story short, we eventually settled on three things:
- Our focus is exclusively on code, and this is how we should describe what we do
- We should focus on the cause of issues, not on their potential consequences
- We name what we do Clean Code
Once these decisions were made, you started to see “Clean Code” appearing here and there. Problem solved? Not quite. We know what we do and our focus, but we still have a gap: how do we classify the nonconformities to Clean Code if we want to remain rooted in the actual code and not in the consequences?
So, we started another project to develop a classification, aka taxonomy.
The Clean Code Taxonomy
The foundation of the Clean Code taxonomy is code that is clean and code that has the following properties: consistent, intentional, adaptable, and responsible.
In other words, whenever code has an issue, this issue will “break” one of these categories.
Let’s now review the four categories in detail.
Consistent
Code should be consistent and follow a common style. This means that all the code, even if worked on by different people over time, should have a similar appearance and adhere to established patterns. This consistency should apply not only within a specific codebase but also ideally across the entire programming language ecosystem.
Example 1:
Code should be formatted. For example, even if you are not familiar with Java code, you probably expect to see consistent indentation in the following code. It’s not about tabs versus spaces, it’s about consistency.
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S1120/java
Example 2:
Code should be idiomatic and follow syntax conventions. For example, in C++ >= 11 type aliases can be declared via either typedef
or using
, however, you should prefer the latter for modern code.
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S5416/cfamily
Example 3:
Code should be easily identifiable. Consider code written in C#, where PascalCase is used for all identifiers except parameter names. In this context, using underscores or other casing styles to differentiate words in an identifier is unacceptable.
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S101/csharp
Intentional
Intentional code reads like it was written with attention and care to convey its purpose. The code should be self-explanatory and only allow for one interpretation. Every instruction makes sense, adequately forms, and simply conveys its behavior. The code should not be ambiguous or leave room for guessing.
Example 1:
Code should be clear and straightforward. Take this Python code as an example, and you'll notice that variables `message
` and `i
` are defined but never used. When readers encounter such cases, they might wonder if it's a coding error that was supposed to do something else or if it's just leftover code that can be safely deleted.
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S1481/python
Example 2:
Code should only contain instructions that are logically sound. For instance, in JavaScript, there's `NaN
`, which stands for 'Not-a-Number.' It represents a numeric data type that isn't a valid number. `NaN
` is not equal to any value, even itself, and this behavior can lead to unexpected results.
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S2688/javascript
Example 3:
Code should be thorough. An example in PHP is the use of secure cookies. The method `setcookie
` allows you to create cookies that can be transmitted via HTTP by default, making their contents readable. Since cookies often carry sensitive data, it's important to ensure they are transferred securely to fulfill their intended purpose. You need to pass a last argument to enable HTTPS only.
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S2092/php
Example 4:
Code should be efficient and not waste resources needlessly. For example, most Linux package managers create a cache by default when working with Docker. Unless you remember to remove these files in your Dockerfile, they will increase the size of your image without providing any additional value.
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S6587/docker
Adaptable
When code is adaptable, it’s segmented and organized in a way that makes it easier to manage and see the relationships between code. The code should be structured for easy and confident evolution. It should simplify the process of extending or repurposing its parts and encourage localized changes without causing unintended side effects.
Example 1:
Code should be distinct and minimize duplication. For instance, duplicating string literals raises the risk of errors when making updates since each occurrence must be changed separately. A better approach is to use constants that can be referenced from multiple places, allowing updates to be made in a single location. Here’s an example using Ruby.
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S1192/ruby
Example 2:
Code should be focused, with each unit having a specific and limited scope. For instance, in Swift, it's best practice to keep types, such as classes, in separate files. This helps prevent an excessive accumulation of instructions or an overwhelming amount of complexity within a single file.
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S1996/swift
Example 3:
Code should be modular, and a key aspect of this is encapsulation. In Object-Oriented languages, encapsulation often involves making fields private. This way, the class retains control over the details of its internal representation and prevents other parts of the code from having too much knowledge about its inner workings.
However, there are multiple levels of encapsulation, and even minor improvements can make a difference. For example, if you're working with VB.Net, which allows publicly accessible fields, it's better to avoid using them and instead use properties. Properties work similarly to fields but are part of the interface and can be overridden by getters and setters.
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S2357/vbnet
Example 4:
Code should include tests that instill confidence when making changes. Ideally, we should prioritize comprehensive functional test coverage. However, accurately measuring it can be challenging. Nonetheless, it's essential to ensure that test coverage is not so low that you can fear modifying the code.
There are odd examples, where you have a test folder or test files, without actual test cases inside, which can mislead other developers: https://sonarsource.github.io/rspec/#/rspec/S2187/
There are also cases where tests are skipped and accidentally committed like that, which might go unnoticed if not tracked in any way: https://sonarsource.github.io/rspec/#/rspec/S1607/
Responsible
Code should be mindful of its ethical obligations concerning data and its potential influence on societal norms. Whether it's a matter of professional duty, providing peace of mind, or championing inclusivity, the bottom line is that code should not present an ongoing risk of unintentionally harming third parties. This applies regardless of whether developers bear immediate liability.
Example 1:
Code should avoid hard-coding secrets. While it may be tempting for internal applications or when you believe the source code is secure, the truth is that responsible code should never store secrets. If malicious parties access the code, secrets can be inadvertently exposed and exploited. This risk not only affects the software itself. It can have far-reaching consequences, impacting the system and third parties.
Here’s a simplified example using Go:
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/S2068/go
Example 2:
Code should be lawful. It should respect basic licensing and copyright regulations. It exercises the creator’s rights and honors other’s rights to license their code.
One common example is companies enforcing copyright headers in their code files:
Read more: https://sonarsource.github.io/rspec/#/rspec/S1451/
Example 3:
Code should be respectful and inclusive. It should avoid employing discriminatory or offensive language and opt for inclusive terminology whenever a suitable alternative communicates the same meaning.
A regular expression can be used to track identifier names and comments, for example:
Non-compliant code:
Compliant code:
Read more: https://sonarsource.github.io/rspec/#/rspec/?query=naming%20convention
And so what?
First, we feel very good about this classification (by the way, each category also breaks down into subcategories). We think this is a solid foundation for Clean Code.
Now, we want to gradually roll out this detailed definition of Clean Code in Sonar products. Starting with the way we classify issues in the code. The first step is already available in SonarQube Cloud, SonarQube for IDE, and SonarQube Server 10.2.
In addition, we will start working on classifying the consequences for the software when the code isn't clean, such as security, reliability, maintainability, etc.
See the community announcement for screenshots and more information: https://community.sonarsource.com/t/introducing-clean-code-in-our-products/98431
Share your feedback!