2008-08-28 24 views
13

Trình biên dịch có thể loại bỏ các câu lệnh được sử dụng cho các mục đích gỡ lỗi (chẳng hạn như đăng nhập) từ mã sản xuất hay không? Các câu lệnh debug sẽ cần được đánh dấu bằng cách nào đó, có thể sử dụng chú thích.Làm thế nào để loại bỏ các câu lệnh gỡ lỗi khỏi mã sản xuất trong Java

Thật dễ dàng để đặt thuộc tính (debug = true) và kiểm tra nó ở từng câu lệnh gỡ rối, nhưng điều này có thể làm giảm hiệu suất. Nó sẽ được tốt đẹp nếu trình biên dịch sẽ chỉ đơn giản là làm cho các báo cáo gỡ lỗi biến mất.

Trả lời

22

Hai đề xuất.

Đầu tiên: để ghi nhật ký thực, sử dụng gói ghi nhật ký hiện đại như log4j hoặc ghi nhật ký riêng của java. Đừng lo lắng về hiệu suất rất nhiều, kiểm tra mức độ đăng nhập là theo thứ tự của nano giây. (đó là một so sánh số nguyên).

Và nếu bạn có nhiều hơn một tuyên bố đăng nhập duy nhất, bảo vệ toàn bộ khối:

(log4j, ví dụ :)

if (logger.isDebugEnabled()) { 

    // perform expensive operations 
    // build string to log 

    logger.debug("...."); 
} 

này cho phép bạn thêm các ghi chép kiểm soát khả năng khi chạy. Việc khởi động lại và chạy một bản dựng gỡ lỗi có thể rất bất tiện.

Thứ hai:

Bạn có thể tìm assertions có nhiều những gì bạn cần. Một khẳng định là một tuyên bố mà đánh giá đến một kết quả boolean, với một thông báo tùy chọn:

assert (sky.state != FALLING) : "The sky is falling!"; 

Bất cứ khi nào kết quả khẳng định trong một sai lầm, sự khẳng định thất bại và một AssertionError được ném chứa thông điệp của bạn (đây là một ngoại lệ được kiểm soát, dự định thoát khỏi ứng dụng).

Điều gọn gàng là, chúng được xử lý đặc biệt bởi JVM và có thể chuyển đổi khi chạy xuống cấp lớp, sử dụng tham số VM (không cần biên dịch lại). Nếu không được kích hoạt, không có phí trên không.

+0

Dưới đây là cách bật xác nhận trong Eclipse: [link] (http://www.coderanch.com/t/416987/vc/enable-Assertions-eclipse) –

+0

Đây không phải là câu trả lời. Nó không giải thích làm thế nào để làm cho các câu lệnh 'biến mất' cho trình biên dịch (do đó không hiển thị trong tệp lớp). Bạn có một số thông tin về điều đó không? –

0

Sử dụng Java Preprocessor? (Google foo thấp nhưng đây là một liên kết đến các diễn đàn Joel cũ thảo luận về nó)

10
public abstract class Config 
{ 
    public static final boolean ENABLELOGGING = true; 
} 

import static Config.*; 

public class MyClass 
{ 
    public myMethod() 
    { 
     System.out.println("Hello, non-logging world"); 

     if (ENABLELOGGING) 
     { 
      log("Hello, logging world."); 
     } 
    } 
} 

Trình biên dịch sẽ loại bỏ các khối mã với "Xin chào, đăng nhập trên thế giới." trong đó nếu ENABLE_LOGGING được đặt thành true vì nó là giá trị cuối cùng tĩnh. Nếu bạn sử dụng một obfuscator như proguard, thì lớp Config cũng sẽ biến mất.

Một obfuscator cũng sẽ cho phép những thứ như thay vì điều này:

public class MyClass 
{ 
    public myMethod() 
    { 
     System.out.println("Hello, non-logging world"); 

     Log.log("Hello, logging world."); 
    } 
} 

import static Config.*; 

public abstract class Log 
{ 
    public static void log(String s) 
    { 
     if (ENABLELOGGING) 
     { 
      log(s); 
     } 
    } 
} 

Phương pháp Log # log sẽ làm giảm không có gì trong trình biên dịch, và được loại bỏ bằng các obfuscator, cùng với bất kỳ các cuộc gọi đến phương thức đó và cuối cùng ngay cả lớp Đăng nhập cũng sẽ bị xóa.

0

Java chứa một số loại tiền xử lý của riêng nó. Nó được gọi là APT. Nó xử lý và tạo mã. Tại thời điểm này tôi không chắc làm thế nào điều này sẽ làm việc (tôi đã không thử nó). Nhưng nó có vẻ được sử dụng cho những thứ này.

-2

Để trả lời trực tiếp câu hỏi của bạn: Tôi không biết.

Nhưng đây là một giải pháp khác cho vấn đề của bạn: Trong tâm trí của tôi, có hai câu lệnh va chạm với nhau ở đây: "báo cáo gỡ lỗi" và "mã sản xuất".

Mục đích của các câu lệnh gỡ lỗi là gì? Giúp để loại bỏ các lỗi trong khi (đơn vị) thử nghiệm. Nếu một phần mềm được kiểm tra và làm việc đúng theo yêu cầu, thì các câu lệnh gỡ lỗi sẽ không có gì khác ngoài OBSOLETE.

Tôi rất không đồng ý với việc để lại bất kỳ câu lệnh gỡ lỗi nào trong mã sản xuất. Tôi đặt cược không ai làm phiền kiểm tra các tác dụng phụ của mã gỡ lỗi trong mã sản xuất. Mã có thể làm những gì nó phải làm, nhưng nó làm nhiều hơn thế? Làm tất cả #defines của bạn hoạt động chính xác và thực sự lấy TẤT CẢ mã gỡ lỗi ra? Ai phân tích 100000 dòng mã được xử lý trước để xem liệu tất cả các công cụ gỡ lỗi đã biến mất chưa?

Trừ khi chúng tôi có định nghĩa khác về mã sản xuất, bạn nên xem xét việc đưa ra các câu lệnh gỡ lỗi sau khi mã được kiểm tra và được thực hiện với nó.

+3

Các câu lệnh gỡ rối trong mã sản xuất có thể là phao cứu sinh nếu bạn phải gỡ rối một hệ thống sản xuất (không có trình gỡ lỗi). Và phần mềm không bao giờ được "kiểm tra và làm việc đúng cách", bạn chỉ tiến gần hơn và gần hơn ... – sleske

+0

Bạn muốn xóa hàng trăm câu lệnh gỡ rối? Và sau đó thêm chúng trở lại khi bạn tiếp tục phát triển? Xin lỗi nhưng đây là lý do tại sao #DEFINE đã được phát minh ngay từ đầu. Đây cũng là Java, không phải C. Tại sao trả lời câu hỏi nếu bạn không biết? – Lodewijk

0

Tôi cũng khuyên bạn nên sử dụng khung ghi nhật ký.

logger.IsDebugEnabled() không bắt buộc, chỉ có thể kiểm tra xem hệ thống có ở cấp độ gỡ lỗi nhanh hơn trước khi đăng nhập hay không.

Sử dụng khung ghi nhật ký nghĩa là bạn có thể định cấu hình mức nhật ký khi đang di chuyển mà không cần khởi động lại ứng dụng.

Bạn có thể có khai thác gỗ như:

logger.error("Something bad happened") 
logger.debug("Something bad happend with loads more detail") 
1

Một khả năng khác là đặt câu lệnh if trong chức năng đăng nhập của bạn, bạn sẽ có được ít code theo cách này, nhưng tại các chi phí của một số cuộc gọi chức năng thêm.

Tôi cũng không phải là người hâm mộ lớn loại bỏ hoàn toàn mã gỡ lỗi. Khi bạn đang trong quá trình sản xuất, có thể bạn sẽ cần quyền truy cập vào thông báo gỡ lỗi nếu có sự cố. Nếu bạn loại bỏ tất cả các cấp mã của bạn gỡ lỗi, hơn này không phải là một khả năng.

0

này "trick" dường như lập báo cáo debug của bạn biến mất

public static final boolean DEBUG = false; 

if (DEBUG) { //disapeared on compilation } 

Các post nói rằng javac là đủ thông minh để kiểm tra static final boolean và không bao gồm những điều khoản debug. (Tôi không đích thân thử nó)

Đối với khai thác gỗ, cá nhân tôi donot muốn thấy mã như:

if (logger.isDebugEnabled()) { 
    logger.debug("...."); 
} 
realImportantWork(); 

Những điều ghi chép sao lãng tôi từ realImportantWork(). Đúng cách đối với tôi là:

logger.debug("...."); 
realImportantWork() 

cộng với cấu hình mà không bao gồm tất cả các thư debug trên sản xuất.

Tôi có nghĩa là điều khiển logger.isDebugEnabled() phải là công việc của khung ghi nhật ký chứ không phải công việc của tôi. Hầu hết các khái niệm hỗ trợ khung đăng nhập như "logger", "LogLevel" .. có thể thực hiện thủ thuật.

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