Почему использование System.out.println () так плохо? [закрыто]


18

Конечно, очень полезно использовать каркас ведения журналов для сообщений об ошибках или предупреждений. Но иногда я использую System.out.println (), если я хочу попробовать что-то новое за короткое время.

Неужели так плохо с использованием System.out.println () для быстрого теста?


3
Нет. Это быстрый тест, кого это волнует?
Брайан Бетчер

10
Кто сказал, что это плохо? Какая альтернатива?
Джеймс

1
Инструменты @Kayser для проверки статического кода не подходят для быстрых тестов - они больше предназначены для кода, который вы собираетесь разрабатывать с другими (или которые другие должны будут понять). Урок, который я, похоже, усваиваю в этом году, заключается в том, что даже в течение рабочего дня существуют очень разные проблемные пространства, которые требуют совершенно разных наборов инструментов и практик. Так что для быстрого теста бросьте все это и используйте Groovy :)
Bill K

1
Попробуйте использовать System.err.println()и посмотреть, что происходит. Я предполагаю, что инструмент думает, что вы используете System.outдля неправильной цели.
Изката

2
Основная проблема связана с масштабируемостью и контролем. Если у вас есть миллионы таких утверждений, как вы можете увидеть то, что вам нужно увидеть. Если вам нужно отреагировать на один из них, как вы можете сделать это программно. Каркасами журналирования обычно являются те две мысли, которые применяются к System.out.

Ответы:


18

Как показано в комментариях, реальный вопрос: почему инструменты статического анализа кода помечают использование System.out.println?

Причина в том, что отправка сообщений на стандартный вывод обычно нецелесообразна в производственной среде. Если вы кодируете библиотеку, библиотека должна возвращать информацию вызывающей стороне, а не печатать на стандартный вывод. Если вы кодируете приложение с графическим интерфейсом, информация должна быть представлена ​​пользователю, а не туда, куда указывает stdout (чего может не быть). Если вы кодируете сервер (или что-то, что работает в контейнере на стороне сервера), вы должны использовать любое средство ведения логов, предоставляемое фреймворком. И так далее.

Но если вы используете println для отладки или разработки, или вы пишете программу и читаете stdin и пишете в stdout, println - это прекрасно. В таких случаях нет ничего плохого.


3
Хороший ответ. Спасибо .. +1 за "Если вы кодируете приложение с графическим интерфейсом, информация должна быть представлена ​​пользователю, а не туда, куда указывает stdout (который может быть нигде)"
Kayser

10

Все stdoutбуферизировано, и, таким образом, возможно, что ваша программа потерпит крах после вашего вызова println(), но до того, как она достигнет экрана.

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


По крайней мере два основных интерпретатора Python очень стараются очистить все открытые файлы перед выходом, даже если выход происходит из-за неустановленного исключения. Разве JVM не делают что-то подобное?

1
@delnan, возможно, но все может случиться. (Код, который очищает стандартный вывод, может быть там, где возникает проблема. Поток, в котором вы работаете, может быть принудительно закрыт. Текущий процесс может быть принудительно выгружен из памяти ОС.) Не проживайте свою жизнь вокруг моего утверждения, но просто знайте об этом.
Rwalk

1
Код, который сбрасывает стандартный вывод, находится в самой ВМ и, следовательно, не подвержен ошибкам на языке, который реализует ВМ. Хороший вопрос о принудительном завершении процесса. Но обратите внимание, что, например, SIGTERM Unix и большинство других сигналов могут быть пойманы, чтобы выполнить очистку, подобную этой, - однако, не работает с более экстремальным SIGKILL.

2
Я не думаю, что когда-либо видел это или слышал о том, что это происходит, хотя я видел другие проблемы. Эта проблема также вряд ли станет лучше с такими инструментами, как регистраторы, поскольку они могут использовать System.out в качестве базового инструмента.
Билл К

@delnan Никогда не предполагайте, что ваш код очистки гарантированно выполняется ... и никогда не помещайте критический код бизнес-транзакции в блоки finally;) System.out отлично подходит для отладки, но помните о буферизации
Стивен

8

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


4
Это на самом деле не отвечает на вопрос. "Это плохо?"
sergserg

@Berg - Потому что эта часть вопроса полностью зависит от контекста. (или просто нет, это не плохо)
spinning_plate

7

Это плохо, если вы работаете над нетривиальной программой, и вы

  • Использует System.out в качестве костыля вместо автоматического модульного тестирования (JUnit)
  • Потратьте много времени на создание и удаление или комментирование / раскомментирование операторов System.out

1
Большинство IDE должны иметь горячие клавиши для автозаполнения System.out.println, комментирования / раскомментирования строки и удаления строки. Вы в принципе правы, пытаясь избежать его чрезмерного использования, но вы можете, по крайней мере, сэкономить время таким образом.
Стивен

7

Есть несколько предостережений по поводу использования System.out, даже в одноразовом коде.

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

Кроме этого, я бы не стал сильно беспокоиться об этом в одноразовом коде. Если вы намереваетесь его зафиксировать (будь то рабочий код или тестовый код), то вам следует избавиться от него и заменить его вызовом регистрации прототипа (да, даже в тестовом коде).


Производительность - хороший аргумент ..
Кайсер

4

Как это часто бывает, ответ «это зависит». Если в вашем приложении уже есть структура ведения журналов, то вы также можете использовать ее. Не может быть менее способным println(), и вы можете воспользоваться другими функциями, которые он предоставляет, - трассировкой стека, дополнительным контекстом, улучшенным форматированием и т. Д. Существует также очевидная возможность того, что каркасы журналирования обеспечивают лучшее восстановление после ошибок, обеспечивая успешную запись ваших журналов даже в случае катастрофического сбоя.

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

Если вы обнаружите, что ведете много журналов println(), ваша кодовая база пытается сказать вам, что испытывает трудности с ростом. На этом этапе стоит инвестировать в правильное ведение журнала.


3

У меня часто возникает проблема с тем, что System.out.print использует кодовую страницу «системное значение по умолчанию», которая часто называется UTF-8 под Linux, но некоторые вещи с ошибками MS под Windows.

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

Поэтому я предпочитаю пользовательский PrintWriter вместо System.out


По мелочам MS. Вы имеете в виду CP1352 или UTF16?
Коул Джонсон

@ColeJohnson: окно консоли Windows, к сожалению, все еще застряло в эпоху, предшествующую UTF16. Однако использование вменяемой IDE со встроенной консолью может уменьшить эту проблему.
Иоахим Зауэр

@Cole Johnson - я мог бы жить с CP 65001 (то есть utf8), но, кажется, нет способа получить это как кодовую страницу «по умолчанию для системы», когда, например, у вас есть немецкая клавиатура, вы получаете CP 850 или что-то подобное.
Инго

1

Это совсем не плохо. Идея может основываться на том факте, что это очень просто и не так сложно, как использование специализированной среды ведения журналов в вашем приложении.

Однако это не означает, что это неверный подход. Я использовал это много раз, чтобы проверить поток приложений после некоторого чихания в черной магии .


0

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

Но если ваши коллеги / другие разработчики / инструменты высмеивают вас, вы всегда можете использовать Logger или начать тестирование Junit !


0

На мой взгляд, самая большая проблема в случае с System.out.println заключается в том, что это «неприятный запах (tm)». Если вы обнаружите, что делаете это, то, вероятно, вы можете улучшить свою эффективность, освоившись с вашим любимым отладчиком.

Также с помощью отладчика вы точно знаете, что точка останова не попадет в ваш производственный код, в отличие от System.out.println.

Напомним, что если вы на самом деле просто делаете быстрый тест и по-прежнему не используете отладчик, я думаю, что System.out.println лучше, чем использование каркаса журналирования, поскольку, если вы случайно оставите оператор log.debug при сделано, труднее искоренить.


0

Создание целой стратегии тестирования, основанной на выводе содержимого внутреннего состояния, - не самый умный шаг, но для быстрых и грязных тестов кода в процессе разработки странный вывод здесь и там не повредит, если вы не забудете их удалить!

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


В чем проблема с забыванием удалить их по вашему мнению? Конечно, на консоли будет больше сообщений. Видите ли вы еще какие-либо проблемы?
Кайсер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.