Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The Sonar way to define a constant

Tags:

java

sonarqube

I use Sonarqube 5.1 and experiment with the “Sonar way” Java quality profile. The job is simple: I want to define a global String constant for a missing media type:

public interface Utf8MediaType {
    String APPLICATION_JSON = "application/json;charset=UTF-8";
}

However, Sonarqube tells me this is bad practice in rule squid:S1214 – Constants should not be defined in interfaces. The long text talks about implementing this interface, which I didn’t intend to, but I give in and create a class instead:

public class Utf8MediaType {
    public static final String APPLICATION_JSON = "application/json;charset=UTF-8";
}

However, this is considered to be a major design issue in rule squid:S1118 – Utility classes should not have public constructors. So it’s urging me to add a private constructor. Of course, this constructor has then to come first not to violate conventions in rule squid:S1213 – The members of an interface declaration or class should appear in a pre-defined order. I guess after that I might even get common-java:InsufficientBranchCoverage because the private constructor is not covered in tests.


These are the default rules and I feel they are a bit silly in combination. I have more examples where the defaults just don’t work for us (TestNG support is lacking). What can I do about it? What do you recommend?

  • Give in. Make it a class, add a private constructor, use introspection in the unit test. Makes the code ten times as big. For a String constant.
  • Create a list of exceptions. But doing this for each project may lead to long lists and invites people to add exceptions even for important stuff.
  • Deactivate rules. Now I would prefer not to tamper with the default profiles, because that may mean a lot of work on Sonarqube upgrades.
  • Create a profile that inherits from the default and overwrites things. It turns out that when you inherit from a profile you cannot deactivate rules. You can only add additional rules and change the configuration of rules (to lower their severity).
like image 238
Michael Piefel Avatar asked May 29 '15 07:05

Michael Piefel


1 Answers

Give in. Make it a class, add a private constructor, use introspection in the unit test. Makes the code ten times as big. For a String constant.

This is the correct approach in general. You really do not want to create a "Constants" interface. The private constructor is needed to ensure that users do not inadvertently extend or instantiate an object that should not be instantiated.

How to add test coverage to a private constructor?

Create a list of exceptions. But doing this for each project may lead to long lists and invites people to add exceptions even for important stuff.

Too much work.

Deactivate rules. Now I would prefer not to tamper with the default profiles, because that may mean a lot of work on Sonarqube upgrades.

As you said... bad idea.

Create a profile that inherits from the default and overwrites things. It turns out that when you inherit from a profile you cannot deactivate rules. You can only add additional rules and change the configuration of rules (to lower their severity).

If you set the severity to "info" it will remove it from the Technical Debt calculation. I had to do that with squid:S1213 which is raised when I sort using the default order specified by Eclipse.

like image 158
Archimedes Trajano Avatar answered Oct 19 '22 14:10

Archimedes Trajano