Как удалить System.out.println из кодовой базы - PullRequest
9 голосов
/ 21 февраля 2009

У нас есть огромная (старая унаследованная java) кодовая база, где многие файлы (около 5 тыс.) Имеют System.out.println. Мы планируем удалить их по причинам очистки / производительности. Как мы можем написать скрипт, который заменит их без каких-либо проблем в коде? Сценарий не может удалить их вслепую, так как может возникнуть проблема в следующем случае:

if ()
  some.code...
else
  System.out.println(...);
DB.close();

Я думаю заменить их на ';'. Это позаботится о вышеупомянутом случае. Видите ли вы какие-либо другие проблемы? Любые другие предложения?

Ответы [ 8 ]

25 голосов
/ 21 февраля 2009

Рассматривали ли вы глупый случай:

System.out.println(" Print " +  object.changeState() );

Я не думаю, что это произойдет, но есть вероятность, что println выполняет метод, который фактически выполняет какое-то действие, от которого зависит система, и может вносить незначительные ошибки (поверьте или нет, но я был свидетелем этого)

Возможно, подойдет замена на регистратор и отключение регистраторов.

Или создание нулевого объекта с использованием шаблона NullObject:

public final class DevNull { 
    public final static PrintStream out = new PrintStream(new OutputStream() {
        public void close() {}
        public void flush() {}
        public void write(byte[] b) {}
        public void write(byte[] b, int off, int len) {}
        public void write(int b) {}

    } );
}

И замена

 System.out.println();

С

 DevNull.out.println();
11 голосов
/ 21 февраля 2009

Log4E - это плагин eclipse, который имеет функцию «Заменить System.out.println ()». Он с радостью преобразует все эти надоедливые вызовы println в вызовы log4j. Он даже обернет их проверкой уровня журнала.

8 голосов
/ 21 февраля 2009

Расширяя концепцию Оскара, вы можете сделать еще лучше ИМХО:

if(!DEBUG) {
    System.setOut(
        new PrintStream(new OutputStream() {
            public  void    close() {}
            public  void    flush() {}
            public  void    write(byte[] b) {}
            public  void    write(byte[] b, int off, int len) {}
            public  void    write(int b) {}

        } );
    }
}

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

6 голосов
/ 21 февраля 2009

Вы можете начать с вызова System.setOut и передачи собственного OutputStream, который ничего не делает. Это поможет вам увидеть, есть ли прирост производительности. Это безопаснее, чем удалять их (по той причине, что указал Оскар - кодирование по побочному эффекту). Если прирост производительности незначителен, вы можете сосредоточить свои усилия в другом месте.

Два вопроса с моим методом:

  1. любой System.out.printlns, который вы хотите сохранить, тоже будет разорван
  2. Конкатенация строк все равно будет иметь место (и это может быть дорого в зависимости от того, сколько там)

Тем не менее, это хороший быстрый тест, чтобы увидеть, получаете ли вы прирост производительности, который вы ищете.

2 голосов
/ 21 февраля 2009

Вы можете использовать условную компиляцию , чтобы получить отладочную сборку с операторами print и сборку выпуска без них.

По сути, идея заключается в создании окончательного статического класса с окончательным статическим логическим значением, которое вы используете в качестве переключателя во время компиляции.

public final class Debug {
   //set to false to allow compiler to identify and eliminate
   //unreachable code
   public static final boolean ON = true;
}

Тогда вы можете просто заменить все ваши System.out.println заявления на

if(Debug.ON)
{
    System.out.println...
}

Поскольку компилятор будет игнорировать любые недоступные ветви кода, вы можете просто установить ON = false, когда будете выполнять сборку релиза, и операторы печати будут исключены из вашего байт-кода.

Примечание: Это не касается случая, на который указал Оскар , когда оператор print может изменить состояние какого-либо объекта. Вы можете использовать условную компиляцию для печати на нулевом объекте, когда он находится в режиме выпуска, как он предложил, вместо полного удаления отпечатков.

1 голос
/ 21 февраля 2009

Лично я бы использовал {} вместо этого, но я думаю, что он работает точно так же.

0 голосов
/ 21 февраля 2009

Рассматривали ли вы редактирование этих исходных файлов для удаления строк?

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

Я использовал Eclipse и функцию очистки при сохранении, чтобы очистить импорт и прочее одновременно.

Это довольно терапевтическое занятие! ​​

0 голосов
/ 21 февраля 2009

Я написал регулярное выражение в perl, которое заменяет строку "System.out.println" на "; // System.out.println". Я считаю, что есть очень мало случаев, когда это сломало бы сборку. Это просто стало бы «else;», которое компилируется в ноль инструкций байт-кода.

Похоже, это то, что вы предложили. Это сработало для меня - за исключением случаев, когда у вас есть дополнительные заявления в той же строке. Тем не менее, это плохой стиль для начала (и я знал, что я этого не делал).

...