System.out.println()の使用がそれほど悪いのはなぜですか?[閉まっている]


18

もちろん、エラーメッセージまたは警告にログフレームワークを使用することは非常に有効です。ただし、短時間で新しいことを試してみたい場合は、System.out.println()を使用することがあります。

System.out.println()を使って簡単なテストを行うのは本当に悪いのでしょうか?


3
いいえ。簡単なテストです。誰が気にしますか?
ブライアンベッチャー

10
誰が悪いと言う?代替手段は何ですか?
ジェームズ

1
@Kayserの静的コードレビューツールは、迅速なテストには不適切です。他の人と開発する(または他の人が理解する必要がある)コードには、より適しています。今年学んでいるように思える教訓は、勤務時間中であっても、非常に異なるツールセットとプラクティスを必要とする非常に異なる問題空間があるということです。簡単なテストのために、すべてをチャックしてGroovyを使用してください:)
ビルK

1
使用System.err.println()してみて、何が起こるか見てみましょう。このツールは、あなたがSystem.out間違った目的に使用していると考えていると推測しています。
イズカタ

2
主な問題は、スケーラビリティと制御にあります。これらのステートメントの数百万を持っている場合、どうすればあなたが見る必要があるかを見ることができます。これらのいずれかに対応する必要がある場合、プログラムでどのように行うことができますか。ロギングフレームワークは通常、System.outに適用される2つの考え方です。

回答:


18

コメントで明らかになったように、求められている本当の質問は、なぜ静的コード分析ツールがSystem.out.printlnの使用にフラグを立てるのかということです。

理由は、標準出力にメッセージを送信することは通常、実稼働環境では不適切だからです。ライブラリをコーディングしている場合、ライブラリは標準出力に出力するのではなく、呼び出し元に情報を返す必要があります。GUIアプリをコーディングしている場合、stdoutが指す場所(どこにもないかもしれない)ではなく、情報をユーザーに提示する必要があります。サーバー(またはサーバー側のコンテナーで実行されるもの)をコーディングしている場合、フレームワークが提供するロギング機能を使用する必要があります。などなど。

しかし、デバッグまたは開発にprintlnを使用している場合、またはプログラムを作成してstdinを読み取りstdoutに書き込む場合、printlnはまったく問題ありません。これらの種類のケースでは何も問題はありません。


3
いい答え。ありがとう..「GUIアプリをコーディングしている場合、stdoutが指す場所(どこでもないかもしれない)ではなく、情報をユーザーに提示する必要があります」
カイザー

10

すべてがstdoutバッファリングされているので、ある可能プログラムがクラッシュすることをした後、あなたが呼ばれprintln()ますが、前にそれが画面に達します。

そうは言っても、このシナリオは本当にありそうもない。先に進んでそれを使用しますが、あなたの心の奥にある小さな制限を守ってください。


少なくとも2つの主要なPythonインタープリターは、終了が未処理の例外によるものであっても、終了前に開いているすべてのファイルをフラッシュしようと非常に努力します。JVMは似たようなことをしませんか?

1
@delnan、おそらく、でも何でも起こります。(stdoutをフラッシュするコードは、問題が表面化する場所にある可能性があります。実行中のスレッドは強制的に閉じられる可能性があります。現在のプロセスは、それに注意してください。
リウォーク

1
stdoutをフラッシュするコードはVM自体にあるため、VMが実装する言語のエラーの影響を受けません。プロセスの強制終了に関する良い点。しかし、たとえばUnixのSIGTERMや他のほとんどのシグナルは、このようなクリーンアップを行うためにキャッチできることに注意してください-しかし、より極端なSIGKILLでは動作しません。

2
私は他の問題を見たことがありますが、私はこれを見たり、起こったことを聞いたことがないと思います。また、この問題は、ロガーなどのツールではSystem.outを基礎ツールとして使用する可能性が高いため、改善される可能性がありません。
ビルK

@delnanクリーンアップコードの実行が保証されていると思い込まず、重要なビジネストランザクションコードをfinallyブロックに配置しないでください;) System.outはデバッグには適していますが、バッファリングに注意してください。
スティーブン

8

System.outラップされBufferedOutputStreamただけです。これは、使用するすべてのロギングフレームワークに類似している可能性があります。フレームワークは、ログ出力の構成と宛先の形式でより多くの機能を提供するだけです。


4
これは本当に質問に答えません。「悪いの?」
sergserg

@Berg-質問のその部分は完全にコンテキスト依存であるため。(あるいは単に、いや、それは悪くはない)
spinning_plate

7

自明ではないプログラムに取り組んでいて、あなたが

  • 自動化された単体テスト(JUnit)の代わりに松葉杖としてSystem.outを使用している
  • System.outステートメントの作成と削除、またはコメント/コメント解除に多くの時間を費やす

1
ほとんどのIDEには、System.out.printlnの自動補完、行のコメント化/コメント解除、および行の削除のためのホットキーが必要です。原則として、過度の使用を避けようとするのは正しいことですが、少なくともこの方法で時間を節約できます。
スティーブン

7

System.out使い捨てコードであっても、の使用にはいくつかの注意事項があります。

1つの大きな問題は、通常遅いことです。たとえば、一部のコードの速度について大まかなアイデアを取得しようとしている場合(マイクロベンチマークは難しいことに注意してください)、System.out.println()どこにでも1つ追加すると、タイミングが台無しになる可能性があります(同期し、実際の出力を待つことが多いため)戻る前にユーザーに表示されます)。

それ以外は、使い捨てのコードではあまり心配しません。あなたはそれをコミットするつもりなら、あなたは(はい、それを取り除くとpropperロギングコールでそれを置き換える必要があり、(製品コードとして、あるいはテストコードとしても)でもテストコードで)。


パフォーマンスは良い議論です
。-カイザー

4

よくあることですが、答えは「依存します」です。アプリケーションにロギングフレームワークがすでにある場合は、それを使用することもできます。の機能よりも劣ることはありません。またprintln()、スタックトレース、追加のコンテキスト、より優れた書式設定など、他の機能を利用することもできます。また、ロギングフレームワークがより優れたエラー回復を提供し、致命的な障害が発生した場合でもログが正常に書き込まれることを保証する明確な可能性があります。

したがって、最初にログシステムを追加するタイミングが問題になります。これは判断の呼びかけです。あまり早く追加したくないので、本当に必要がないかどうかを確認するだけです。また、追加するのが遅すぎて、アドホックソリューションから変換する作業が過剰になりたくないでしょう。

を使用して多くのログを記録しprintln()ていることに気付いた場合、コードベースは痛みが大きくなっていることを伝えようとしています。その時点で、適切なロギングに投資する価値があります。


3

System.out.printが「システムのデフォルト」コードページを使用するという問題がよくあります。これはLinuxではUTF-8であることが多いですが、WindowsではMSのものが一部欠けています。

これにより、プログラムの実行場所に応じて、画面に正しく印刷される場合とされない場合があります。

したがって、System.outよりもカスタムPrintWriterの方が好きです。


ひび割れたMSのもの。CP1352またはUTF16のことですか?
コールジョンソン

@ColeJohnson:残念ながら、Windowsコンソールウィンドウは、UTF16より前の時代に残っています。ただし、組み込みのコンソールで正しいIDEを使用すると、その問題を軽減できます。
ヨアヒムザウアー

@Cole Johnson-CP 65001(つまりutf8)と一緒に暮らすこともできますが、たとえば、ドイツ語のキーボードでCP 850などを取得する場合、これを「システムのデフォルト」コードページとして取得する方法はないようです。
インゴ

1

それはまったく悪くありません。この概念は、アプリケーションで専用のロギングフレームワークを使用するほど単純ではなく、洗練されていないという事実から生じる可能性があります。

ただし、これは無効なアプローチだと言っているわけではありません。ブラックマジックブードゥープログラミングのハイジャックの後、アプリケーションフローをチェックするために何度も使用しました。


0

それを使用することに何の問題もありません、それはあなたが「一体何が起こっているのか」を理解するのに役立ちます。

しかし、あなたの仲間/他の開発者/ツールがあなたをridしているなら、あなたはいつもLoggerを使うか、Junitテストを始めることができます!


0

職業System.out.printlnの最大の問題は、私が見るように、それが「悪い癖の匂い(tm)」であることです。これを実行していることに気付いた場合は、お気に入りのデバッガーをより快適に使用することで、おそらく有効性を向上させることができます。

また、デバッガーを使用すると、System.out.printlnが停止する可能性がある一方で、ブレークポイントが実動コードにスリップしないことが確実にわかります。

ちなみに、実際に簡単なテストを行っているだけで、デバッガーを使用しない場合は、ロギングフレームワークを使用するよりもSystem.out.printlnの方が優れていると思います。完了、根絶するのは難しい。


0

内部状態の内容のエコーアウトに関するテスト戦略全体を構築することは最も賢明な動きではありませんが、開発中のコードの迅速で汚れたテストのために、ここで奇妙なprintlnを削除します。

それらを削除するのを忘れる危険性は、おそらくそれが反対されている理由です。


あなたの意見でそれらを削除することを忘れることの問題は何ですか?コンソールにはさらにメッセージが表示されます。他に問題がありますか?
カイザー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.