Как удалить отладочные операторы из производственного кода в Java - PullRequest
14 голосов
/ 28 августа 2008

Может ли компилятор удалить операторы, используемые для целей отладки (например, ведения журнала) из производственного кода? Операторы отладки должны быть как-то помечены, возможно, с использованием аннотаций.

Легко установить свойство (debug = true) и проверять его при каждом операторе отладки, но это может снизить производительность. Было бы хорошо, если бы компилятор просто заставлял операторы отладки исчезать.

Ответы [ 8 ]

23 голосов
/ 28 августа 2008

Две рекомендации.

Первый: для реальной регистрации используйте современный пакет регистрации, такой как log4j или собственный встроенный протокол java. Не стоит сильно беспокоиться о производительности, проверка уровня журналирования имеет порядок наносекунд. (это целочисленное сравнение).

А если у вас более одного оператора журнала, защитите весь блок:

(log4j, например:)

if (logger.isDebugEnabled()) {

  // perform expensive operations
  // build string to log

  logger.debug("....");
}

Это дает вам добавленную возможность управления журналом во время выполнения. Необходимость перезапуска и запуска отладочной сборки может быть очень неудобной.

Второе:

Вы можете найти утверждений больше, чем вам нужно. Утверждение - это оператор, который оценивает логический результат с необязательным сообщением:

 assert (sky.state != FALLING) : "The sky is falling!";

Всякий раз, когда утверждение приводит к ложному утверждению, оно завершается ошибкой, и выдается ошибка AssertionError, содержащая ваше сообщение (это непроверенное исключение, предназначенное для выхода из приложения).

Удобно то, что они обрабатываются JVM специально и могут переключаться во время выполнения до уровня класса, используя параметр VM (перекомпиляция не требуется). Если не включено, накладные расходы равны нулю.

10 голосов
/ 28 августа 2008
public abstract class Config
{
    public static final boolean ENABLELOGGING = true;
}

import static Config.*;

public class MyClass
{
    public myMethod()
    {
        System.out.println("Hello, non-logging world");

        if (ENABLELOGGING)
        {
            log("Hello, logging world.");
        }
    }
}

Компилятор удалит блок кода с помощью «Hello, logging world». в нем, если ENABLE_LOGGING установлен в true, потому что это статическое конечное значение. Если вы используете обфускатор, такой как proguard, класс Config тоже исчезнет.

Обфускатор также разрешил бы такие вещи:

public class MyClass
{
    public myMethod()
    {
        System.out.println("Hello, non-logging world");

        Log.log("Hello, logging world.");
    }
}

import static Config.*;

public abstract class Log
{
    public static void log(String s)
    {
        if (ENABLELOGGING)
        {
            log(s);
        }
    }
}

Метод Log # log сводится к нулю в компиляторе и будет удален обфускатором вместе с любыми вызовами этого метода, и в конечном итоге даже сам класс Log будет удален.

1 голос
/ 28 августа 2008

Другая возможность заключается в том, чтобы поместить оператор if в функцию регистрации, таким образом вы получите меньше кода, но за счет некоторых дополнительных вызовов функций.

Я также не большой поклонник полного удаления кода отладки. Когда вы начнете работать, вам, вероятно, понадобится доступ к сообщениям отладки, если что-то пойдет не так. Если вы удалите все отладки на уровне кода, это невозможно.

0 голосов
/ 08 мая 2014

Этот " трюк ", кажется, делает ваши отладочные операторы исчезнувшими

public static final boolean DEBUG = false;

if (DEBUG) { //disapeared on compilation }

В сообщении говорится, что javac достаточно умен, чтобы проверить static final boolean и исключить операторы отладки. (Лично я не пробовал)

Для регистрации я лично не хотел бы видеть код как:

if (logger.isDebugEnabled()) {
    logger.debug("....");
}
realImportantWork();

Лесозаготовки отвлекают меня от realImportantWork(). Правильный путь для меня:

logger.debug("....");
realImportantWork()

плюс конфигурация, которая исключает все отладочные сообщения в Production.

Я имею в виду, что элемент управления logger.isDebugEnabled() должен быть заданием структуры ведения журнала, а не моей работой. Большинство каркасов ведения журналов поддерживают такие понятия, как «logger», «LogLevel» ... которые могут помочь.

0 голосов
/ 28 августа 2008

Я бы также настоятельно рекомендовал использовать каркас журналирования.

logger.IsDebugEnabled() не является обязательным, просто может быть быстрее проверить, находится ли система на уровне отладки перед регистрацией.

Использование каркаса ведения журнала означает, что вы можете настроить уровни ведения журнала на лету, не перезапуская приложение.

Вы можете вести журнал как:

logger.error("Something bad happened")
logger.debug("Something bad happend with loads more detail")
0 голосов
/ 28 августа 2008

Чтобы прямо ответить на ваш вопрос: я не знаю.

Но вот еще одно решение вашей проблемы: На мой взгляд, здесь есть два утверждения, которые сталкиваются друг с другом: «операторы отладки» и «производственный код».

Какова цель отладочных операторов? Помогите избавиться от ошибок при (модульном) тестировании. Если часть программного обеспечения должным образом протестирована и работает в соответствии с требованиями, операторы отладки - это не что иное, как УСТРАНЕНИЕ.

Я категорически не согласен с тем, чтобы оставлять любые отладочные операторы в производственном коде. Держу пари, что никто не мешает тестировать побочные эффекты отладочного кода в рабочем коде. Код, вероятно, делает то, что должен, но делает ли он больше? Все ли ваши #defines работают правильно и действительно удаляют ВСЕ отладочный код? Кто анализирует 100000 строк предварительно обработанного кода, чтобы выяснить, все ли отладочные материалы исчезли?

Если у нас нет другого определения производственного кода, вам следует рассмотреть возможность удаления операторов отладки после того, как код протестирован, и покончить с этим.

0 голосов
/ 28 августа 2008

Java содержит своего рода препроцессор. Это называется APT . Обрабатывает и генерирует код. На данный момент я не уверен, как это должно работать (я не пробовал). Но, похоже, он используется для подобных вещей.

0 голосов
/ 28 августа 2008

Использовать Препроцессор Java ? (Google Foo Low, но это ссылка на старые форумы Джоэл, обсуждающие это)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...