Mengapa menggunakan System.out.println () sangat buruk? [Tutup]


18

Tentu saja, sangat baik digunakan untuk menggunakan kerangka kerja logging untuk pesan kesalahan atau peringatan. Tapi kadang-kadang saya menggunakan System.out.println () jika saya ingin mencoba sesuatu yang baru dalam waktu singkat.

Apakah sangat buruk menggunakan System.out.println () untuk beberapa tes cepat?


3
Tidak. Ini tes cepat, siapa yang peduli?
Bryan Boettcher

10
Siapa bilang itu buruk? Apa alternatifnya?
James

1
@Kayser alat peninjau kode statis tidak pantas untuk tes cepat - mereka lebih untuk kode yang ingin Anda kembangkan dengan orang lain (atau yang harus dipahami orang lain). Pelajaran yang tampaknya saya pelajari tahun ini adalah bahwa ada ruang masalah yang sangat berbeda, bahkan sepanjang hari kerja, yang membutuhkan peralatan dan praktik yang sangat berbeda. Jadi untuk tes cepat Anda, buang semuanya dan gunakan Groovy :)
Bill K

1
Coba gunakan System.err.println()dan lihat apa yang terjadi. Saya menduga alat berpikir Anda menggunakan System.outuntuk tujuan yang salah.
Izkata

2
Masalah utama adalah dengan skalabilitas dan kontrol. Jika Anda memiliki jutaan pernyataan ini, bagaimana Anda bisa melihat apa yang perlu Anda lihat. Jika Anda perlu bereaksi terhadap salah satu dari ini, bagaimana Anda bisa melakukan itu secara terprogram. Kerangka logging biasanya dua pemikiran yang diterapkan pada System.out.

Jawaban:


18

Seperti yang diungkapkan dalam komentar, pertanyaan sebenarnya yang diajukan adalah, Mengapa alat analisis kode statis menandai penggunaan System.out.println?

Alasannya adalah bahwa mengirim pesan ke stdout biasanya tidak sesuai di lingkungan produksi. Jika Anda mengode perpustakaan, perpustakaan harus mengembalikan informasi ke pemanggilnya, bukan mencetak ke stdout. Jika Anda mengkode aplikasi GUI, informasi tersebut harus disajikan kepada pengguna, bukan ke tempat stdout menunjuk (yang mungkin tidak ada di mana pun). Jika Anda mengode server (atau sesuatu yang berjalan dalam wadah sisi server), Anda harus menggunakan fasilitas logging apa pun yang disediakan kerangka kerja. Dan seterusnya.

Tetapi jika Anda menggunakan println untuk debugging atau pengembangan, atau Anda sedang menulis program dan membaca stdin dan menulis ke stdout, println baik-baik saja. Tidak ada yang salah dengan itu untuk kasus-kasus semacam itu.


3
Jawaban bagus. Terima kasih .. +1 untuk "Jika Anda mengode aplikasi GUI, informasi tersebut harus disajikan kepada pengguna, bukan ke tempat stdout menunjuk (yang mungkin tidak ada di mana-mana)"
Kayser

10

Semua stdoutbuffer, dan dengan demikian mungkin program Anda akan macet setelah Anda menelepon println(), tetapi sebelum mencapai layar.

Dengan itu dikatakan, skenario ini benar-benar tidak mungkin. Silakan dan gunakan itu, tetapi simpan saja batasan kecil itu di belakang pikiran Anda.


Paling tidak dua interpreter Python utama berusaha sangat keras untuk menyiram semua file yang terbuka sebelum keluar, bahkan jika keluar itu karena pengecualian yang tidak ditangani. Bukankah JVM melakukan hal yang serupa?

1
@nannan, Mungkin, tetapi apa pun bisa terjadi. (Kode yang mem-flush stdout bisa jadi merupakan tempat timbulnya masalah. Utas yang Anda jalankan bisa ditutup dengan paksa. Proses saat ini dapat dengan paksa dibuang dari memori oleh OS.) hanya sadar akan hal itu.
riwalk

1
Kode yang flushes stdout ada di dalam VM itu sendiri dan karenanya tidak terpengaruh oleh kesalahan dalam bahasa yang diimplementasikan oleh VM. Poin bagus tentang akhir proses paksa. Tetapi perhatikan bahwa mis. SIGTERM Unix dan sebagian besar sinyal lainnya dapat ditangkap untuk melakukan pembersihan seperti ini - tidak bekerja dengan SIGKILL yang lebih ekstrem.

2
Saya tidak berpikir saya pernah melihat ini atau mendengar hal itu terjadi, meskipun saya telah melihat masalah lain. Masalah ini juga sepertinya tidak akan menjadi lebih baik dengan alat seperti penebang karena mereka cenderung menggunakan System.out sebagai alat yang mendasarinya.
Bill K

@delnan Jangan pernah berasumsi bahwa kode pembersihan Anda dijamin untuk menjalankan ... dan tidak pernah memasukkan kode transaksi bisnis penting pada akhirnya menjadi blok;) System.out baik-baik saja untuk debugging, tetapi waspadai buffering.
Steven

8

System.outhanya dibungkus BufferedOutputStream. Ini kemungkinan mirip dengan kerangka kerja logging yang akan Anda gunakan, kerangka kerja hanya menyediakan lebih banyak fungsi dalam bentuk konfigurasi dan tujuan dari output log Anda


4
Ini tidak benar-benar menjawab pertanyaan. "Apa itu buruk?"
sergserg

@Erg - Karena bagian dari pertanyaan itu sepenuhnya tergantung konteks. (atau hanya, tidak, itu tidak buruk)
spinning_plate

7

Ini buruk jika Anda bekerja pada program non-sepele dan Anda

  • Menggunakan System.out sebagai penopang bukannya pengujian unit otomatis (JUnit)
  • Luangkan banyak waktu untuk membuat dan menghapus atau mengomentari / membatalkan pernyataan System.out

1
Kebanyakan IDE harus memiliki hotkey untuk melengkapi otomatis System.out.println, mengomentari / menghapus komentar pada sebuah baris, dan menghapus sebuah baris. Anda pada prinsipnya benar untuk mencoba menghindari penggunaan yang berlebihan, tetapi Anda setidaknya dapat menghemat waktu dengan cara ini.
Steven

7

Ada beberapa peringatan tentang penggunaan System.out, bahkan dalam kode sekali pakai.

Satu masalah utama adalah biasanya lambat . Misalnya, jika Anda mencoba untuk mendapatkan gambaran kasar tentang kecepatan beberapa kode (perhatikan bahwa microbenchmark sulit ), kemudian menambahkan satu di System.out.println()mana saja dapat benar-benar mengacaukan pengaturan waktu Anda (karena sinkronisasi dan sering menunggu keluaran aktual untuk terlihat oleh pengguna sebelum kembali).

Selain itu, saya tidak akan terlalu khawatir tentang hal itu dalam kode sekali pakai. Jika Anda bermaksud melakukan itu (baik sebagai kode produksi atau sebagai kode uji), maka Anda harus menyingkirkannya dan menggantinya dengan panggilan logging yang tepat (ya, bahkan dalam kode uji).


Performa adalah argumen yang bagus ..
Kayser

4

Seperti yang sering terjadi, jawabannya adalah "itu tergantung". Jika aplikasi Anda sudah memiliki kerangka kerja logging, maka Anda dapat menggunakannya. Itu tidak bisa kurang mampu daripada println(), dan Anda mungkin mendapat manfaat dari fitur-fitur lain yang disediakannya — tumpukan jejak, konteks tambahan, pemformatan yang lebih baik, dan sebagainya. Ada juga kemungkinan yang berbeda bahwa kerangka kerja logging menawarkan pemulihan kesalahan yang lebih baik, memastikan bahwa log Anda berhasil ditulis bahkan jika terjadi kegagalan yang dahsyat.

Jadi pertanyaannya adalah kapan harus menambahkan sistem logging di tempat pertama. Ini adalah panggilan penilaian: Anda tidak ingin menambahkannya terlalu dini, hanya untuk mengetahui Anda benar-benar tidak membutuhkannya. Anda juga tidak ingin menambahkannya terlambat, dan melakukan pekerjaan yang berlebihan dengan mengonversi dari solusi ad-hoc Anda.

Jika Anda mendapati bahwa Anda melakukan banyak logging println(), maka basis kode Anda mencoba untuk memberi tahu Anda bahwa itu sedang mengalami rasa sakit yang tumbuh. Pada titik itu, layak untuk berinvestasi dalam pembalakan yang benar.


3

Saya sering mengalami masalah karena System.out.print menggunakan codepage "system default", yang seringkali UTF-8 di Linux, tetapi beberapa barang MS rusak di Windows.

Ini dapat menyebabkan karakter unicode yang dicetak dengan benar atau tidak ke layar, tergantung di mana program berjalan.

Karena itu saya lebih suka PrintWriter kustom daripada System.out


Dengan MS crapped stuff. Maksud Anda CP1352 atau UTF16?
Cole Johnson

@ColeJohnson: Jendela konsol Windows sayangnya masih macet di era pra-UTF16. Namun, menggunakan IDE yang waras dengan konsol internal dapat mengurangi masalah itu.
Joachim Sauer

@Cole Johnson - Saya bisa hidup dengan CP 65001 (yaitu utf8), tetapi sepertinya tidak ada cara untuk mendapatkan ini sebagai codepage "sistem default", ketika, misalnya, Anda memiliki keyboard Jerman Anda mendapatkan CP 850 atau semacamnya.
Ingo

1

Tidak buruk sama sekali. Gagasan ini mungkin berasal dari fakta bahwa itu sangat sederhana dan tidak secanggih menggunakan kerangka kerja logging khusus dalam aplikasi Anda.

Namun, ini bukan untuk mengatakan bahwa ini adalah pendekatan yang tidak valid. Saya telah menggunakannya berkali-kali untuk memeriksa aliran aplikasi setelah beberapa hijinks pemrograman voodoo ilmu hitam .


0

Tidak ada yang salah dengan menggunakannya, ada baiknya Anda mencari tahu 'apa yang sedang terjadi'.

Tetapi jika rekan-rekan Anda / pengembang / alat lain mengejek Anda, Anda selalu bisa menggunakan Logger , atau memulai pengujian Junit !


0

Masalah terbesar dengan System.out.println occasional, seperti yang saya lihat, adalah "bau kebiasaan buruk (tm)". Jika Anda menemukan diri Anda melakukan ini, maka Anda mungkin dapat meningkatkan efektivitas Anda dengan menjadi lebih nyaman menggunakan debugger favorit Anda.

Juga dengan debugger, Anda tahu pasti bahwa breakpoint tidak akan masuk ke kode produksi Anda, sementara System.out.println mungkin.

Sebagai catatan, jika Anda benar-benar hanya melakukan tes cepat dan bertahan dengan tidak menggunakan debugger, saya pikir System.out.println lebih baik daripada menggunakan kerangka kerja logging, karena jika Anda secara tidak sengaja meninggalkan pernyataan log.debug ketika Anda Sudah selesai, lebih sulit untuk root.


0

Membangun seluruh strategi pengujian dengan mengumandangkan isi keadaan internal bukanlah langkah yang paling cerdas, tetapi untuk pengujian kode yang cepat dan kotor dalam pengembangan, hasil cetak yang aneh di sana-sini tidak akan ada masalah selama Anda ingat untuk menghapusnya!

Bahaya lupa untuk menghapusnya mungkin merupakan alasan mengapa hal itu disarankan.


Apa masalah dengan lupa menghapusnya menurut Anda? Tentu akan ada beberapa pesan lagi di konsol. Apakah Anda melihat masalah lain?
Kayser
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.