Tại sao sử dụng System.out.println () lại tệ như vậy? [đóng cửa]


18

Tất nhiên, việc sử dụng khung đăng nhập cho các thông báo lỗi hoặc cảnh báo là rất tốt. Nhưng đôi khi tôi sử dụng System.out.println () nếu tôi muốn thử một cái gì đó mới trong một thời gian ngắn.

Có thực sự rất tệ khi sử dụng System.out.println () cho một số thử nghiệm nhanh?


3
Không. Đó là một bài kiểm tra nhanh, ai quan tâm?
Bryan Boettcher

10
Ai nói nó xấu? Cái gì thay thế?
James

1
Các công cụ đánh giá mã tĩnh @Kayser không phù hợp để kiểm tra nhanh - chúng phù hợp hơn với mã bạn định phát triển với người khác (hoặc người khác sẽ phải hiểu). Bài học tôi dường như đang học trong năm nay là có nhiều không gian vấn đề rất khác nhau, thậm chí trong suốt cả ngày làm việc, đòi hỏi các bộ công cụ và thực tiễn rất khác nhau. Vì vậy, để kiểm tra nhanh, hãy tặc lưỡi và sử dụng Groovy :)
Bill K

1
Hãy thử sử dụng System.err.println()và xem những gì sẽ xảy ra. Tôi đoán công cụ này nghĩ rằng bạn đang sử dụng System.outsai mục đích.
Izkata

2
Vấn đề chính là khả năng mở rộng và kiểm soát. Nếu bạn có hàng triệu câu nói này, làm thế nào bạn có thể thấy những gì bạn cần xem. Nếu bạn cần phản ứng với một trong những điều này, làm thế nào bạn có thể làm điều đó theo chương trình. Các khung ghi nhật ký thường là hai suy nghĩ được áp dụng cho System.out.

Câu trả lời:


18

Như được tiết lộ trong các bình luận, câu hỏi thực sự được đặt ra là, Tại sao các công cụ phân tích mã tĩnh lại sử dụng System.out.println?

Lý do là việc gửi tin nhắn đến thiết bị xuất chuẩn thường không phù hợp trong môi trường sản xuất. Nếu bạn đang mã hóa thư viện, thư viện sẽ trả lại thông tin cho người gọi, không in ra thiết bị xuất chuẩn. Nếu bạn đang mã hóa một ứng dụng GUI, thông tin sẽ được trình bày cho người dùng, chứ không phải nơi mà thiết bị xuất chuẩn sẽ được trỏ (có thể không ở đâu). Nếu bạn đang mã hóa máy chủ (hoặc thứ gì đó chạy trong thùng chứa phía máy chủ), bạn nên sử dụng bất kỳ phương tiện ghi nhật ký nào mà khung đã cung cấp. Và kể từ đó trở đi.

Nhưng nếu bạn đang sử dụng println để gỡ lỗi hoặc phát triển, hoặc bạn đang viết chương trình và đọc stdin và viết lên thiết bị xuất chuẩn, println hoàn toàn ổn. Không có gì sai với nó cho những trường hợp như vậy.


3
Câu trả lời tốt đẹp. Cảm ơn .. +1 cho "Nếu bạn đang mã hóa ứng dụng GUI, thông tin sẽ được hiển thị cho người dùng, chứ không phải nơi xuất hiện lỗi xuất hiện (có thể không ở đâu)"
Kayser

10

Tất cả stdoutđược đệm, và do đó, có thể chương trình của bạn sẽ bị sập sau khi bạn gọi println(), nhưng trước khi nó đến màn hình.

Với điều đó đã được nói, kịch bản này là thực sự không thể. Đi trước và sử dụng nó, nhưng chỉ cần giữ giới hạn nhỏ đó trong tâm trí của bạn.


Ít nhất hai trình thông dịch Python chính cố gắng hết sức để xóa tất cả các tệp đang mở trước khi thoát, ngay cả khi lối ra là do một ngoại lệ không rõ ràng. Đừng JVM làm điều gì đó tương tự?

1
@delnan, Có thể, nhưng chuyện gì cũng có thể xảy ra. . chỉ cần nhận thức được nó.
riwalk

1
Mã tuôn ra thiết bị xuất chuẩn nằm trong chính VM và do đó không bị ảnh hưởng bởi các lỗi trong ngôn ngữ mà VM thực hiện. Điểm tốt về kết thúc quá trình bắt buộc. Nhưng lưu ý rằng, ví dụ SIGTERM của Unix và hầu hết các tín hiệu khác có thể bị bắt để dọn dẹp như thế này - mặc dù không hoạt động với SIGKILL cực đoan hơn.

2
Tôi không nghĩ rằng tôi đã từng thấy điều này hoặc nghe về nó xảy ra, mặc dù tôi đã thấy các vấn đề khác. Vấn đề này cũng không có khả năng trở nên tốt hơn với các công cụ như logger vì chúng có khả năng sử dụng System.out làm công cụ cơ bản.
Bill K

@delnan Đừng bao giờ cho rằng mã dọn dẹp của bạn được đảm bảo để chạy ... và không bao giờ đặt mã giao dịch kinh doanh quan trọng vào các khối cuối cùng;) System.out rất tốt để gỡ lỗi, nhưng hãy chú ý đến việc đệm.
Steven

8

System.outchỉ là một bọc BufferedOutputStream. Điều này có thể giống với bất kỳ khung ghi nhật ký nào bạn sẽ sử dụng, các khung chỉ cung cấp nhiều chức năng hơn dưới dạng cấu hình và đích của đầu ra nhật ký của bạn


4
Điều này không thực sự trả lời câu hỏi. "Nó có tồi không?"
serserg

@Berg - Bởi vì một phần của câu hỏi hoàn toàn phụ thuộc vào ngữ cảnh. (hoặc chỉ, không, nó không tệ)
spin_plate

7

Thật tệ nếu bạn đang làm việc trên một chương trình không tầm thường và bạn

  • Đang sử dụng System.out như một cái nạng thay vì kiểm tra đơn vị tự động (JUnit)
  • Dành nhiều thời gian để tạo và xóa hoặc nhận xét / bỏ ghi chú System.out

1
Hầu hết các IDE nên có các phím nóng để tự động hoàn thành System.out.println, bình luận / bỏ ghi chú một dòng và xóa một dòng. Về nguyên tắc, bạn đúng khi cố gắng tránh sử dụng nó quá mức, nhưng ít nhất bạn có thể tiết kiệm thời gian theo cách này.
Steven

7

Có một vài lưu ý về việc sử dụng System.out , ngay cả trong mã vứt đi.

Một vấn đề lớn là nó thường chậm . Ví dụ: nếu bạn đang cố gắng có được một ý tưởng sơ bộ về tốc độ của một số mã (lưu ý rằng các dấu hiệu vi mô là khó ), sau đó thêm một mãSystem.out.println() có thể thực sự làm rối loạn thời gian của bạn (vì nó đồng bộ hóa và thường chờ đầu ra thực tế đến hiển thị cho người dùng trước khi quay trở lại).

Ngoài ra, tôi sẽ không lo lắng quá nhiều về nó trong mã vứt đi. Nếu bạn có ý định cam kết nó (có thể là mã sản xuất hoặc mã thử nghiệm), thì bạn nên loại bỏ nó và thay thế nó bằng một cuộc gọi đăng nhập propper (có, ngay cả trong mã thử nghiệm).


Hiệu suất là một cuộc tranh luận tốt ..
Kayser

4

Như thường lệ, câu trả lời là phụ thuộc vào nó. Nếu ứng dụng của bạn đã có khung đăng nhập, thì bạn cũng có thể sử dụng nó. Nó không thể là ít có khả năng hơnprintln() , và bạn có thể được hưởng lợi từ các tính năng khác nó cung cấp-stack dấu vết, bối cảnh thêm, định dạng tốt hơn, và như vậy. Ngoài ra còn có khả năng khác biệt là các khung ghi nhật ký cung cấp khả năng phục hồi lỗi tốt hơn, đảm bảo rằng các nhật ký của bạn được viết thành công ngay cả trong trường hợp xảy ra lỗi nghiêm trọng.

Vì vậy, câu hỏi trở thành khi thêm một hệ thống đăng nhập ở nơi đầu tiên. Đây là một lời kêu gọi phán xét: bạn không muốn thêm nó quá sớm, chỉ để biết rằng bạn thực sự không có nhu cầu về nó. Bạn cũng không muốn thêm nó quá muộn và thực hiện quá nhiều công việc chuyển đổi từ giải pháp đặc biệt của mình.

Nếu bạn phát hiện ra rằng bạn đang đăng nhập nhiều println(), thì cơ sở mã của bạn đang cố gắng nói với bạn rằng nó đang trải qua những cơn đau ngày càng tăng. Tại thời điểm đó, đáng để đầu tư vào đăng nhập thích hợp.


3

Tôi thường gặp vấn đề là System.out.print sử dụng bảng mã "mặc định hệ thống", thường là UTF-8 trong Linux, nhưng một số nội dung MS bị bỏ qua trong Windows.

Điều này có thể dẫn đến các ký tự unicode được in hoặc không được in chính xác ra màn hình, tùy thuộc vào nơi chương trình chạy.

Do đó, tôi thích PrintWriter tùy chỉnh hơn System.out


Bằng cách bỏ qua các công cụ MS. Ý bạn là CP1352 hay UTF16?
Cole Johnson

@ColeJohnson: Cửa sổ bảng điều khiển Windows không may vẫn bị kẹt trong thời kỳ tiền UTF16. Tuy nhiên, sử dụng một IDE lành mạnh với bảng điều khiển tích hợp có thể làm giảm vấn đề đó.
Joachim Sauer

@Cole Johnson - Tôi có thể sống với CP 65001 (tức là utf8), nhưng dường như không có cách nào để có được điều này dưới dạng codepage "mặc định hệ thống", ví dụ như khi bạn có bàn phím tiếng Đức, bạn có CP 850 hoặc một số như vậy.
Ingo

1

Nó không tệ chút nào. Khái niệm này có thể xuất phát từ thực tế là nó rất đơn giản và không phức tạp như sử dụng khung ghi nhật ký chuyên dụng trong ứng dụng của bạn.

Tuy nhiên, điều này không có nghĩa là đó là một cách tiếp cận không hợp lệ. Tôi đã sử dụng nó nhiều lần để kiểm tra luồng ứng dụng sau một số trò chơi lập trình ma thuật đen .


0

Không có gì sai khi sử dụng nó, nó giúp bạn tìm ra 'chuyện quái gì đang xảy ra'.

Nhưng nếu đồng nghiệp / nhà phát triển / công cụ khác đang chế giễu bạn, bạn luôn có thể sử dụng Logger hoặc bắt đầu thử nghiệm Junit !


0

Vấn đề lớn nhất với System.out.println, như tôi thấy, đó là "mùi thói quen xấu (tm)". Nếu bạn thấy mình làm điều này, thì có lẽ bạn có thể cải thiện hiệu quả của mình bằng cách thoải mái hơn khi sử dụng trình gỡ lỗi yêu thích của bạn.

Ngoài ra với trình gỡ lỗi, bạn biết chắc chắn rằng một điểm dừng sẽ không rơi vào mã sản xuất của bạn, trong khi System.out.println có thể.

Bên cạnh đó, nếu bạn thực sự chỉ đang thực hiện một thử nghiệm nhanh và kiên trì không sử dụng trình gỡ lỗi, tôi nghĩ System.out.println tốt hơn so với sử dụng khung ghi nhật ký, vì nếu bạn vô tình để lại câu lệnh log.debug khi bạn xong rồi, khó nhổ tận gốc.


0

Xây dựng toàn bộ chiến lược thử nghiệm xung quanh việc lặp lại nội dung của trạng thái nội bộ không phải là bước đi thông minh nhất nhưng đối với các thử nghiệm mã nhanh và bẩn trong quá trình phát triển bản in kỳ lạ ở đây và sẽ không bị tổn thương chừng nào bạn còn nhớ loại bỏ chúng!

Nguy cơ quên không loại bỏ chúng có lẽ là lý do tại sao nó được khuyên chống lại.


Vấn đề với việc quên loại bỏ chúng theo ý kiến ​​của bạn là gì? Chắc chắn sẽ có một số tin nhắn nhiều hơn trên bảng điều khiển. Bạn có thấy vấn đề nào khác không?
Kayser
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.