Разрешить AvoidLiteralsInIfCondition в методе интерфейса по умолчанию - PullRequest
1 голос
/ 12 февраля 2020

Правило PMD AvoidLiteralsInIfCondition отмечает проблему, когда в условии используется литерал (например, 7, 10) (например, if (x > 7)). В классе я обычно решаю это путем создания private static final для хранения значения. Однако, если литерал используется в методе интерфейса по умолчанию, я не могу создать private static final в интерфейсе. Как мне исправить AvoidLiteralsInIfCondition?

Я знаю, что могу использовать // NOPMD или @SuppressWarnings, но это не решает проблему. Я не извлекаю выгоду из более ясного кода, используя private static final.

Вот некоторый код, который демонстрирует проблему.

public interface UTF8Length
{
   default int getUTF8Length(char value)
   {
      if (value <= 0x007F)  // PMD flags a problem with 0x007F
         return 1;

      if (value <= 0x07FF)  // PMD flags a problem with 0x07FF
         return 2;

      return 3;
   }
}

1 Ответ

1 голос
/ 19 февраля 2020

Как предложено в комментариях OP, вы могли бы перенести ваши константы во внешний класс:

public class ConstantHelper {
    public static final int TWO_BYTE_MAX_CP = 0x7FF;
}

Тогда в методе по умолчанию вашего интерфейса вы можете сделать это без нарушения PMD:

if (value <= ConstantHelper.TWO_BYTE_MAX_CP) { // No PMD issue with this.
    return 2;
}

Это, вероятно, хорошо для вашего примера, но есть несколько руководящих принципов:

  • Вывод константы в класс констант не является хорошим подходом, если эта константа является только подробностью реализации для вашего интерфейса. и вряд ли когда-либо будет использоваться какими-либо другими классами или интерфейсами. Создание нового класса констант исключительно для удаления предупреждения PMD является сомнительным подходом.
  • Вывод константы в класс констант не является хорошим подходом, если значение может измениться в будущем, поскольку это изменение может также повлиять на другие классы. В этом случае похоже, что вы ссылаетесь на значения Unicode, которые почти наверняка никогда не изменятся, так что здесь это не проблема.

Альтернативный подход заключается в наличии локальных объявлений в вашем методе по умолчанию, и используйте их:

default int getUTF8Length(char value) {

    final int oneByteMaxCP = 0x007F; // PMD flags AvoidFinalLocalVariables

    if (value <= oneByteMaxCP) { 
        return 1;
    }

    final int twoByteMaxCP = 0x007FF; // PMD flags AvoidFinalLocalVariables

    if (value <= twoByteMaxCP) { 
        return 2;
    }

    return 3;
}

Если вы сделаете это, вы оскорбите PMD другим способом (« AvoidFinalLocalVariable: избегайте использования конечных локальных переменных, превратите их в поля »), но преимущества являются:

  • Вам не нужен внешний класс.
  • Я считаю код немного более понятным, хотя это личный вкус.
  • Эти локальные декларации являются самостоятельными документирование и - в отличие от комментариев - они должны быть правильными, чтобы код работал правильно.
  • Эти локальные объявления являются полностью частными. Это может быть не выгодно для вашего указанного c примера, но легко представить другой сценарий ios, где вы хотите использовать константы в методе по умолчанию, и не делиться ими с кем-либо еще.

Так что, если значения констант, которые вы хотите вывести, не нарушают двух принципов, описанных выше, то создайте класс констант. В противном случае объявите свои константы локально и примите, что вы получите AvoidFinalLocalVariable предупреждений от PMD, потому что написание ясного, понятного и обслуживаемого кода важнее, чем удаление предупреждений PMD.

...