2009-02-21 40 views
9

Chúng tôi có một mã nguồn mở (cũ) java-base, nơi có nhiều tệp (khoảng 5k) có System.out.println's. Chúng tôi đang có kế hoạch loại bỏ chúng vì lý do dọn dẹp/hiệu suất. Làm thế nào chúng ta có thể viết một kịch bản mà sẽ thay thế chúng mà không giới thiệu bất kỳ vấn đề trong mã? Tập lệnh không thể xóa một cách mù quáng các trường hợp sau đây có thể là một vấn đề:Làm thế nào để loại bỏ System.out.println's từ codebase

if() 
    some.code... 
else 
    System.out.println(...); 
DB.close(); 

Tôi đang nghĩ đến việc thay thế chúng bằng ';'. Điều đó sẽ chăm sóc trường hợp trên. Bạn có thấy bất kỳ vấn đề nào khác không? Bất cứ một đề nghị nào khác?

+0

chế độ pontificate trên :-) Đó là (trong số nhiều lý do khác) tại sao tôi luôn sử dụng {} ngay cả đối với một dòng! (Tôi biết nó là di sản và có khả năng không làm của bạn). Tôi sẽ thay thế chúng bằng {} thay vì; nhưng cả hai đều ổn. – TofuBeer

+0

Giáo lý vang lên: Tôi chuẩn bị bình luận chính xác điều tương tự. –

+0

Tôi biết và có thể không có trong mã. Tuy nhiên, vì có rất nhiều tập tin và di sản (mà hầu như luôn luôn có nghĩa là xấu), tôi không muốn mạo hiểm. – amit

Trả lời

24

Bạn đã xem xét các trường hợp ngớ ngẩn:

System.out.println(" Print " + object.changeState()); 

Tôi không nghĩ rằng nó xảy ra nhưng rất có thể là các println thực hiện một phương pháp mà thực sự là thực hiện một số hành động mà hệ thống phụ thuộc vào và có thể giới thiệu các lỗi tinh tế (tin tôi hay không, nhưng tôi đã chứng kiến ​​điều này)

Có thể thay thế bằng bộ ghi và vô hiệu hóa nhật ký có thể thực hiện.

Hoặc tạo ra một đối tượng null sử dụng mô hình NullObject:

public final class DevNull { 
    public final static PrintStream out = new PrintStream(new OutputStream() { 
     public void close() {} 
     public void flush() {} 
     public void write(byte[] b) {} 
     public void write(byte[] b, int off, int len) {} 
     public void write(int b) {} 

    }); 
} 

Và thay thế

System.out.println(); 

Với

DevNull.out.println(); 
+0

Tôi rất thích nó, Oscar. Tôi nghĩ, tôi phải nói. –

+0

Tuyệt vời, tôi phải thoát ra khỏi NetBeans và thử nó. – Paxic

+0

Ý tưởng hay - thậm chí sẽ dễ dàng hơn nếu bạn thay đổi "trường hợp ngớ ngẩn" từ object.stateChanged() thành object.changeState(), nếu không nó giống như một truy vấn đối tượng mà tôi luôn xem là không có thay đổi nghiệp vụ trạng thái đối tượng. ... thói quen cá nhân ... –

1

Cá nhân tôi sẽ sử dụng {} thay vào đó, nhưng tôi nghĩ nó hoạt động giống nhau.

2

Bạn có thể sử dụng một conditional compilation để có một debug xây dựng với báo cáo in và bản phát hành mà không có chúng.

Về cơ bản, ý tưởng là tạo một lớp tĩnh cuối cùng với một boolean tĩnh cuối cùng mà bạn sử dụng làm công tắc tại thời gian biên dịch.

public final class Debug { 
    //set to false to allow compiler to identify and eliminate 
    //unreachable code 
    public static final boolean ON = true; 
} 

Sau đó, bạn chỉ có thể thay thế tất cả các System.out.println báo cáo của bạn với

if(Debug.ON) 
{ 
    System.out.println... 
} 

Kể từ khi trình biên dịch sẽ bỏ qua bất kỳ chi nhánh unreachable mã, bạn chỉ có thể thiết lập ON = false khi bạn làm một xây dựng phát hành và in ấn báo cáo sẽ bị loại trừ khỏi bytecode của bạn.

Lưu ý: Điều này không giải quyết được trường hợp Oscar chỉ ra, trong đó tuyên bố in có thể thay đổi trạng thái của một số đối tượng. Bạn có thể sử dụng trình biên dịch có điều kiện để in ra một đối tượng rỗng khi ở chế độ phát hành, như ông đã gợi ý, thay vì loại bỏ các bản in hoàn toàn.

11

Log4E là một plugin eclipse có tính năng "Replace System.out.println()". Nó sẽ vui vẻ chuyển đổi tất cả các cuộc gọi println pesky thành cuộc gọi log4j. Nó thậm chí sẽ quấn chúng với một kiểm tra mức độ đăng nhập.

+3

liên kết: http://log4e.jayefem.de/ –

6

Bạn có thể bắt đầu bằng cách gọi Systems.setOut và chuyển vào OutputStream của riêng bạn mà không làm gì cả. Điều đó sẽ giúp bạn thấy nếu có một sự thuận lợi. Điều này an toàn hơn là loại bỏ chúng (vì lý do mà Oscar đã chỉ ra - mã hóa bởi tác dụng phụ).Nếu đạt được hiệu suất là không thể bỏ qua sau đó bạn có thể muốn tập trung nỗ lực của bạn ở nơi khác.

Hai vấn đề với phương pháp trên của tôi:

  1. bất kỳ System.out.printlns bạn muốn giữ lại sẽ disapper quá
  2. String bởi ghép vẫn sẽ diễn ra (và có thể tốn kém tùy thuộc vào bao nhiêu có)

Tuy nhiên, đây là một thử nghiệm nhanh để xem bạn có đạt được hiệu suất mà bạn đang tìm kiếm hay không.

0

Tôi đã viết một regex trong perl thay thế chuỗi "System.out.println" bằng "; // System.out.println". Tôi tin rằng có rất ít trường hợp điều này sẽ phá vỡ xây dựng. Nó sẽ trở thành một "else;", được biên dịch thành các lệnh bytecode bằng không.

Có vẻ như đây là những gì bạn đã đề xuất. Nó làm việc cho tôi - ngoại trừ nếu bạn có các câu lệnh bổ sung trên cùng một dòng. Tuy nhiên, đó là phong cách xấu để bắt đầu với (và tôi biết tôi đã không làm điều đó).

8

Mở rộng khái niệm Oscar của bạn có thể làm thậm chí IMHO tốt hơn:

if(!DEBUG) { 
    System.setOut(
     new PrintStream(new OutputStream() { 
      public void close() {} 
      public void flush() {} 
      public void write(byte[] b) {} 
      public void write(byte[] b, int off, int len) {} 
      public void write(int b) {} 

     }); 
    } 
} 

Trong trường hợp này, nếu bạn đang không ở trong chế độ gỡ lỗi hoặc bất kỳ khác hệ thống mặc định ra được thay thế trong nội bộ với việc thực hiện devNull, ngược lại nó làm việc như kỳ vọng. Bằng cách này bạn không phải tìm và thay thế bất cứ thứ gì trong mã của bạn.

+0

Thú vị đủ. Các báo cáo in mới có thể được xử lý với logger và vô hiệu hóa hoàn toàn System.out với điều này. :) – OscarRyz

+0

Vậy, chúng ta có thể gọi phương pháp này là "Oscar Reyes + Bill the Lizard" không? : P: P +1 cho rằng – OscarRyz

+0

Điều này giả định không có mã nào khác đã thực hiện setOut;) Chỉ đùa thôi. Đó là một gợi ý tốt. – amit

0

Bạn có cân nhắc chỉnh sửa các tệp nguồn đó để xóa các dòng không?

Bạn có thể thấy rằng nó sẽ chỉ là một nhà phát triển một vài ngày để đi qua và loại bỏ hầu hết trong số họ. Chúng tôi đã có một vấn đề tương tự và tôi đã thức dậy sớm và đã trải qua tất cả các tệp của chúng tôi để loại bỏ rác.

Tôi đã sử dụng Eclipse và làm sạch tính năng lưu để xóa các mục nhập và nội dung cùng một lúc.

Điều trị khá tuyệt vời của nó!

Các vấn đề liên quan