it-swarm-vi.com

Là nhận xét ra mã thực sự luôn luôn xấu?

Thực tế mọi văn bản về chất lượng mã tôi đã đọc đều đồng ý rằng nhận xét mã là một điều xấu. Ví dụ thông thường là ai đó đã thay đổi một dòng mã và để lại dòng cũ ở đó như một nhận xét, dường như để gây nhầm lẫn cho những người đọc mã sau này. Tất nhiên, đó là một điều xấu.

Nhưng tôi thường thấy mình để lại mã nhận xét trong một tình huống khác: tôi viết một thuật toán xử lý hình học hoặc hình học tính toán. Để hiểu loại mã này và để tìm các lỗi tiềm ẩn trong đó, thường rất hữu ích để hiển thị kết quả trung gian (ví dụ: vẽ một tập hợp các điểm vào màn hình hoặc lưu tệp bitmap). Nhìn vào các giá trị này trong trình gỡ lỗi thường có nghĩa là nhìn vào một bức tường số (tọa độ, giá trị pixel thô). Không hữu ích lắm. Viết một trình gỡ lỗi trực quan mỗi lần sẽ là quá mức cần thiết. Tôi không muốn để lại mã trực quan hóa trong sản phẩm cuối cùng (điều này làm tổn hại đến hiệu suất và thường chỉ gây nhầm lẫn cho người dùng cuối), nhưng tôi cũng không muốn mất nó. Trong C++, tôi có thể sử dụng #ifdef để biên dịch có điều kiện mã đó, nhưng tôi không thấy nhiều sự khác biệt giữa điều này:

/* // Debug Visualization: draw set of found interest points
for (int i=0; i<count; i++)
    DrawBox(pts[i].X, pts[i].Y, 5,5);
*/

và điều này:

#ifdef DEBUG_VISUALIZATION_DRAW_INTEREST_POINTS
for (int i=0; i<count; i++)
    DrawBox(pts[i].X, pts[i].Y, 5,5);
#endif

Vì vậy, hầu hết thời gian, tôi chỉ để lại mã trực quan nhận xét, với một bình luận nói những gì đang được trực quan hóa. Khi tôi đọc mã một năm sau đó, tôi thường rất vui vì tôi chỉ có thể bỏ qua mã trực quan hóa và theo nghĩa đen là "xem điều gì đang xảy ra".

Tôi có nên cảm thấy tồi tệ về điều đó? Tại sao? Có một giải pháp ưu việt?

Cập nhật: S. Lott hỏi trong một bình luận

Bạn có bằng cách nào đó "khái quát quá mức" tất cả các mã nhận xét để bao gồm gỡ lỗi cũng như mã lỗi thời, vô nghĩa? Tại sao bạn lại đưa ra kết luận quá khái quát đó?

Gần đây tôi đã đọc "Mã sạch" của Robert Martins, có nội dung:

Rất ít thực hành có ý nghĩa như mã nhận xét. Đừng làm điều này!.

Tôi đã xem lại đoạn văn trong cuốn sách một lần nữa (tr. 68), không có phẩm chất, không có sự phân biệt giữa các lý do khác nhau để nhận xét mã. Vì vậy, tôi tự hỏi nếu quy tắc này là quá khái quát (hoặc nếu tôi hiểu nhầm cuốn sách) hoặc nếu những gì tôi làm là thực hành xấu, vì một số lý do tôi không biết.

53
nikie

Lợi ích của # ifdef trái ngược với nhận xét, là (trên các dự án lớn) bạn có thể có các định nghĩa được liệt kê trong tệp tạo hoặc cấu hình - và do đó, không phải tự mình thực hiện một điều không chú ý, xây dựng và sau đó -theo dõi họ nếu nó ở nhiều nơi. Nhược điểm của việc này là việc thay đổi DEFINE của dự án thường có nghĩa là xây dựng lại toàn bộ, chứ không chỉ thay đổi các tệp.

Mặc dù ... tôi nghĩ rằng "mã nhận xét là một điều xấu" thực sự đề cập đến mã chết rằng mọi người chỉ không muốn xóa vì bất kỳ lý do gì (sợ vứt bỏ thứ gì đó họ đã bỏ ra thời gian có lẽ?). Nó không thực sự về tình huống bạn sẽ dành cho bạn.

58
TZHX

Nếu nó nhận xét, thì nó có thể bị thối: khi bạn đột nhiên quyết định rằng bạn cần nó một lần nữa, bạn nhận ra rằng nó không còn được biên dịch, hoặc cần phải viết lại để làm cho nó phù hợp với những thứ khác đã thay đổi trong thời gian đó.

Nếu bạn để lại mã, nhưng theo cách mà trình biên dịch có thể tối ưu hóa nó đi nếu không cần thiết, thì bạn có lợi từ việc giữ mã cập nhật không phải chịu đựng nhị phân được thêm vào kích thước hoặc hiệu suất thời gian chạy.

Ví dụ, trong C, điều này có nguy cơ bị thối:

/*
doSomeDebugStuff();
*/

Và đây là:

#if 0
doSomeDebugStuff();
#endif

Nhưng điều này là tốt, vì nó luôn được trình biên dịch kiểm tra tính hợp lệ, nhưng có khả năng được tối ưu hóa đi:

if (0)
{
  doSomeDebugStuff();
}

Chỉnh sửa: như những người khác chỉ ra, sử dụng một biểu tượng có ý nghĩa thay vì 0 cho bài kiểm tra thậm chí còn tốt hơn.

25
Graham Borland
// The problem with commented out code is that it can hide what you're actually
// trying to say in a wall of text.  Syntax highlighting may help, but you're 
// still left with this huge ginormous wall of text in front of you, searching
// through it for what the actual answer is. You'd think that mentally it'd be 
// really easy to disregard the comments, but in actual usage, it's a lot harder
// than a one Word answer that can tell you what you're looking for. It's tough.
/* Sometimes they'll even through you off with different comments. */ Yes.
// It's really tough to deal with people that don't like to use source control, 
// that would rather comment lines and lines of code instead of deleting the 
// code and checking in revision.  Cue irrelevant paragraph about the reason why 
// I wrote this instead of just deleting the entire block and replacing it 
// with my intention. Maybe I was hedging my bets? Cue misspelled wrod.  
18
George Stocker

Tôi nghĩ rằng cần phải phân biệt giữa mã nhận xét đã lỗi thời và mã chỉ được sử dụng trong bản dựng gỡ lỗi (hoặc bản dựng "đặc biệt" khác, được biên dịch có điều kiện). Thứ hai là một thực tế phổ biến, và không có gì sai với nó.

Cái trước không nên có mặt trong một cơ sở nguồn, vì hệ thống kiểm soát phiên bản theo dõi những thứ lỗi thời, nếu bạn muốn lấy lại.

15
Alex Budovski

Hầu như không có "luôn luôn" trong mã hóa :) Nếu bạn biết đủ về các lý do đằng sau một hướng dẫn và có lý do thực sự tốt để phá vỡ nó, thì hãy làm như vậy.

Ví dụ, tôi nhận xét mã khi tôi thực hiện "tái cấu trúc kamikaze" và cần một lời nhắc trực quan để thêm lại mọi thứ hoặc nhớ cách mã cũ hoạt động trong một thời gian. Điều quan trọng trong những trường hợp như thế này là bạn sẽ xóa các bình luận sau đó nếu không họ sẽ đơn giản làm lộn xộn mã của bạn.

11
Homde

Đôi khi bạn đặt mã trong các nhận xét của mình để hiển thị cách sử dụng một lớp - điều này rất khác với mã nhận xét được sử dụng để chạy.

8
Ian

Tôi làm rất nhiều đánh giá mã và tôi thấy không có lý do thực sự nào cho mã nhận xét bất kể lý do. Nếu bạn đang sử dụng mã nhận xét cho mục đích gỡ lỗi, bạn có thể tạo cơ chế theo dõi bị vô hiệu hóa trong chế độ phát hành hoặc có các mức theo dõi (luôn luôn tốt để có thể theo dõi trong phiên bản phát hành) hoặc bạn chỉ cần sử dụng trình gỡ lỗi.

Mã nhận xét là xấu bởi vì khi người khác đọc mã - đặc biệt là khi bạn bị căng thẳng khi cố gắng sửa lỗi khi tác giả ban đầu đi nghỉ - có phải rất khó hiểu khi đọc mã, đặc biệt là nếu lỗi là do lỗi. được đặt // ở đầu dòng ... ngay cả khi sử dụng/* bạn có thể vô tình nhận xét điều gì đó đáng lẽ phải có trong đó - hoặc không.

Để giữ cho mã của bạn sạch sẽ và dễ đọc hơn, hãy xóa mã nhận xét, rất khó để đọc các chương trình vì nó không phải đọc mã có thể có hoặc không đáng kể.

3
AndersK

Vâng, đúng vậy.

Ngay cả khi bạn có mã gỡ lỗi mà bạn không muốn trong bản phát hành sản xuất của mình, bạn không nên nhận xét nó. Sử dụng #ifdef 's là tốt hơn, bởi vì sau đó bạn có thể bật và tắt dễ dàng với một #define macro hoặc bằng cách có cấu hình bản dựng riêng. Điều này chắc chắn nhịp đập phải đi vào mã và bình luận/bỏ ghi chú mỗi khối mã gỡ lỗi bằng tay.

Và nếu bạn cần linh hoạt để bật một số khối gỡ lỗi nhưng không phải các khối gỡ lỗi khác, thì bạn nên nhóm các khối gỡ lỗi thành "mức gỡ lỗi".

Một giải pháp tốt hơn là hoàn toàn không sử dụng bộ xử lý trước và sử dụng các tính năng ngôn ngữ bản địa, như hằng số và câu lệnh if. Vì vậy, thay vì

#define DEBUG0
#ifdef DEBUG0
  // debugging code
#endif

bạn có thể có

const bool DEBUG0 = true;
if(DEBUG0)
{
  // debugging code
}

Ưu điểm của việc này, hơn là sử dụng bộ xử lý trước là mã gỡ lỗi của bạn sẽ luôn được trình biên dịch kiểm tra. Điều này làm giảm khả năng nó sẽ bị thối, khi bạn thay đổi mã xung quanh nó.

Bạn sẽ không phải chịu bất kỳ cú đánh hiệu suất nào nếu bạn làm cho cờ boolean sai, bởi vì trình biên dịch hiện đại tối ưu hóa mã không thể truy cập. Tệ nhất, bạn có thể nhận được một cảnh báo trình biên dịch về nó.

2
Dima

Tôi không nghĩ những gì bạn đang làm là hết sức tệ hại nhưng tôi nghĩ ít nhất bạn nên có một số thực tế ý kiến ​​với nó để giải thích những gì nó đang làm, tại sao và làm thế nào và khi nào nên sử dụng nó.

Cá nhân tôi thường đặt loại điều này vào một số loại nỗ lực loại IF DebugMode = TRUE xung quanh mã được đề cập và đặt nó làm tham số dòng lệnh/khởi động. Đối với tôi, điều đó giúp dễ dàng nhận ra rằng đó là lý do tại sao mã ở đó và cách đặt mã mặc dù trong trường hợp của bạn có thể có vấn đề về hiệu năng với sự so sánh nhỏ mà bạn muốn tránh.

Vì vậy, tôi có thể thấy những gì bạn đang làm là một điều ác cần thiết chứ không phải là ra và sai. Nếu bạn có thể tìm cách nào đó để hợp lý hóa nó thì rõ ràng là làm như vậy nhưng tôi sẽ không tự đánh bại mình về điều đó.

1
Jon Hopkins

Tôi nghĩ rằng một trong những lý do khiến mã nhận xét được coi là mùi mã là vì nó chỉ ra rằng lập trình viên đặt nó ở đó không hiểu kiểm soát nguồn của họ hoặc họ không sử dụng bất kỳ mã nào. Một trong số đó khiến người ta nghi ngờ thêm về rất nhiều điều khác mà họ đang làm.

Nếu bạn có một lý do chính đáng cho nó bạn để lại lời giải thích tại sao đó là một lý do chính đáng để tìm thấy nó có lẽ bạn đang làm tốt. Hầu hết những thứ thường được coi là tin xấu cũng có thể là một công cụ hữu ích trong tay phải. Vấn đề là những bàn tay đó hiếm hơn những người nghĩ rằng họ có chúng.

0
glenatron

Nó giúp cung cấp một lịch sử về cách mà (các) tâm trí lập trình viên đang làm việc tại thời điểm đó. Nhưng trong những ngày kiểm soát nguồn phổ biến này, không có lý do gì để bỏ nó trong lần cắt cuối cùng - các phiên bản trước sẽ chứa mã cũ hơn mà bạn cần tham khảo.

0
5arx

Tôi không nghĩ rằng có những điều tuyệt đối ở đây. Thỉnh thoảng tôi để lại mã nhận xét khi nó chỉ là một đoạn nhỏ, đặc biệt nếu có cơ hội hợp lý rằng tôi sẽ sớm nhận ra nó. Về cơ bản, tôi để các đoạn mã đó miễn là chúng không phá vỡ tính dễ đọc của mã thực tế và miễn là chúng không nhân lên ở mọi nơi.

Những gì tôi hoàn toàn từ chối là phương pháp đầy đủ của mã nhận xét. Vâng, tôi đã thấy những người trước đây: WTF. Họ có thể nghỉ ngơi trong thiên đường sửa đổi nguồn ;-)

0
Andres F.