Skip to main content

Do not judge a design by sonar coverage

Greetings!

I have been using SonarQube as a quality tool for quite some time now. It is used for continuous inspection of code quality to perform automatic reviews with static analysis of code to detect bugs, code smells, and security vulnerabilities.

Eventhough the intention is to detect issues, top level managers, architects, etc use it to measure team's working quality progress in their visual boards. As they are usually busy people they will not have time to look into real code and to see the real issues there. What happen then? developers will start to write "sonar satisfy" codes.

I have seen very unreadable bad codes with zero sonar quality issues. And also there are good quality codes with some unnecessary sonar issues. Reason for that is it can detect prefined rules but not all design flows.

If you want to be a good developer, don't try to write "sonar quality" code, instead use "clean codes" and get the Sonar support when necessary.

Let's discuss some of the misleading sonar rules.

1. Large methods

Sonar will correctly complain if your method is too large.
Common solution: Split the method into few private methods, create several helpers and utils and "skip" the sonar rule.
Better solution: Solution will depend on the logic you are building. You need to check whether you are breaking any design principle like SRP, OCP. By doing so, you will understand you can write a better code by using OOP practices with design patterns. Once you apply proper design principles, you will notice that there are places to apply standard patterns like Template, Command, etc.

2. if/else conditions

Sonar will complain about multiple branching levels which is surely a problem.
Common solution: create private methods and call those.
Better soluiton: If/else conditions are candidates for polymorphism. If you carefully study your conditions, you will see you can create an abstration around it. This might end up with a simple factory, or even more advanced solutions like Template, CoR, Command pattern. (read)

3. Loops

for loop, while loop, etc will introduce large methods doing multiple things.
Common solution: use private methods.
Better solution: Look for Java 8 features. As an example you can write a stream, forEach to solve this. However this might get complicated. You are doing many things inside the loop. I wrote an Iterator sometime ago to handle this (read).

4. try/catch

It is kind of mistake in Java, forcing to use try/catch to handle exceptions, which ends up ugly looking codes.
Common solution: nothing, just surround the logic with try/catch block.
Better solution: If you are lucky enough to use AOP, you can create an aspect to solve this. What if not? you can use a Decorator. Still, this looks like more work. How about lending functional programming's assistance? I'll solve this using an Execute Around functional pattern.

5. Large classes

How can you escape from this?
Common solution: Bunch of helpers, utils.
Better solution: Think about basic OOP principles and SOLID principles. Are you breaking any of the principles? then solve it one by one. Look for abstrations, compositions. You will end up creating a beautiful code without knowing. Do not worry if you are a novice to design patterns. You have a better code with better principles.

There are some design issues which are not caught by sonar.

7. Helpers, Utils

Sonar rule does not complain for this even though it's a violation in OOP paradigm
Better solution: Helpers, utils are mainly created because developers do not understand where to put that common logic. Easiest solution is to go for a helper or util. However, these belongs to domain classes. If you do not have domain classes, try to create domain specific structure, domain services.

8. Hidden domain logics

Is there a Sonar rule for this?
Developers are scared to touch the legacy code because something will fail. However, why it fails? because of unknown/ hidden business logics. This might be a suprise but that is the truth. Not just legacy code, many developers write procedural codes so that they hide useful business logics without knowing. There might be carefully written patterns also. Still if it hides the core business logics, it will haunt you in future.
The better way to do this is to extract the business logic into use cases with business naming (ubiquitous language). Your code should reveal your business intentions.

9. Dependencies

Can I have a sonar rule for this 😉
When you have multiple modules, it is very common to use other modules classes/services within your logic. This is wrong. You are violating DIP. Your business logic should not depend on other entities. Instead of relying on them, invert them (will try to write on this later). Do not introduce unnecessary coupling into your domain.

Summary

Having zero sonar issues does not quarantee that you have a quality code base. People can/do easily cheat those rules. Use sonar to adhere to common guidelines. Design with standard practices. Read Uncle Bob's books 😉

Happy coding ⌣