Nhận xét là một mã mùi


100

Một đồng nghiệp của tôi tin rằng bất kỳ việc sử dụng nhận xét trong mã nào (nghĩa là không phải phương thức kiểu javadoc hoặc nhận xét lớp) là mùi mã . Bạn nghĩ sao?


44
Tôi sẽ đưa ra bất kỳ câu trả lời nào nói "không".
Nicole

2
@Renesis Đó là mùi của thần thánh.
ixtmixilix

107
Đồng nghiệp của bạn đã thực hiện một khái quát sâu rộng, điều đó tự động có nghĩa là anh ta sai. :)
Alex Feinman

5
@Mongus, tôi không đồng ý. Các bình luận trong ví dụ của bạn là xấu không phải vì chúng là các bình luận, mà bởi vì chúng gần với mã mà sau đó thay đổi. Họ nên nói TẠI SAO chứ không phải CÁI GÌ .

5
@Alex, đó không phải là một sự khái quát sâu rộng, do đó là sai (kết quả là anh ta không sai)?

Câu trả lời:


167

Chỉ khi nhận xét mô tả những gì mã đang làm.

Nếu tôi muốn biết những gì đang xảy ra trong một phương thức hoặc khối, tôi sẽ đọc mã. Dù sao, tôi hy vọng rằng bất kỳ nhà phát triển nào làm việc trong một dự án nhất định ít nhất cũng đủ quen thuộc với ngôn ngữ phát triển để đọc những gì được viết và hiểu những gì nó đang làm.

Trong một số trường hợp tối ưu hóa cực độ, bạn có thể đang sử dụng các kỹ thuật khiến ai đó khó theo dõi những gì mã của bạn đang làm. Trong những trường hợp này, các bình luận có thể và nên được sử dụng để không chỉ giải thích lý do tại sao bạn có tối ưu hóa như vậy, mà cả mã đang làm gì. Một nguyên tắc tốt là sẽ có người khác (hoặc nhiều người khác) làm quen với ngôn ngữ triển khai và dự án xem mã của bạn - nếu họ không thể hiểu cả lý do và cách thức, thì bạn nên bình luận cả lý do và Làm thế nào.

Tuy nhiên, những gì không rõ ràng trong mã là lý do tại sao bạn đã làm một cái gì đó. Nếu bạn thực hiện một cách tiếp cận có thể không rõ ràng với người khác, bạn nên có một nhận xét giải thích lý do tại sao bạn đưa ra quyết định mà bạn đã làm. Tôi nghi ngờ rằng bạn thậm chí có thể không nhận ra rằng cần có một nhận xét cho đến sau khi một cái gì đó giống như đánh giá mã, nơi mọi người muốn biết lý do tại sao bạn làm X thay vì Y - bạn có thể ghi lại câu trả lời của mình cho người khác xem nó trong tương lai.

Tuy nhiên, điều quan trọng nhất là thay đổi nhận xét của bạn khi bạn thay đổi mã. Nếu bạn thay đổi một thuật toán, hãy chắc chắn cập nhật các nhận xét với lý do tại sao bạn đi với thuật toán X trên Y. Nhận xét cũ là một mùi mã thậm chí còn lớn hơn.


8
Tôi đồng ý với câu trả lời này vì một bình luận vis, nhưng tôi cũng đã xem nó được trích dẫn là một lý do cho việc thiếu tài liệu, đó là sai. Đọc mã là một nỗi đau trong ass đôi khi. Bạn không cần phải xem mã cho một phương thức để tìm ra phương thức đó làm gì. Bạn sẽ có thể tìm ra nó từ tên và nhận thêm một số chi tiết từ các tài liệu. Khi đọc mã, bạn thường phải chuyển từ lớp này sang lớp khác, và tập tin thành tập tin. Điều này đặc biệt là một vấn đề trong các ngôn ngữ động, trong đó việc viết một IDE có thể xử lý tất cả những điều này là không tầm thường.
davidtbernal

1
Dù sao, đôi khi bạn cũng phải bình luận CÁCH nếu nó phức tạp (đặc biệt nếu nó được tối ưu hóa hoặc bất kỳ loại hoạt động không tầm thường nào khác). Nếu tôi phải dành hơn 5 phút để đọc một khối mã để hiểu những gì nó đang làm, có thể khá bực bội ...
Khelben

3
"Chỉ khi nhận xét mô tả những gì mã đang làm." Hoặc nếu bình luận mô tả những gì mã được sử dụng để làm; mã đã thay đổi nhưng bình luận thì không.
Bruce Alderman

1
Làm thế nào để bạn kiểm tra rằng nhận xét của bạn là chính xác? Tại sao không viết bình luận của bạn như một bài kiểm tra? Bất kỳ nhà bảo trì nào trong tương lai đều có thể sử dụng thử nghiệm làm tài liệu kiểm chứng cho mã. Nếu bình luận có liên quan đến việc thực thi mã, thì điều đó / phải / có thể được xác nhận. Nếu bình luận không liên quan gì đến việc thực thi mã, vậy thì nó đang làm gì trong mã mà chỉ lập trình viên sẽ nhìn?
flamingpenguin

2
@ back2dos, nếu bạn thường xuyên nôn mửa khi đọc mã người khác, tôi rất vui vì chúng tôi không chia sẻ văn phòng ...

110

Điều này đặc biệt khó chịu khi nghe vào lúc này, tôi đã dành một chút thời gian vào cuối tuần này để xem mã rất nổi tiếng, rất sạch sẽ, không bị lỗi khi thực hiện một thuật toán nghiên cứu (một thuật toán chưa được công bố thực sự). Tôi cấp cao quen thuộc với nó, anh chàng ngồi cạnh tôi là nhà phát minh và mã được viết bởi một vài năm trước bởi một người khác. Chúng tôi hầu như không thể làm theo nó.

Đồng nghiệp của bạn không đủ kinh nghiệm, rõ ràng.


16
Tôi tò mò nhìn vào "mã được đặt tên tốt, rất sạch sẽ, không bị lỗi" rất khó theo dõi. Bất kỳ mã nào tôi sẽ phân loại như vậy rất dễ theo dõi. Tôi chắc chắn sẽ không đi xa đến mức "đồng nghiệp của bạn không đủ kinh nghiệm, rõ ràng".
Liggy

8
@Liggy: Tôi sẽ. Đây là một thuật toán nghiên cứu, không phải là một ứng dụng kinh doanh.
Paul Nathan

9
Tôi đã từng có một đoạn mã mà bạn phải điền các trường vào một đối tượng cột cơ sở dữ liệu (bên thứ 3) theo thứ tự "sai" (được xác định bởi "logic" của quy trình và các tiêu chuẩn mã hóa của chúng tôi) - thực hiện theo thứ tự chúng tôi 'thường sử dụng và nó sẽ sụp đổ. Không có số lượng đọc mã nào có thể cho bạn biết điều này vì vậy nó hoàn toàn tích cực, phải có một nhận xét - và đó không phải là mùi, ít nhất là không phải là mã mà chúng tôi đã kiểm soát (đó là điểm mấu chốt). Một sự thiếu sót hoàn toàn và hoàn toàn không có ý kiến ​​cũng nhiều mùi như những bình luận kém.
Murph

29
Toán, toán, toán. Không phải tất cả các mã đều thực hiện keo IoC tầm thường và 'giá * số lượng'. Toán học phức tạp không thể được thực hiện một cách kỳ diệu để tự giải thích.
bmargulies

4
@Liggy, mã triển khai các cơ sở dữ liệu phức tạp có thể hoàn toàn không thể hiểu được nếu không có tài liệu mở rộng.

75

Bình luận nên giải thích tại sao chứ không phải như thế nào.

Howloại bình luận thường được xử lý tốt hơn với việc sử dụng tái cấu trúc. Cá nhân, tôi thường tránh bình luận ủng hộ tái cấu trúc.

Trước:

# convert to cents
a = x * 100

# avg cents per customer 
avg = a / n

# add to list
avgs < avg
t += 1

sau:

total_cents = total * 100
average_per_customer = total_cents / customer_count

track_average(average_per_customer)

26
Tôi đồng ý với lý do tại sao không phải là một phần và tái cấu trúc của bạn hoạt động như thế nào trong ví dụ này, nhưng với mã phức tạp hơn, không có số lượng biến đổi / chức năng đổi tên / tái cấu trúc sẽ có ý nghĩa hoàn hảo, và vẫn cần bình luận ở đó.
GSto

3
Ví dụ tốt, nhưng tại sao hệ thống làm việc với xu trái ngược với đô la? Câu hỏi đó trở nên có liên quan trong các hệ thống tài chính nơi bạn có thể thấy tiền tệ phân đoạn xuất hiện.
rjzii

3
@ Bắt đầu tên của hàm nên nói nó làm gì.
Alb

3
@GSto, tôi không thể không đồng ý nhiều hơn. Nếu mã phức tạp, nó nên được chia thành các phương thức / hàm nhỏ hơn với các tên thích hợp mô tả hành động.
CaffGeek

1
Bạn giả sử rằng bạn có toàn quyền kiểm soát cơ sở mã.
LennyProgrammer

32

Tôi tuyên bố đồng nghiệp của bạn là một kẻ dị giáo! Những đôi giày heretic-burnin 'của tôi đâu rồi?

Nhận xét ám ảnh là xấu và đau đầu bảo trì, và bình luận không thể thay thế cho các phương thức, lớp, biến được đặt tên tốt, v.v. Nhưng đôi khi đặt ra lý do tại sao một cái gì đó lại có thể vô cùng quý giá đối với kẻ ngốc nghèo phải duy trì mã trong sáu tháng - đặc biệt là khi tên ngốc đáng thương đó trở thành bạn.

Một số ý kiến ​​thực tế từ mã tôi đang làm việc:


    // If this happens, somebody's been screwing around with the database definitions and
    // has removed the restriction that a given alarm may have only one entry in the 
    // notifications table.  Bad maintenance programmer!  Bad!  No biscuit!



    // If an alert is active on our side but inactive on theirs, that might mean
    // they closed the alert.  (Or that we just haven't told them about it yet.)  The
    // logic comes later; for now, we'll just compile it in a list.



    // If we know for a fact that an alarm isn't getting through, we're going to whine pretty
    // aggressively about it until it gets fixed.


7
+1 cho ý kiến ​​tốt đẹp. Không có số lượng mã nào có thể nói "Nếu điều này xảy ra, ai đó đang làm rối tung các định nghĩa cơ sở dữ liệu".
DistantEcho

9
@Niphra, tốt, chúng tôi có thể ném một SomebodyScrewedAroundWithDatabaseException...

@ Thorbjørn +1, Nếu mã biết điều gì sai thì hãy báo cáo. Các khách hàng hỗ trợ kỹ thuật có thể tải lại DB của họ và tránh cuộc gọi dịch vụ.
Tim Williscroft

@Tim, vì khách hàng có thể thấy điều này, việc đặt tên trung lập hơn có thể phù hợp.

3
Chắc chắn, hãy nhớ: không bao giờ sử dụng tên ngớ ngẩn. Khách hàng sẽ luôn nhìn thấy chúng.
Tim Williscroft

29

Lý tưởng nhất, mã phải được mã hóa tốt đến mức nó phải tự động khám phá. Trong thế giới thực, chúng ta biết rằng mã cũng rất cần chất lượng đôi khi cần bình luận.

Điều bạn tuyệt đối nên tránh là "dự phòng mã nhận xét" (những bình luận không thêm bất cứ điều gì vào mã):

i++; // Increment i by 1

Sau đó, nếu có một tài liệu và thiết kế mã tốt (và được duy trì / căn chỉnh), việc bình luận thậm chí còn ít hữu ích hơn.

Nhưng trong một số trường hợp, các bình luận có thể là một trợ giúp tốt về khả năng đọc mã:

while( foo )
{
     if( dummy )
     {
     }
     else // !dummy
     {
     }
} // end while( foo )

Đừng quên rằng bạn phải duy trì và giữ đồng bộ các bình luận ... bình luận lỗi thời hoặc sai có thể là một nỗi đau khủng khiếp! Và, như một quy luật chung, bình luận quá nhiều có thể là một triệu chứng của lập trình xấu.


2
Quy ước đặt tên tốt và mã có cấu trúc tốt sẽ giúp bạn giảm các ý kiến ​​cần thiết. Đừng quên rằng mỗi dòng bình luận bạn thêm vào đó là một dòng mới để duy trì !!
Gabriel Mongeon

81
Tôi ghét khi mọi người sử dụng ví dụ thứ hai trong câu hỏi của bạn. } //end whilechỉ có nghĩa là bắt đầu của vòng lặp while ở rất xa, thậm chí bạn không thể nhìn thấy nó và không có gợi ý nào cho thấy mã bạn đang xem nằm trong một vòng lặp. Tái cấu trúc nặng nên được ưu tiên nghiêm túc để nhận xét về cách cấu trúc mã.
Carson Myers

4
@Carson: trong khi giữ các khối ngắn là một quy tắc nổi tiếng, điều đó không có nghĩa là chúng ta luôn có thể áp dụng nó.
Wizard79

4
@Carson: Một trong những dự án tôi làm việc không có đủ mã đánh giá, dẫn đến một bộ sưu tập các tệp JSP có độ phức tạp theo chu kỳ "OMFG JUST KILL YOUSELF." Tái cấu trúc những thứ đẫm máu đại diện cho những ngày làm việc cần phải được chi tiêu ở nơi khác. Những } // end whilebình luận có thể là một cứu cánh.
BlairHippo

11
@BlairHippo: "Mùi mã là bất kỳ triệu chứng nào trong mã nguồn của chương trình có thể chỉ ra vấn đề sâu hơn". Tất nhiên bình luận là một trình cứu sinh, nhưng vòng lặp OMGWTF là "vấn đề sâu hơn" đã nói ở trên và sự cần thiết của trình cứu sinh là một chỉ số rõ ràng;)
back2dos

26

Phân loại xác định một phương pháp hoặc quy trình như một "mùi mã" là "mùi nhiệt tâm". Thuật ngữ này đang trở thành "được coi là có hại" mới.

Xin nhớ rằng tất cả những thứ này được cho là hướng dẫn.

Nhiều câu trả lời khác đưa ra lời khuyên tốt khi bình luận được bảo hành.

Cá nhân tôi sử dụng rất ít ý kiến. Giải thích mục đích của các quá trình không rõ ràng và để lại mối đe dọa tử vong thường xuyên cho bất kỳ ai có thể đang cân nhắc thay đổi mọi thứ theo cách riêng của họ trong vài tuần điều chỉnh.

Tái cấu trúc mọi thứ cho đến khi một học sinh mẫu giáo có thể hiểu rằng đó có thể không phải là cách sử dụng hiệu quả thời gian của bạn và có thể sẽ không hoạt động tốt như một phiên bản ngắn gọn hơn.

Nhận xét không ảnh hưởng đến thời gian chạy, vì vậy vấn đề tiêu cực duy nhất cần xem xét là bảo trì.


8
Tôi nghĩ rằng "chống mẫu" là "có hại" mới. Một mùi mã chỉ là một cái gì đó cần xem xét kỹ hơn để dọn dẹp có thể.
Jeffrey Hantin

1
Tôi không đồng ý rằng chống mẫu cũng đủ điều kiện. Cả hai đều được sử dụng theo cách đó với chống mẫu được sử dụng thay vì mùi khi thiết kế đủ phức tạp mà rõ ràng đó là một sự lựa chọn có chủ ý. Trong cả hai trường hợp, tôi không đồng ý với khái niệm rằng có một nguồn chính xác tuyệt đối về những điều này.
Hóa đơn

4
+1 cho "Tái cấu trúc mọi thứ cho đến khi một học sinh mẫu giáo có thể hiểu rằng đó có thể không phải là cách sử dụng hiệu quả thời gian của bạn và có thể sẽ không thực hiện tốt như một phiên bản ngắn gọn hơn."
Earlz

23

Trong một số trường hợp, không có số lượng đặt tên tốt, tái cấu trúc, vv có thể thay thế một nhận xét. Chỉ cần nhìn vào ví dụ thực tế này (ngôn ngữ là Groovy):

  response.contentType="text/html"
  render '{"success":true}'

Trông lạ nhỉ? Có lẽ là một lỗi sao chép-dán? Tiếng khóc cho một lỗi?

Bây giờ giống nhau với ý kiến:

  // DO NOT TOUCH THE FOLLOWING TWO LINES; the ExtJS UploadForm requires it exactly like that!!!
  response.contentType="text/html"  // must be text/html so the browser renders the response within the invisible iframe, where ExtJS can access it
  render '{"success":true}'         // ExtJS expects that, otherwise it will call the failure handler instead of the succss handler

hàm Prime_extjs_uploadform () {answer.contentType = 'text / html'; kết xuất '{"thành công": true}'; } Prime_extjs_uploadform ();
DrPizza

23

Vấn đề chính ở đây là ý nghĩa của thuật ngữ "mùi mã".

Nhiều người (bao gồm cả bạn, tôi nghĩ) hiểu một mùi mã là một cái gì đó gần với một lỗi hoặc ít nhất là một cái gì đó cần phải được sửa chữa. Có lẽ bạn nghĩ về nó như một từ đồng nghĩa với "chống mẫu".

Đây không phải là ý nghĩa của thuật ngữ!

Ẩn dụ mùi mã bắt nguồn từ Wards Wiki và họ nhấn mạnh:

Lưu ý rằng CodeSmell là một gợi ý rằng có thể có gì đó không đúng, không chắc chắn. Một thành ngữ hoàn toàn tốt có thể được coi là CodeSmell vì nó thường bị sử dụng sai hoặc vì có một cách thay thế đơn giản hơn, hoạt động trong hầu hết các trường hợp. Gọi một cái gì đó là CodeSmell không phải là một cuộc tấn công; nó chỉ đơn giản là một dấu hiệu cho thấy một cái nhìn gần hơn được bảo hành.

Vì vậy, ý nghĩa của các bình luận là mùi mã: có nghĩa là khi bạn nhìn thấy một bình luận, bạn nên tạm dừng và nghĩ: "Hmmm, tôi cảm thấy một gợi ý rằng một cái gì đó có thể được cải thiện". Có lẽ bạn có thể đổi tên một biến, thực hiện "phương pháp trích xuất" - tái cấu trúc - hoặc có lẽ nhận xét thực sự là giải pháp tốt nhất.

Đó là những gì nó có nghĩa là cho ý kiến ​​là mã mùi.

EDIT: Tôi chỉ tình cờ đọc được hai bài báo này, điều này giải thích nó tốt hơn tôi:


2
Tôi choáng váng khi mất 2 tháng để đưa ra câu trả lời này. Nó cho thấy mức độ hiểu lầm của thuật ngữ này lan rộng như thế nào.
Paul Butcher

Khẳng định trường hợp chung vẫn sai. Bạn không nói, "Tôi đang xem mã nhận xét. Đó là một dấu hiệu xấu."
Stuart P. Bentley

1
@Stuart: Bạn đang xem hai đoạn mã, cả hai đều có mức nhận xét phù hợp. (Vấn đề này không phải là về số lượng bình luận thích hợp, mà là về cách bạn đánh giá mã dựa trên số lượng bình luận.) Một người không có ý kiến, người kia có hàng tấn. Mà bạn nhìn kỹ hơn? - Nhận xét là một dấu hiệu cho thấy mã phức tạp và tinh tế và do đó nhiều khả năng có vấn đề.
David Schwartz

Đây là câu trả lời chính xác.
vidstige

21

Tôi nghĩ quy tắc này khá đơn giản: hãy tưởng tượng một người hoàn toàn xa lạ nhìn thấy mã của bạn. Bạn có thể sẽ là một người xa lạ với mã của riêng bạn trong 5 năm. Cố gắng giảm thiểu nỗ lực tinh thần để hiểu mã của bạn cho người lạ này.


8
+1 Đối với bất kỳ nhà phát triển nào chưa từng làm việc trong một dự án đủ lâu để trải nghiệm điều này, hãy tin tôi rằng điều đó sẽ xảy ra. Bất cứ khi nào tôi học điều này một cách khó khăn và phải học lại mã của riêng mình, tôi không để mình mắc lỗi tương tự hai lần và nhận xét nó trước khi tôi chuyển sang một thứ khác.
Nicole

Không, bạn nên tưởng tượng một kẻ tâm thần biết bạn sống ở đâu: họ sẽ vui vẻ duy trì mã của bạn chứ?
Richard

4
Tôi thường xuyên trở thành một kẻ tâm thần khi tôi thấy mã không thể đọc được.
LennyProgrammer

3
5 năm? Giống như 5 phút. ;)
Alex Feinman

11

Một ý tưởng tốt để có những bình luận đúng là bắt đầu bằng việc viết bình luận.

// This function will do something with the parameters, 
// the parameters should be good according to some rules.
myFunction(parameters)
{
    // It will do some things to get started.

    // It will do more with the stuff.

    // It will end doing things with the stuff.
}

Điều này cho phép bạn trích xuất các phương thức dễ dàng để thậm chí loại bỏ các bình luận,
chỉ cần để mã cho những điều này ! Xem cách viết lại (cắt / dán) theo cách rất hay:

// This function will do something with the parameters, 
// the parameters should be good according to some rules.
myfunction(parameters)
{
  var someThing = initializedWithSomething;

  doSomethingWith(someThing);

  doMoreWith(someThing);

  endDoingThingsWith(someThing);

  return someThing;
}

// This function will do some things to get started,
// the parameters should be good according to some rules.
doSomethingWith(parameters)
{
  parameters.manipulateInSomeWay();
  ... etc ...
}

... etc ...

Đối với những thứ không thể tách rời, chỉ cần trích xuất các phương thức và nhập mã dưới các bình luận.

Đây là những gì tôi thấy là một cách hữu ích để tiếp tục bình luận ở mức tối thiểu, thật sự vô ích khi bình luận từng dòng ... Chỉ ghi lại một dòng duy nhất nếu đó là về khởi tạo giá trị ma thuật hoặc ý nghĩa của nó.

Nếu các tham số được sử dụng quá nhiều, thì chúng phải là thành viên riêng trong lớp của bạn.


1
Đây là những gì tôi làm. Nếu bạn nghĩ rằng bạn cần bình luận, tôi có thể khuyên bạn nên thử điều này như một sự thay thế.
bzlm

10

Tôi nghĩ rằng câu trả lời là thông thường "Nó phụ thuộc". Mã nhận xét chỉ để nhận xét mã là một mùi. Mã nhận xét bởi vì bạn đang sử dụng thuật toán tối nghĩa, thứ tự cường độ nhanh hơn sẽ tiết kiệm cho lập trình viên bảo trì (thường là tôi 6 tháng sau khi tôi viết nó) nửa ngày chọc qua mã để xác định xem nó đang làm gì.


10
// Dear me in the future. Please, resolve this problem.

hoặc là

// You think this code was written by somebody else. 
// No, it wasn't. You ([some name]) did it.

Ah, chân thành cầu xin cho bản thân tương lai.
Anthony Pegram

8

Nhận xét mã chắc chắn không phải là "mùi mã". Niềm tin này thường xuất phát từ thực tế là các bình luận có thể trở nên cũ kỹ (lỗi thời) và có thể khó duy trì. Tuy nhiên, có những bình luận tốt giải thích tại sao mã đang làm một cái gì đó theo một cách nhất định có thể (và thường là) quan trọng để bảo trì.

Nhận xét tốt giúp dễ hiểu mã hơn đang làm gì và quan trọng hơn, tại sao nó lại thực hiện theo cách cụ thể. Nhận xét có nghĩa là được đọc bởi các lập trình viên và nên rõ ràng và chính xác. Một bình luận khó hiểu hoặc không chính xác không tốt hơn nhiều so với việc không có bình luận nào cả.

Việc thêm các nhận xét rõ ràng và chính xác vào mã của bạn có nghĩa là bạn không cần phải dựa vào bộ nhớ để hiểu về những gì mà Cameron và các lý do tại sao của một phần của mã. Điều này là quan trọng nhất khi bạn xem mã đó sau này hoặc người khác phải xem mã của bạn. Vì các bình luận trở thành một phần của nội dung văn bản trong mã của bạn, nên chúng phải tuân theo các nguyên tắc viết tốt ngoài việc được viết rõ ràng.

Để viết một bình luận tốt, bạn nên cố gắng hết sức để ghi lại mục đích của mã (tại sao, không phải như thế nào) và chỉ ra lý do và logic đằng sau mã càng rõ ràng càng tốt. Tốt nhất, bình luận nên được viết cùng lúc với bạn viết mã. Nếu bạn chờ đợi, có lẽ bạn sẽ không quay lại và thêm chúng.

Sams tự dạy mình bằng hình ảnh C # 2010 trong 24 giờ , trang 348-349.


1
Nhận xét có thể trở nên cũ kỹ, nhưng điều đó đúng với mọi thứ không được xác minh bởi trình biên dịch hoặc kiểm tra đơn vị, như ý nghĩa của tên lớp, hàm và tên biến.
LennyProgrammers

@ Lenny222: Có, các bình luận có thể trở nên cũ kỹ ... thường là biểu hiện của những lập trình viên lười biếng. Nếu bình luận mô tả lý do tại sao một mô tả được tạo ra, tại sao mã sử dụng một thuật toán cụ thể để tính toán hoặc mô tả cách thức hoạt động của mã, thì không có lý do gì để bình luận trở nên cũ kỹ ngoài việc ai đó thay đổi cách thực hiện và không cập nhật nhận xét cho phù hợp - tương đương với việc lười biếng.
Scott Dorman

2
Tôi đồng ý. Quan điểm của tôi là, có nguy cơ nó trở nên cũ kỹ, vâng. Nhưng khi tôi có một hàm doBar () và sau 3 năm thì nó không "làm thanh", nhưng nó "không thanh và foo ngoại trừ vào thứ tư" thì ý nghĩa của các hàm cũng có thể bị cũ. Và tên biến. Nhưng tôi hy vọng không ai lấy điều này vì một lý do để không đưa ra các hàm và biến tên có ý nghĩa.
LennyProgrammer

6

Nếu mã đã được viết theo một cách cụ thể để tránh sự cố xảy ra trong thư viện (cả thư viện của bên thứ ba hoặc thư viện đi kèm với trình biên dịch), thì sẽ có ý nghĩa để nhận xét nó.
Nó cũng có ý nghĩa để nhận xét mã cần được thay đổi trong các phiên bản trong tương lai hoặc khi sử dụng phiên bản mới của thư viện hoặc khi chuyển từ PHP4 sang PHP5, chẳng hạn.


6

Ngay cả cuốn sách được viết tốt nhất vẫn có khả năng có phần giới thiệu và tiêu đề chương. Nhận xét trong mã tài liệu tốt vẫn hữu ích để mô tả các khái niệm cấp cao và giải thích cách tổ chức mã.


Nhận xét của loại này cung cấp tín hiệu hình ảnh đẹp để bạn không phải đọc từng dòng để tìm phần bắt đầu của phần bạn đang tìm kiếm. Như ông tôi thường nói, "mọi thứ trong chừng mực."
Blrfl

4

Đề cập đến danh dự là chống mẫu:

Tôi ấn tượng rằng đôi khi các phần mở đầu giấy phép FLOSS thường được sử dụng thay cho tài liệu tệp. GPL / BSDL tạo ra một văn bản phụ đẹp và sau đó bạn hiếm khi thấy bất kỳ khối nhận xét nào khác.


4

Tôi không đồng ý với ý kiến ​​rằng viết bình luận để giải thích mã là xấu. Điều này hoàn toàn bỏ qua thực tế là mã có lỗi. Có thể rõ ràng những gì mã làm mà không có ý kiến. Nó ít có khả năng rõ ràng những gì mã phải làm. Không có ý kiến, làm thế nào để bạn biết nếu kết quả sai, hoặc chúng được sử dụng không chính xác?

Các ý kiến ​​nên giải thích mục đích của mã, để nếu có lỗi, ai đó đọc các bình luận + mã có cơ hội tìm thấy nó.

Tôi thường thấy mình viết bình luận nội tuyến trước khi tôi viết mã. Bằng cách này, rõ ràng tôi đang cố gắng viết mã để làm gì và giảm bị lạc trong thuật toán mà không thực sự biết bạn đang cố gắng làm gì.


1
Kiểm tra đơn vị giúp rất nhiều để xác định nếu kết quả là sai. Nếu bạn đọc một số mã và nghĩ rằng nó làm X khi trong thực tế nó có Y, thì có thể mã không được viết theo cách đủ dễ đọc. Tôi không chắc ý của bạn về kết quả được sử dụng không chính xác. Một bình luận sẽ không bảo vệ bạn trước ai đó tiêu thụ mã của bạn theo những cách lạ.
Adam Lear

"Nếu bạn đọc một số mã và nghĩ rằng nó thực hiện X khi thực tế nó là Y" Đó không phải là những gì tôi đã nói. Tôi đang nói về hiểu biết những gì đang thực hiện làm, nhưng không phải những gì nó phải làm. Giả sử bạn nghi ngờ có lỗi. Làm thế nào để bạn biết lỗi thay thế không nằm trong mã tiêu dùng thay thế hoặc mã này? Nhận xét giải thích mục đích của mã, giúp rất nhiều trong việc theo dõi các lỗi.
Daniel Tuppeny

Mặt khác, các bình luận chỉ có thể cho bạn biết mã được cho là làm gì vào thời điểm các bình luận được viết. Bản thân mã có thể cho bạn biết những gì nó phải làm bây giờ. Bình luận không được biên dịch. Bạn không thể kiểm tra ý kiến. Họ có thể hoặc không thể chính xác.
Anthony Pegram

3

Nhận xét được đưa vào vì ai đó nghĩ rằng có thể có 700 dòng trong một phương thức là một mùi.

Nhận xét là có bởi vì bạn biết nếu bạn không đưa ra nhận xét, ai đó sẽ mắc lỗi tương tự một lần nữa là một mùi.

Nhận xét đưa vào bởi vì một số công cụ phân tích mã yêu cầu nó cũng là một mùi.

Những người sẽ không bao giờ đưa ra một nhận xét, hoặc viết thậm chí một chút giúp đỡ cho các nhà phát triển khác cũng là một mùi. Tôi ngạc nhiên khi có nhiều người sẽ không viết ra những thứ đó, nhưng sau đó sẽ quay lại và thừa nhận họ không thể nhớ những gì họ đã làm 3 tháng trước. Tôi không thích viết tài liệu, nhưng tôi muốn nói với mọi người điều tương tự lặp đi lặp lại thậm chí ít hơn.


3

Tôi sẽ trả lời với một câu hỏi của riêng tôi. Bạn có thể tìm thấy lỗi trong mã chưa hoàn thành dưới đây?

tl; dr: Người tiếp theo duy trì mã của bạn có thể không giống như bạn.

 [org 0x7c00]

 main:
  mov ah, 0x0e
  mov bx, string
  call strreverse
  call print

 stop:
  jmp $

 strreverse:
  pusha
  mov dx, bx
  mov cx, 0

 strreverse_push:
  mov al, [bx]
  cmp al, 0
  je strreverse_pop
  push ax
  add bx, 1
  add cx, 1
  jmp strreverse_push

 strreverse_pop:
  mov bx, dx

 strreverse_pop_loop:
  cmp cx, 0
  je strreverse_end
  pop ax
  mov [bx], al
  sub cx, 1
  add bx, 1
  jmp strreverse_pop_loop

 strreverse_end:
  popa
  ret

 print:
  pusha

 print_loop:
  mov al, [bx]
  cmp al, 1
  je print_end
  int 0x10
  add bx, 1
  jmp print_loop

 print_end:
  popa
  ret
 string:
  db 'Boot up', 0

 times 510 -( $ - $$ ) db 0
 dw 0xaa55

Nhưng cách trong thời đại ngày nay là bạn không sử dụng langage cấp cao?
Ian

2
@Ian: Chương trình này là bộ tải khởi động IBM-PC. Bạn không thể viết nó vào bất cứ thứ gì ngoài lắp ráp, bởi vì bạn cần kiểm soát hoàn toàn chính xác vị trí của chương trình trong RAM, nơi xuất hiện đoạn ngắn cuối cùng và một số phần cứng bị gián đoạn. Nghiêm túc, lấy cho mình một bản sao của NASM. Lắp ráp nó, ghi nó vào khu vực khởi động của đĩa mềm hoặc thanh USB và khởi động nó. Mặc dù có thể bạn sẽ thấy nó không hoạt động như mong đợi vì lỗi. Bây giờ hãy tìm lỗi ... Bất kể, tôi chắc chắn rằng trong 20 năm nữa, mọi người sẽ hỏi điều tương tự về Java chưa hoàn thành.
Kiến

Chắc chắn mã có thể được viết bằng C hoặc C ++ và nhị phân được lắp ráp từ mã đối tượng C và một số công cụ bên ngoài.
kevin cline

Không may măn. Hãy xem trang này trên CodeProject: codeproject.com/KB/tips/boot-loader.aspx - "ngôn ngữ cấp cao không có hướng dẫn cần thiết". Không chỉ vậy, nhưng bạn chỉ có 512 byte để chơi trong bộ tải khởi động. Đôi khi bạn chỉ cần lấy trực tiếp phần cứng.
Ant

1
Khi lắp ráp mã hóa, tôi sẽ làm những gì người khác làm - nhận xét từng dòng với những gì nó đang làm. Dòng trong câu hỏi sẽ có nhận xét "kiểm tra nếu chữ cái là 0", vì mã sử dụng các chuỗi kết thúc 0 kiểu C. Với nhận xét đó, thật dễ dàng để thấy rằng mã đang thực hiện một cmp với 1, có nghĩa là nó bị kẹt trong một vòng lặp vô hạn hoặc in rác cho đến khi nó chạm vào RAM 1 ngẫu nhiên. Tôi cũng có thể đã thêm một nhận xét về thực tế là các chuỗi bị chấm dứt 0, không rõ ràng từ mã. Có một thứ như thử nghiệm đơn vị tự động cho mã hóa lắp ráp?
Kiến

2

Bạn phải giữ cân bằng giữa mã và bình luận ... Thông thường tôi cố gắng thêm một số bình luận tiếp tục một khối mã. Không phải vì tôi sẽ không thể hiểu được mã (cũng vậy), mà bởi vì tôi có thể đọc mã của chính mình nhanh hơn và xác định các phần cụ thể nơi xảy ra nội dung quan trọng.

Dù sao, tiêu chí cá nhân của riêng tôi là "khi nghi ngờ, bình luận". Tôi thích có một dòng dự phòng hơn là một dòng hoàn toàn khó hiểu mà tôi sẽ không thể hiểu được. Tôi luôn có thể xóa nhận xét về đánh giá mã, sau một thời gian (và tôi thường làm)

Ngoài ra, các bình luận khá hữu ích khi thêm "hãy cẩn thận" như "Hãy cẩn thận! Nếu định dạng của đầu vào không phải là ASCII, mã này sẽ phải thay đổi!"


Bạn có thể giải thích những gì bạn có nghĩa là "ý kiến ​​tiếp tục một khối mã"?
Đánh dấu C

2

Đọc điều này tôi được nhắc nhở về một cái gì đó mà lần đầu tiên tôi đọc (từ một danh sách dài hơn, được bảo quản bằng cách chụp bản sao) vài thập kỷ trước:

Các lập trình viên thực sự không viết bình luận - nếu khó viết thì khó đọc

Một mùi methinks khá cũ.


2

Tôi nghĩ rằng nhận xét mã được một khởi đầu rất nghèo cho cuộc sống. Tôi không biết về những ngày này, nhưng khi tôi lần đầu tiên được dạy lập trình ở trường, tôi đã nhận được các bài tập về bản chất của "Viết chương trình in các số từ một đến mười trên các dòng riêng biệt. Hãy chắc chắn rằng bạn nhận xét mã của mình." Bạn sẽ bị đánh dấu xuống nếu bạn không thêm nhận xét vì nhận xét mã của bạn là một điều TỐT.

Nhưng có gì để nói về một quá trình tầm thường như vậy? Vì vậy, cuối cùng bạn viết cổ điển

i++; // add one to the "i" counter.

chỉ để có được một điểm tốt và, nếu bạn có bất kỳ nous nào, ngay lập tức hình thành một ý kiến ​​rất thấp về nhận xét mã.

Mã nhận xét không phải là một điều tốt. Đó là một điều cần thiết, và Thomas Owens trong câu trả lời hàng đầu cung cấp một lời giải thích tuyệt vời về các tình huống cần thiết. Tuy nhiên, những tình huống này hiếm khi tăng lên trong các bài tập loại bài tập về nhà.

Theo nhiều cách, việc thêm một bình luận nên được coi là lựa chọn cuối cùng, khi những gì cần nói không thể được nói rõ ràng trong các phần hoạt động của ngôn ngữ lập trình. Mặc dù việc đặt tên đối tượng có thể trở nên cũ kỹ, các cơ chế thiếu phản hồi của con người và máy tính giúp bạn dễ dàng quên việc duy trì các bình luận và do đó các bình luận trở nên cũ kỹ nhanh hơn nhiều so với mã hoạt động. Vì lý do đó, khi có thể lựa chọn, việc thay đổi mã để làm cho nó rõ ràng hơn nên luôn luôn được ưu tiên để chú thích mã không rõ ràng bằng các bình luận.


+1 để chỉ ra rằng thói quen bình luận xấu bắt đầu với các lớp lập trình sớm. -1 để kết luận rằng các bình luận chỉ là lựa chọn cuối cùng.
HỎI

1

Tất nhiên ý kiến ​​là một mùi mã ...

mọi lập trình viên đều biết tất cả chúng ta cuối cùng trở nên điên loạn do khối lượng công việc, gỡ lỗi hoặc chỉ là sự điên rồ đơn giản mà chúng ta gặp phải.

"Làm cái này!" quản lý dự án của bạn nói.

Bạn trả lời, "Không thể làm được."

Họ nói: "Sau đó, chúng tôi sẽ tìm người khác để làm điều đó."

Bạn nói, "OK, có lẽ nó có thể được thực hiện."

Và sau đó dành số X ngày tiếp theo .. tuần .. tháng .. cố gắng tìm ra nó. Trong suốt quá trình, bạn sẽ thử và thất bại, và thử và thất bại. Tất cả chúng ta làm điều này. Câu trả lời đúng là có hai loại lập trình viên, những người bình luận và những người không bình luận.

1) Những người đang làm cho công việc của họ trở nên dễ dàng hơn bằng cách ghi lại tài liệu tham khảo trong tương lai, nhận xét các thói quen thất bại không hoạt động (mùi không xóa chúng sau khi tìm thấy công việc đó.) định dạng để hy vọng làm cho nó dễ đọc hoặc dễ hiểu hơn một chút. Nghiêm túc mà nói, tôi không thể đổ lỗi cho họ. Nhưng cuối cùng, họ chụp và sau đó bạn có điều này: // dammit this code sucks! swear! curse! i hate it! i am going to write something here to vent my anger!!!!

2) Những người không giả vờ là siêu anh hùng hoặc đang sống trong hang động . Họ chỉ đơn giản là coi thường người khác, bản thân họ, và có thể quan tâm ít hơn về mã, hoặc ý nghĩa của nó có thể có cho sau này.

Bây giờ đừng hiểu sai về tôi .. các biến và chức năng tự ghi lại tài liệu có thể tránh điều này hoàn toàn .. và tin tôi đi, bạn không bao giờ có thể thực hiện đủ việc dọn mã. Nhưng sự thật đơn giản là miễn là bạn giữ bản sao lưu, bạn có thể luôn luôn xóa bình luận.


1
Đáp lại 1. Mùi thực sự trong thói quen nhận xét không xóa chúng ngay lập tức khi bạn quyết định chúng có thể là ngõ cụt và muốn thử một cái gì đó khác --- điều này là do chúng nên có sẵn trong kiểm soát phiên bản nếu bạn quyết định xem lại chúng .
Sharpie

1

Tôi cho rằng việc không sử dụng một số bình luận trong mã của bạn là mùi mã. Mặc dù tôi đồng ý rằng mã phải tự ghi lại càng nhiều càng tốt, bạn nhấn vào một điểm nhất định nơi bạn sẽ thấy mã không có ý nghĩa bất kể mã được viết tốt như thế nào. Tôi đã thấy một số mã trong các ứng dụng kinh doanh trong đó các ý kiến ​​bắt buộc khá nhiều vì:

  1. Bạn cần phải làm một cái gì đó trong từng trường hợp và không có logic tốt cho nó.
  2. Mã có thể sẽ thay đổi trong một hoặc hai năm khi luật được thay đổi và bạn muốn tìm lại nó một cách nhanh chóng.
  3. Ai đó đã chỉnh sửa mã trong quá khứ vì họ không hiểu mã đang làm gì.

Ngoài ra, hướng dẫn kiểu công ty có thể yêu cầu bạn làm điều gì đó theo một cách nhất định - nếu họ nói rằng bạn có thể có ý kiến ​​nêu rõ các khối mã trong một chức năng đang làm gì, sau đó bao gồm các nhận xét.


1

Có một sự khác biệt cơ bản lớn giữa các bình luận và mã: các bình luận là một cách để mọi người truyền đạt ý tưởng cho người khác, trong khi mã chủ yếu dành cho máy tính. Có nhiều khía cạnh trong "mã" cũng chỉ dành cho con người, như đặt tên và thụt lề. Nhưng ý kiến ​​được viết nghiêm ngặt cho con người, bởi con người.

Do đó, viết bình luận là một chút khó khăn như bất kỳ giao tiếp bằng văn bản của con người! Người viết nên có một quan niệm rõ ràng về đối tượng là ai, và họ sẽ cần loại văn bản nào. Làm thế nào bạn có thể biết ai sẽ đọc ý kiến ​​của bạn trong mười, hai mươi năm nữa? Điều gì xảy ra nếu người đó đến từ một nền văn hóa hoàn toàn khác? V.v. Tôi hy vọng mọi người hiểu điều này.

Ngay cả trong nền văn hóa đồng nhất nhỏ bé mà tôi sống, thật khó để truyền đạt ý tưởng cho người khác. Giao tiếp của con người thường thất bại, ngoại trừ do tai nạn.


0

Tôi phải đồng ý với đồng nghiệp của bạn. Tôi luôn nói rằng nếu tôi nhận xét mã của mình, điều đó có nghĩa là tôi lo lắng rằng tôi sẽ không thể tìm ra mã của riêng mình trong tương lai. Đây là một dấu hiệu xấu.

Lý do duy nhất khác mà tôi rắc ý kiến ​​vào mã là để gọi ra một cái gì đó dường như không có ý nghĩa.

Những bình luận đó thường có dạng như:

//xxx what the heck is this doing??

hoặc là

// removed in version 2.0, but back for 2.1, now I'm taking out again

1
Hoặc, thay vào đó, nhận xét có thể phản ánh thực tế rằng mã đang xử lý một thuật toán phức tạp nơi mã vốn không rõ ràng hoặc do mã đang làm điều gì đó kỳ lạ do các yếu tố ngoài tầm kiểm soát của bạn (ví dụ như tương tác với dịch vụ bên ngoài).
Murph

Rất đúng. Có nhiều lý do tại sao mã tốt có thể không rõ ràng. Hầu hết thời gian mặc dù mã bối rối là bối rối bởi vì nó được viết theo cách khó hiểu.
Ken

Có vẻ như bạn chưa viết mã cho các bộ xử lý nhúng, nơi bạn chỉ có 32k để chơi và những điều làm bạn mơ hồ về giá thầu. Bình luận là cứu người.
quick_now

0

Nhận xét mã, khi áp dụng, các đơn vị của đối số và trả về hàm, trường cấu trúc, thậm chí các biến cục bộ có thể rất tiện dụng. Hãy nhớ tàu quỹ đạo sao Hỏa!


Tốt hơn nhiều để xây dựng các đơn vị thành các tên biến, vì vậy lập trình viên nghèo không cần phải nhớ chúng. Thay vì 'gấp đôi chiều dài // tính bằng mét', hãy nói 'gấp đôi chiều dài_m'. Tốt nhất của tất cả là sử dụng một ngôn ngữ mạnh mẽ hơn, vì vậy bạn có thể chỉ cần nói Độ dài l; Lực f; Mô-men xoắn t = l * f; in (t.in (Torque.newtonMeter));
kevin cline

0

Đây là quy tắc của tôi:

  • Viết mã và lưu trữ một bản tóm tắt ngắn của mã trong một tài liệu riêng biệt.
  • Để lại mã một mình trong vài ngày để làm việc khác.
  • Quay trở lại mã. Nếu bạn không thể hiểu ngay những gì cần làm, hãy thêm tóm tắt vào tệp nguồn.


0

Không, bình luận không phải là mùi mã, chúng chỉ là một công cụ có thể bị lạm dụng.

Ví dụ về những bình luận tốt :

// Tôi nghĩ rằng đây là bằng cm. Cần điều tra thêm!

// Đây là một cách làm X thông minh

// Danh sách được đảm bảo không trống ở đây


Thứ ba là một bình luận xấu IMO. Tại sao không Assert(list.IsEmpty)?
CodeInChaos

@CodeInChaos IMO Assert(!list.isEmpty())không chính xác là một hợp đồng như trong bình luận thứ ba, mà chỉ đơn giản là hành vi (tức là "ném IllegalArgumentException nếu đối số trống") phải được kiểm tra đơn vị như bất kỳ logic chương trình nào khác. Lưu ý sự khác biệt tinh tế với nhận xét, trong đó nêu rõ khi phương thức có thể được sử dụng, nhưng chỉ định không có hành vi nếu điều kiện tiên quyết không được đáp ứng. Thậm chí tốt hơn bình luận sẽ là để thực thi các hợp đồng thời gian biên dịch. Nhưng điều này vượt quá phạm vi câu trả lời của tôi;)
Andres F.

Bạn không thể thực hiện Asserts, vì chúng mô tả những điều không bao giờ xảy ra, ngay cả khi API công khai nhận được các đối số không hợp lệ.
CodeInChaos

@CodeInChaos Tôi rút lại ý kiến ​​của mình. Dưới đây là những gì Sunacle nói về sự khẳng định . Có vẻ như bạn đã đúng. Vâng, bạn học được điều gì đó mỗi ngày!
Andres F.
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.