System.out.println () kullanmak neden bu kadar kötü? [kapalı]


18

Elbette, hata mesajları veya uyarılar için bir günlük kaydı çerçevesi kullanmak çok iyi bir yöntemdir. Ancak kısa sürede yeni bir şey denemek istersem bazen System.out.println () yöntemini kullanırım.

Bazı hızlı testler için System.out.println () kullanmak gerçekten çok mu kötü?


3
Hayır. Hızlı bir test, kimin umurunda?
Bryan Boettcher

10
Kim demiş kötü? Alternatif nedir?
James

1
@Kayser statik kod inceleme araçları hızlı testler için uygun değildir - başkalarıyla geliştirmeyi planladığınız (veya başkalarının anlamak zorunda kalacağı) kodlar için daha uygundur. Bu yıl öğreniyor olduğum ders, iş günü boyunca bile çok farklı araç setleri ve uygulamaları gerektiren çok farklı sorun alanlarının olmasıdır. Hızlı testiniz için hepsini bir kenara koyun ve Groovy kullanın :)
Bill K

1
Kullanmayı deneyin System.err.println()ve ne olduğunu görün. Sanırım bu araç System.outyanlış amaçla kullandığınızı düşünüyor .
Izkata

2
Birincil sorun ölçeklenebilirlik ve kontrol ile ilgilidir. Milyonlarca ifadeniz varsa ne görmeniz gerektiğini nasıl görebilirsiniz? Bunlardan birine tepki göstermeniz gerekiyorsa, bunu programlı olarak nasıl yapabilirsiniz? Günlük çerçeveleri genellikle System.out'a uygulanan iki düşüncedir.

Yanıtlar:


18

Yorumlarda da belirtildiği gibi, sorulan asıl soru şudur: Statik kod analiz araçları System.out.println'in kullanımını neden işaretliyor?

Bunun nedeni, stdout'a mesaj göndermenin genellikle bir üretim ortamında uygunsuz olmasıdır. Bir kitaplığı kodluyorsanız, kitaplık stdout'a yazdırmamak için bilgileri arayanın bilgisine döndürmelidir. Bir GUI uygulaması kodluyorsanız, bilgi, stdout'un nereye işaret ettiği değil (hiçbir yerde olmayabilir) kullanıcıya sunulmalıdır. Bir sunucuyu (veya sunucu tarafı kapsayıcısında çalışan bir şeyi) kodluyorsanız, çerçevenin sağladığı günlük oluşturma özelliğini kullanmalısınız. Ve böylece.

Ancak hata ayıklama veya geliştirme için println kullanıyorsanız veya bir program yazıp stdin okuyor ve stdout'a yazarsa println gayet iyi. Bu tür davalar için yanlış bir şey yok.


3
Güzel cevap. Teşekkürler .. "" Eğer bir GUI uygulaması kodluyorsanız, bilgi kullanıcıya (stdout'un işaret ettiği yere değil, hiçbir yerde olmayabilir) sunulmalıdır "
Kayser

10

Tüm stdouttamponlu edilir ve böylece o mümkün program çökmesine edeceği sonra aradığınız println()ama önce o ekrana ulaşır.

Bununla birlikte, bu senaryo gerçekten olası değildir. Devam edin ve kullanın, ancak bu küçük sınırlamayı zihninizin arkasında tutun.


En az iki büyük Python yorumlayıcısı, çıkış işlenmemiş bir istisnadan kaynaklansa bile, çıkıştan önce tüm açık dosyaları temizlemeye çok çalışmaktadır. JVM'ler benzer bir şey yapmıyor mu?

1
@delnan, Muhtemelen, ama her şey olabilir. (Stdout'u temizleyen kod, sorunlu yüzeyler olabilir. Çalıştığınız iş parçacığı zorla kapatılabilir. Geçerli işlem, işletim sistemi tarafından bellekten zorla çıkarılabilir.) sadece farkında olun.
riwalk

1
Stdout'u temizleyen kod VM'nin kendisindedir ve bu nedenle VM'nin uyguladığı dilde yapılan hatalardan etkilenmez. Zorunlu süreç sonu hakkında iyi bir nokta. Ancak, Unix'in SIGTERM ve diğer birçok sinyalin bu şekilde temizlik yapmak için yakalanabileceğini unutmayın - daha aşırı SIGKILL ile çalışmaz.

2
Başka sorunlar görmeme rağmen bunu gördüğümü veya bunun olduğunu duyduğumu sanmıyorum. System.out'u altta yatan bir araç olarak kullanmaları muhtemel olduğundan, bu sorunun kaydediciler gibi araçlarla daha iyi olması muhtemel değildir.
Bill K

@delnan Temizleme kodunuzun çalışacağının asla garanti edilmediğini varsaymayın ... ve kritik iş işlem kodunu son olarak bloklara koymayın;) System.out hata ayıklama için iyidir, ancak arabelleğe alma işleminin farkında olun.
Steven

8

System.outsadece sarılmış BufferedOutputStream. Bu muhtemelen kullanacağınız herhangi bir günlükleme çerçevesine benzer, çerçeveler yalnızca günlük çıktınızın yapılandırması ve hedefi şeklinde daha fazla işlevsellik sağlar


4
Bu soruya gerçekten cevap vermiyor. "Kötü bir şey mi?"
sergserg

@Berg - Çünkü sorunun bu kısmı tamamen bağlama bağlıdır. (ya da sadece, hayır, fena değil)
spinning_plate

7

Önemsiz bir program üzerinde çalışıyorsanız ve

  • System.out'u otomatik birim testi (JUnit) yerine koltuk değneği olarak mı kullanıyorsunuz?
  • System.out bildirimlerini oluşturmak, silmek veya yorumlamak / yorumunu kaldırmak için çok zaman harcayın

1
Çoğu IDE, System.out.println'leri otomatik tamamlama, bir satırı yorumlama / açma ve bir satırı silme için kısayol tuşlarına sahip olmalıdır. Prensipte aşırı kullanımı önlemek için haklısınız, ancak en azından bu şekilde zaman kazanabilirsiniz.
Steven

7

Kullanmayla ilgili birkaç uyarı var System.outAtma kodunda bile, kullanımla .

Önemli bir sorun, genellikle yavaş olmasıdır . Örneğin, bazı kodların hızı hakkında kaba bir fikir edinmeye çalışıyorsanız ( mikrobenç işaretlerin zor olduğunu unutmayın ), o zaman tek bir System.out.println()yere eklemek zamanlamanızı gerçekten bozabilir (çünkü senkronize edilir ve genellikle gerçek çıkışın dönmeden önce kullanıcı tarafından görülebilir).

Bunun dışında, ıskarta kodunda çok fazla endişelenmezdim. Bunu yapmak istiyorsanız (üretim kodu veya test kodu olarak), ondan kurtulmalı ve bir propper günlük çağrısı ile değiştirmelisiniz (evet, test kodunda bile ).


Performans iyi bir argüman ..
Kayser

4

Çoğu zaman olduğu gibi, cevap “duruma bağlıdır”. Uygulamanızın zaten bir günlük kaydı çerçevesi varsa, bunu da kullanabilirsiniz. Daha az yetenekli olamaz println()ve sağladığı diğer özelliklerden (yığın izleri, ekstra bağlam, daha iyi biçimlendirme vb.) Yararlanabilirsiniz. Günlüğe kaydetme çerçevelerinin daha iyi hata kurtarma özelliği sunması ve kayıtlarınızın felaketli bir hata durumunda bile başarıyla yazılmasını sağlamanın belirgin bir olasılığı vardır.

Böylece soru, ne zaman ilk etapta bir kayıt sistemi ekleneceğidir. Bu bir yargılama çağrısıdır: çok erken eklemek istemezsiniz, sadece buna gerçekten ihtiyacınız olmadığını öğrenmek için. Ayrıca çok geç eklemek istemiyorsunuz ve geçici çözümünüzden aşırı dönüşüm sağlıyorsunuz.

Çok fazla günlük kaydı yaptığınızı fark ederseniz println(), kod tabanınız size artan ağrılar yaşadığını söylemeye çalışıyor. Bu noktada, doğru günlüğe kaydetmeye değer.


3

Sık sık System.out.print Linux altında UTF-8 olan "sistem varsayılan" kod sayfasını kullanır, ancak bazı Windows altında MS şeyler tıkanma var.

Bu, programın çalıştığı yere bağlı olarak ekrana doğru yazdırılan veya yazdırılmayan unicode karakterlere yol açabilir.

Bu nedenle System.out yerine özel bir PrintWriter tercih ediyorum


Kırpılmış MS şeyler ile. CP1352 veya UTF16 mı demek istediniz?
Cole Johnson

@ColeJohnson: Windows konsol penceresi maalesef hala UTF16 öncesi bir dönemde kalmış. Bununla birlikte, yerleşik konsolla aklı başında bir IDE kullanmak bu sorunu azaltabilir.
Joachim Sauer

@Cole Johnson - CP 65001 (yani utf8) ile yaşayabilirim, ancak örneğin "850 varsayılan" kod sayfası olarak almanın bir yolu yok gibi görünüyor, örneğin, CP 850 veya benzeri bir Alman klavyeniz varsa.
Ingo

1

Hiç fena değil. Fikir, uygulamanızda özel bir günlükleme çerçevesi kullanmak kadar çok basit ve karmaşık olmadığı gerçeğinden kaynaklanabilir.

Ancak, bunun geçersiz bir yaklaşım olduğu anlamına gelmez. Bazı kara büyü voodoo programlama hijinks sonra uygulama akışını kontrol etmek için birçok kez kullandım .


0

Kullanırken yanlış bir şey yok, 'neler oluyor' anlamanıza yardımcı oluyor.

Meslektaşlarınızın / diğer Devs / araçları seninle dalga Ama eğer, her zaman kullanabilirsiniz Logger veya başlatmak JUnit testi!


0

Görüldüğü gibi, Ocational System.out.println ile ilgili en büyük sorun, bunun "kötü alışkanlık kokusu (tm)" olmasıdır. Bunu yaparken kendinizi bulursanız, muhtemelen en sevdiğiniz hata ayıklayıcıyı kullanarak daha rahat hale getirerek etkinliğinizi artırabilirsiniz.

Ayrıca bir hata ayıklayıcı ile, bir kesme noktasının üretim kodunuza kaymayacağından emin olabilirsiniz, System.out.println olabilir.

Bir yan notta, aslında sadece hızlı bir test yapıyorsanız ve bir hata ayıklayıcı kullanmamaya devam ediyorsanız, System.out.println'in bir günlükleme çerçevesi kullanmaktan daha iyi olduğunu düşünüyorum, çünkü yanlışlıkla bir log.debug deyimi bırakırsanız bitti, kök salmak daha zor.


0

İçsel durumun içeriğini yansıtan bir test stratejisi oluşturmak en akıllıca hareket değildir, ancak koddaki hızlı ve kirli testler için burada tek bir baskı çıktı ve onları kaldırmayı hatırladığınız sürece zarar görmez!

Onları kaldırmayı unutma tehlikesi muhtemelen buna karşı önerilmektedir.


Onları kaldırmayı unutmanın problemi nedir? Elbette konsolda daha fazla mesaj olacak. Başka bir sorun görüyor musun?
Kayser
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.