Статьи

5 очень критических, но редко используемых правил PMD

Просматривая статистику использования правил на Techdebt.org, я с удивлением обнаружил критические правила PMD, которые, похоже, игнорируются. Вот презентация 5 из них с объяснением того, что они проверяют. У всех этих правил есть две общие черты:

  • Их неуважение может привести к огромным проблемам в вашем приложении;
  • Статистика их использования на удивление низкая.

Для каждого правила вы также найдете статистику его использования (процент проекта, в котором используется правило, в соответствии с Techdebt.org) и набор правил PMD, где вы можете найти правило. Вы можете не узнать ничего нового, но не забудьте проверить свой профиль качества, чтобы убедиться, что вы используете их;)

 

ReturnFromFinallyBlock

Использование: 7,75% Набор правил PMD: базовый

Это правило находит возвращение в блоках finally . Это определенно критическая ошибка, поскольку она может отбрасывать исключения. Если исключение, отмеченное или не отмеченное, выбрасывается в блок try, возвращение в блоке finally отклоняет его.

Пример: следующий код печатает только «Наконец».

   public static void main(final String[] args) {
        try {
            foo();
        }
        catch (final Exception e) {
            System.out.println("Catch");
        }
    }
    public static int foo() throws Exception {  
        try {
            // some clever code that throws an Exception
            throw new Exception();
        }
        finally {
            System.out.println("Finally");
            return -1;
        }
    }

 

DoNotThrowExceptionInFinally

Использование: 7,51% Набор правил PMD: строгие исключения

Создание исключения в блоке finally может привести к путанице и затруднить отладку кода. Это также отменит любое предыдущее исключение. Например, если неожиданное исключение, такое как NullPointerException , генерируется в блоке try , оно будет отброшено. Это может скрывать ошибки, что приводит к болезненным задачам отладки …

Пример: следующий код выводит «Gotcha!» когда вы хотите, чтобы он потерпел крах с NPE.

    public static void main(final String[] args) {  
        try {
            foo();
        }
        catch (final IOException e) {
            System.out.println("Gotcha!");
        }
    }
    public static void foo() throws IOException {
        try {
            // some clever code...
            // unexpected exception
            throw new NullPointerException();
        }
        finally {
            // do something
            // throw IOException, the NullPointerException is discarded.
            throw new IOException();
        }
    } 

 

DontCallThreadRun

Использование: 1,08% Набор правил PMD: базовый

Метод run () выполняется в текущем потоке. Чтобы создать новый поток, должен использоваться метод start () , который обычно является предполагаемым поведением. Это правило также присутствует в Findbugs с именем «RU_INVOKE_RUN» . Одно из этих правил должно быть активировано.

Пример: этот код иллюстрирует поведение thread.run () и thread.start ().

    public static void main(final String[] args) {
        System.out.println("Main thread: " + Thread.currentThread().getId());
        final FooThread thread = new FooThread();
        thread.run();
        thread.start();
    }
    public static class FooThread extends Thread
    {
        @Override
        public void run() {
            System.out.println("I'm executing from thread " + Thread.currentThread().getId());
            super.run();
        }
    }

 

AvoidStringBufferField

Использование: 7,51% Набор правил PMD:   String и StringBuffer

Следует избегать использования StringBuffer в качестве поля класса. StringBuffer может использовать много памяти. Если класс имеет длительный срок службы, это может привести к переполнению памяти. Пока это возможно, предпочитайте использовать локальные переменные.

Пример: не делай этого

   public class ExampleClass
   {
       private StringBuffer output;

 

FinalizeShouldBeProtected

Использование: 7,57% Набор правил PMD: Финализатор

Finalize () вызывается сборщиком мусора, когда объект собирается. Вы не должны полагаться на завершение для выполнения задач, кроме освобождения ресурсов. Finalize не предназначен для вызова кем-либо, кроме сборщика мусора. По этой причине finalize () должен быть не публичным, а защищенным. Это правило также есть в Findbugs с именем «FI_PUBLIC_SHOULD_BE_PROTECTED» . По крайней мере, одно из этого правила должно быть использовано.

Пример: опять же, не делайте этого

    @Override
    public void finalize() throws Throwable {
        ...
    }

 

 

Это конец этой статьи, как мы видели, нарушение этих правил может принести некоторые проблемы. Я был удивлен, увидев, что они используются редко, поэтому скажите мне: вы знали об этих правилах? Как вы думаете, стоит проверить?