Tôi có nên sử dụng dấu ngoặc đơn trong các câu lệnh logic ngay cả khi không cần thiết?


100

Giả sử tôi có một điều kiện boolean a AND b OR c AND dvà tôi đang sử dụng một ngôn ngữ ANDcó tiền lệ hoạt động cao hơn so với OR. Tôi có thể viết dòng mã này:

If (a AND b) OR (c AND d) Then ...

Nhưng thực sự, điều đó tương đương với:

If a AND b OR c AND d Then ...

Có bất kỳ đối số trong hoặc chống lại bao gồm cả dấu ngoặc đơn không? Có kinh nghiệm thực tế cho thấy rằng nó có giá trị bao gồm chúng cho khả năng đọc? Hay đó là một dấu hiệu cho thấy một nhà phát triển cần phải thực sự ngồi xuống và tự tin vào những điều cơ bản trong ngôn ngữ của họ?


90
Tôi có thể lười biếng, nhưng tôi thích có dấu ngoặc đơn trong hầu hết các tình huống như vậy để dễ đọc.
thorsten müller

6
Tôi cũng vậy. Tôi chỉ hy vọng tôi làm điều đó nhiều hơn để dễ đọc và ít hơn bởi vì tôi quá lười biếng để trở nên tự tin / có năng lực trong những điều cơ bản của ngôn ngữ của mình.
Jeff Bridgman

16
Sử dụng tốt các dấu ngoặc đơn cũng giống như sử dụng tốt ngữ pháp. 2 * 3 + 2có thể giống như (2 * 3) + 2nhưng thứ hai dễ đọc hơn.
Phản ứng

16
@Mathew Có lẽ nếu bạn yếu môn toán. Đối với các trường hợp phức tạp hơn, chắc chắn, sử dụng dấu ngoặc đơn. Nhưng đối với những người rõ ràng rõ ràng (BODMAS mộc), họ giảm khả năng đọc nhiều hơn là giúp đỡ nó do sự lộn xộn.
Konrad Rudolph

3
Điều đó nói rằng, cùng một ưu tiên của AND / OR có trong Basic, Python, SQL ... ấn tượng của tôi là đây là quy tắc trong phần lớn các ngôn ngữ hiện đại (mặc dù không phải tất cả).
Tim Goodman

Câu trả lời:


117

Các nhà phát triển giỏi cố gắng viết mã rõ ràngchính xác . Dấu ngoặc trong điều kiện, ngay cả khi chúng không được yêu cầu nghiêm ngặt, giúp cả hai.

Để rõ ràng , hãy nghĩ về dấu ngoặc đơn như nhận xét trong mã: chúng không thực sự cần thiết và về lý thuyết, một nhà phát triển có thẩm quyền sẽ có thể tìm ra mã mà không có chúng. Tuy nhiên, những tín hiệu này cực kỳ hữu ích, bởi vì:

  • Họ giảm công việc cần thiết để hiểu mã.
  • Họ cung cấp xác nhận về ý định của nhà phát triển.

Hơn nữa, các dấu ngoặc đơn bổ sung, giống như các vết lõm, khoảng trắng và các tiêu chuẩn kiểu khác, giúp tổ chức trực quan mã theo cách hợp lý.

Đối với tính chính xác , điều kiện không có dấu ngoặc đơn là một công thức cho những sai lầm ngớ ngẩn. Khi chúng xảy ra, chúng có thể là những lỗi khó tìm - bởi vì thường thì một điều kiện không chính xác sẽ hành xử chính xác hầu hết thời gian và chỉ thỉnh thoảng thất bại.

Và ngay cả khi bạn hiểu đúng, người tiếp theo làm việc với mã của bạn có thể không, thêm lỗi vào biểu thức hoặc hiểu sai logic của bạn và do đó thêm lỗi ở nơi khác (như LarsH chỉ ra đúng).

Tôi luôn sử dụng dấu ngoặc đơn cho các biểu thức kết hợp andor(và cả cho các phép toán số học với các vấn đề ưu tiên tương tự).


3
Mặc dù, tôi đã nghe nói rằng các bình luận là lời xin lỗi (đối với mã xấu / khó đọc) ... rất có thể bạn có thể viết nó tốt hơn. Tôi đoán bạn có thể nói một điều tương tự về dấu ngoặc đơn.
Jeff Bridgman

6
Một khía cạnh khác của tính chính xác là bảo vệ nó thông qua các thay đổi: Mặc dù nhà phát triển ban đầu có thể được ưu tiên ngay lập tức mà không cần dấu ngoặc đơn khi lần đầu tiên viết mã với mục đích và bối cảnh mới mẻ, anh ta (hoặc người khác) đi sau và không nhớ tất cả các chi tiết cũng có thể làm rối tung nó khi họ thêm nhiều thuật ngữ vào biểu thức. (Điều đó hầu như đã được ngụ ý nhưng tôi cảm thấy như nó đáng được nhấn mạnh.)
LarsH

1
@LarsH, cảm ơn, tôi đã thêm điều này vào câu trả lời một cách rõ ràng.

8
+1 "Họ cung cấp xác nhận về ý định của nhà phát triển." - bất kỳ lập trình viên nào (OK, có thể không phải tất cả, nhưng tất cả những người sống ở đây ....) có thể tìm ra trình biên dịch sẽ làm gì với logic phức tạp nhất. Hoàn toàn không ai có thể tìm ra những gì nhà phát triển ban đầu dự định (Bao gồm cả bản thân anh ta) trong vài tuần theo dõi cho bất cứ điều gì đơn giản nhất .....
mattnz

2
Tôi nghĩ rằng @JeffBridgman đã tham khảo một quan điểm khá nổi tiếng về "các bình luận đôi khi có thể là một mùi mã". Ví dụ: xem tóm tắt của Jeff Atwood bao gồm câu hỏi "Bạn có thể cấu trúc lại mã để nhận xét không bắt buộc không?". Tôi tranh luận rằng nếu bình luận của bạn giải thích lý do tại sao mã của bạn quá không trực quan, thì đó chắc chắn có thể là một gợi ý rằng có gì đó không đúng. Vào những thời điểm như thế này, bạn nên đơn giản hóa mã. Tuy nhiên, tôi hoàn toàn đồng ý với câu trả lời thực tế của bạn và đảm nhận dấu ngoặc đơn.
Daniel B

94

Nó ít quan trọng cho dù bạn có tự tin trong việc nắm bắt ngôn ngữ hay không. Điều quan trọng hơn là việc nắm bắt ngôn ngữ của n00b theo bạn.

Viết mã của bạn theo cách rõ ràng nhất rõ ràng nhất có thể. Phụ huynh thường xuyên (nhưng không phải luôn luôn) giúp đỡ. Chỉ đưa ra một tuyên bố trên một dòng thường giúp. Sự nhất quán trong phong cách mã hóa thường giúp.

Có một điều giống như quá nhiều dấu ngoặc đơn, nhưng đó là một trong những tình huống mà bạn sẽ không cần lời khuyên - bạn sẽ biết điều đó khi bạn nhìn thấy nó. Tại thời điểm đó, cấu trúc lại mã của bạn để giảm độ phức tạp của câu lệnh thay vì loại bỏ dấu ngoặc đơn.


72
Đừng quên rằng ngay cả khi bạn là nhà phát triển solo khi bị ốm, mệt mỏi hoặc xử lý mã bạn đã viết năm ngoái; mức độ hiểu của bạn giảm xuống mức n00b.
Dan Neely

30
There is such a thing as too many parenthesis- bạn rõ ràng không phải là một kẻ nói dối;)
paul

18
Đó là lời khuyên tồi: Đừng viết cho noobs. Điều này sẽ làm giảm chất lượng mã của bạn (đáng kể) vì bạn không thể sử dụng các thành ngữ được thiết lập tốt vượt xa hai chương đầu tiên của cuốn sách dành cho người mới bắt đầu.
Konrad Rudolph

10
@KonradRudolph: có thể là như vậy, nhưng đừng viết cho những người duy nhất biết Nghệ thuật lập trình máy tính từ trang bìa đến trang bìa, hoặc sẵn sàng để gỡ lỗi mã của họ sau đó, và không biết tại sao bạn lại làm như vậy . Mã được đọc nhiều hơn nó được viết.
haylem

15
@dodgethesteamler: Tôi đã thấy quá nhiều nhà phát triển có năng lực / được kính trọng giới thiệu các lỗi ưu tiên (mọi người đều có một ngày tồi tệ và sau đó) vẫn không được chú ý từ lâu. Đối với các nhà phát triển giỏi, những người biết các quy tắc ưu tiên, nguy cơ mắc lỗi / lỗi chính tả không được phát hiện là quá cao. Đối với những người khác rủi ro cao hơn. Các nhà phát triển tốt nhất là các nhà phát triển thường nhớ các quy tắc ưu tiên của ngôn ngữ, nhưng quên chúng do thói quen sử dụng dấu ngoặc đơn cho bất cứ điều gì không rõ ràng.
Brendan

31

Đúng

Bạn phải luôn luôn sử dụng dấu ngoặc đơn ... bạn không kiểm soát thứ tự ưu tiên ... nhà phát triển trình biên dịch nào. Đây là một câu chuyện xảy ra với tôi về việc không sử dụng dấu ngoặc đơn. Điều này ảnh hưởng đến hàng trăm người trong khoảng thời gian hai tuần.

Lý do thực tế

Tôi đã sử dụng một ứng dụng khung chính. Một ngày nọ, khi trời trong xanh, nó ngừng hoạt động. Đó là ... nó chỉ dừng lại.

Công việc của tôi là làm cho nó hoạt động nhanh nhất có thể. Mã nguồn đã không được sửa đổi trong hai năm, nhưng đột nhiên nó chỉ dừng lại. Tôi đã cố gắng biên dịch mã và nó đã bị hỏng trên dòng XX. Tôi nhìn vào dòng XX và tôi không thể biết điều gì sẽ khiến dòng XX bị phá vỡ. Tôi yêu cầu thông số kỹ thuật chi tiết cho ứng dụng này và không có thông tin nào. Dòng XX không phải là thủ phạm.

Tôi đã in mã ra và bắt đầu xem xét nó từ trên xuống. Tôi bắt đầu tạo ra một sơ đồ về những gì đang diễn ra. Mã này rất phức tạp, tôi thậm chí không thể hiểu được nó. Tôi đã từ bỏ cố gắng để lưu đồ nó. Tôi sợ thực hiện các thay đổi mà không biết sự thay đổi đó sẽ ảnh hưởng đến phần còn lại của quá trình như thế nào, đặc biệt là vì tôi không có thông tin chi tiết về những gì ứng dụng đã làm hoặc nơi nó nằm trong chuỗi phụ thuộc.

Vì vậy, tôi quyết định bắt đầu ở đầu mã nguồn và thêm whitespce và phanh dòng để làm cho mã dễ đọc hơn. Tôi nhận thấy, trong một số trường hợp, có những điều kiện kết hợp ANDORkhông thể phân biệt rõ ràng giữa dữ liệu nào được chỉnh sửa ANDvà dữ liệu nào được chỉnh sửa OR. Vì vậy, tôi bắt đầu đặt dấu ngoặc đơn xung quanh ANDvà các ORđiều kiện để làm cho chúng dễ đọc hơn.

Khi tôi từ từ dọn dẹp nó, tôi sẽ định kỳ lưu công việc của mình. Tại một thời điểm tôi đã cố gắng biên dịch mã và một điều kỳ lạ xảy ra. Lỗi đã nhảy qua dòng mã ban đầu và bây giờ đã xuống sâu hơn. Vì vậy, tôi tiếp tục, bỏ qua các điều kiện ANDORđiều kiện với parens. Khi tôi đã hoàn thành việc làm sạch nó, nó hoạt động. Đi hình.

Sau đó tôi quyết định ghé thăm cửa hàng hoạt động và hỏi họ xem gần đây họ có cài đặt bất kỳ thành phần mới nào trên khung chính không. Họ nói có, gần đây chúng tôi đã nâng cấp trình biên dịch. Hừm.

Nó chỉ ra rằng trình biên dịch cũ đánh giá biểu thức từ trái sang phải bất kể. Phiên bản mới của trình biên dịch cũng đánh giá các biểu thức từ trái sang phải nhưng mã mơ hồ, nghĩa là sự kết hợp không rõ ràng ANDORkhông thể giải quyết được.

Bài học tôi học được từ điều này ... LUÔN LUÔN, LUÔN LUÔN, LUÔN LUÔN sử dụng parens cho các ANDđiều kiện và điều kiện riêng biệt ORkhi chúng được sử dụng để kết hợp với nhau.

Ví dụ đơn giản hóa

IF Product = 191 OR Product = 193 AND Model = "ABC" OR Product = 201 OR Product = 202 AND Model = "DEF" ...(mã bị vấy bẩn với một vài trong số này)

Đây là phiên bản đơn giản hóa của những gì tôi gặp phải. Cũng có những điều kiện khác với các câu lệnh logic boolean ghép.

Tôi nhớ đã nhai nó để:
IF ((Product = 191 OR Product = 193) AND Model = "ABC") OR ((Product = 201 OR Product = 202) AND Model = "DEF") ...



Tôi không thể viết lại vì không có thông số kỹ thuật. Các tác giả ban đầu đã qua lâu. Tôi nhớ áp lực dữ dội. Toàn bộ tàu chở hàng bị mắc kẹt tại cảng và không thể tải được vì chương trình nhỏ này không hoạt động. Không có cảnh báo. Không có thay đổi đối với mã nguồn. Tôi chỉ nhận ra rằng tôi yêu cầu các hoạt động mạng nếu họ sửa đổi bất cứ điều gì sau khi tôi nhận thấy rằng việc thêm parens đã làm thay đổi các lỗi.


22
Đó dường như là một minh họa tốt hơn về lý do tại sao cần có một trình biên dịch tốt.
ruakh

6
@CapeCodGunny: Tôi chắc chắn là bạn không. Nhưng vấn đề ở đây là bạn có một nhà cung cấp trình biên dịch tồi đã tạo ra một sự thay đổi đột phá. Tôi không thấy cách bạn học một bài học để "LUÔN, LUÔN, LUÔN" làm việc xung quanh vấn đề đó, ngay cả khi sử dụng trình biên dịch tốt hơn.
ruakh

5
@ruakh - Không, nhà cung cấp chỉ cần thay đổi trình phân tích mã của họ. Tôi là trường học cũ, tôi không dựa vào khả năng ghi nhớ mọi hệ thống mà tôi đã mã hóa hoặc tham gia. Không có tài liệu, tất cả những gì bạn có là mã nguồn. Khi mã nguồn khó đọc và làm theo nó sẽ tạo ra một tình huống cực kỳ căng thẳng. Các lập trình viên không sử dụng khoảng trắng có lẽ chưa bao giờ phải đối phó với một tình huống như tình huống mà tôi phải đối mặt. Tôi cũng học được rằng viết mã như: Xem Dick; Xem Jane; Xem Dick VÀ Jane; Những câu đơn giản dễ đọc ... bình luận ... và làm theo.
Michael Riley - AKA Gunny

2
Câu chuyện tuyệt vời, nhưng tôi đồng ý rằng đó không phải là lý do để sử dụng dấu ngoặc đơn. và / hoặc quyền ưu tiên là gần như phổ biến và về điều ít có khả năng thay đổi nhất mà người ta có thể nghĩ đến. Nếu bạn không thể dựa vào hành vi nhất quán cho một hoạt động cơ bản, tiêu chuẩn như vậy, trình biên dịch của bạn là rác và bạn sẽ không có vấn đề gì cho dù bạn làm gì. Câu chuyện của bạn là 100% một vấn đề về trình biên dịch và 0% là một vấn đề về mã. Đặc biệt là hành vi mặc định là đánh giá từ trái sang phải đơn giản - thứ tự sẽ luôn rõ ràng, vậy tại sao mọi người sẽ sử dụng dấu ngoặc đơn?

7
Tôi nghĩ rằng có những bài học kinh nghiệm ở đây ở cả hai phía ... Bạn nên sử dụng dấu ngoặc đơn tốt hơn nhiều khi phương án thay thế dựa vào hành vi không có giấy tờ của trình biên dịch liên quan đến mã mơ hồ . Và nếu lập trình viên không biết biểu thức nào là mơ hồ, hãy sử dụng parens tốt hơn. Mặt khác, việc thay đổi hành vi của trình biên dịch là rất nguy hiểm, nhưng ít nhất nó đã gây ra lỗi trong trường hợp hành vi thay đổi. Sẽ tệ hơn nếu trình biên dịch không đưa ra lỗi, nhưng đã bắt đầu biên dịch khác đi. Các lỗi bảo vệ bạn khỏi các lỗi không được chú ý.
LarsH

18

Có, nếu có hỗn hợp 'và' và 'hoặc'.

Ngoài ra ý tưởng tốt để () những gì là một kiểm tra logic.

Mặc dù tốt nhất là sử dụng các hàm vị ngữ được đặt tên tốt và loại bỏ hầu hết các kiểm tra và điều kiện ở đó, để lại nếu đơn giản và dễ đọc.


6
Đúng, có một cơ hội rất tốt a AND bcó lẽ nên được thay thế bằng một hàm hoặc giá trị boolen được tính toán trước có tên mô tả hơn.
Jeff Bridgman

14

Các dấu ngoặc đơn là dư thừa về mặt ngữ nghĩa, vì vậy trình biên dịch không quan tâm, nhưng đó là một cá trích đỏ - mối quan tâm thực sự là khả năng đọc và hiểu của lập trình viên.

Tôi sẽ đảm nhận vị trí cấp tiến ở đây và nói "không" với các dấu ngoặc đơn trong a AND b OR c AND d. Mọi lập trình viên nên biết rằng sự ưu tiên trong các biểu thức Boolean KHÔNG> VÀ> HOẶC , giống như ghi nhớ Xin vui lòng Xin lỗi Dì thân mến của tôi cho các biểu thức đại số. Dấu câu thừa chỉ thêm lộn xộn thị giác hầu hết thời gian trong mã mà không có lợi ích trong khả năng đọc của lập trình viên.

Ngoài ra, nếu bạn luôn sử dụng dấu ngoặc đơn trong các biểu thức logic và đại số, thì bạn từ bỏ khả năng sử dụng chúng làm điểm đánh dấu cho "điều gì đó khó khăn đang xảy ra ở đây - xem ra!" Đó là, trong trường hợp bạn muốn ghi đè mức ưu tiên mặc định và được đánh giá bổ sung trước khi nhân hoặc OR trước AND, dấu ngoặc đơn là một cờ đỏ đẹp cho lập trình viên tiếp theo. Sử dụng chúng quá nhiều khi không cần thiết và bạn trở thành Cậu bé Sói khóc.

Tôi sẽ tạo một ngoại lệ cho bất cứ điều gì bên ngoài lĩnh vực đại số (Boolean hoặc không), chẳng hạn như các biểu thức con trỏ trong C, trong đó bất cứ điều gì phức tạp hơn các thành ngữ tiêu chuẩn như *p++hoặc p = p->nextcó lẽ nên được ngoặc đơn để giữ cho hội thảo và số học thẳng. Và, tất nhiên không điều nào trong số này áp dụng cho các ngôn ngữ như Lisp, Forth hoặc Smalltalk sử dụng một số dạng ký hiệu Ba Lan cho các biểu thức; nhưng đối với phần lớn các ngôn ngữ chính, ưu tiên logic và số học hoàn toàn được chuẩn hóa.


1
+1, dấu ngoặc đơn cho rõ ràng là tốt, nhưng ANDvs ORlà một trường hợp khá cơ bản mà tôi muốn các nhà phát triển khác trong nhóm của tôi biết. Tôi lo lắng rằng đôi khi "sử dụng dấu ngoặc đơn cho rõ ràng" thực sự là "sử dụng dấu ngoặc đơn để tôi không bao giờ phải bận tâm tìm hiểu quyền ưu tiên".
Tim Goodman

1
Trong tất cả các ngôn ngữ tôi làm việc với thường xuyên đó là .membertrước khi khai thác unary, unary trước khi khai thác nhị phân, */trước +-trước <>==trước &&trước ||trước khi chuyển nhượng. Những quy tắc này rất dễ nhớ vì chúng phù hợp với "ý thức chung" của tôi về cách các toán tử thường được sử dụng (ví dụ: bạn sẽ không ==ưu tiên nhiều hơn +hoặc 1 + 1 == 2ngừng hoạt động) và chúng bao gồm 95% các câu hỏi ưu tiên mà tôi có .
Tim Goodman

4
@Timoodman Vâng, chính xác, cho cả hai ý kiến ​​của bạn. Những người trả lời khác ở đây dường như nghĩ rằng đó là một câu hỏi đen hoặc trắng - luôn luôn sử dụng dấu ngoặc đơn, không có ngoại lệ hoặc bay bất cẩn bởi chỗ ngồi của quần qua một biển các quy tắc tùy ý và không thể nhớ, mã của bạn sôi sục với các lỗi khó phát hiện. (Các ẩn dụ hỗn hợp rất có chủ ý.) Rõ ràng cách đúng là điều độ; sự rõ ràng về mã rất quan trọng, nhưng việc hiểu rõ các công cụ của bạn cũng vậy và bạn sẽ có thể mong đợi một sự hiểu biết tối thiểu nhất định về các nguyên tắc lập trình và CS từ các đồng đội của mình.
dodgethesteamler

8

Theo tôi thấy:

Ưu điểm:

  • Thứ tự của các hoạt động là rõ ràng.
  • Bảo vệ bạn khỏi các nhà phát triển trong tương lai, những người không hiểu thứ tự hoạt động.

Nhược điểm:

  • Có thể dẫn đến lộn xộn, khó đọc mã

KHÔNG Ưu điểm:

  • ?

Không có khuyết điểm:

  • Trình tự hoạt động là ẩn
  • Mã ít được duy trì cho các nhà phát triển mà không hiểu rõ về thứ tự các hoạt động.

Nói tốt, mặc dù tôi nghĩ rằng "Có thể dẫn đến lộn xộn, khó đọc mã" là khá chủ quan.
Thất vọngWithFormsDesigner

2
Làm thế nào để làm cho ngữ nghĩa của mã của bạn rõ ràng gây khó đọc?
Mason Wheeler

1
Tôi đồng ý với những người khác khi đặt câu hỏi về "Có khuyết điểm" của bạn. Tôi nghĩ rằng nó gần như luôn luôn ngược lại.

@Frustrated Là chủ quan như yêu cầu ngược lại. Có nghĩa là, hoàn toàn không. Chỉ khó đo.
Konrad Rudolph

1
@MasonWheeler: Mặc dù tôi đồng ý rằng các parens rõ ràng rất quan trọng trong nhiều trường hợp, tôi có thể thấy làm thế nào một người có thể quá nhiệt tình trong việc làm cho ngữ nghĩa rõ ràng. Tôi thấy 3 * a^2 + 2 * b^2dễ đọc hơn (3 * (a^2)) + (2 * (b^2)), bởi vì định dạng và quyền ưu tiên là quen thuộc và tiêu chuẩn. Tương tự như vậy, bạn có thể (cực đoan) cấm sử dụng các hàm và macro (hoặc trình biên dịch!) Để làm cho ngữ nghĩa của mã của bạn rõ ràng hơn. Rõ ràng tôi không ủng hộ điều đó, nhưng tôi hy vọng sẽ trả lời câu hỏi của bạn về lý do tại sao cần phải có những hạn chế (sự cân bằng) trong việc làm cho mọi thứ rõ ràng.
LarsH

3

Có bất kỳ đối số trong hoặc chống lại bao gồm cả dấu ngoặc đơn không? Có kinh nghiệm thực tế cho thấy rằng nó có giá trị bao gồm chúng cho khả năng đọc? Hay đó là một dấu hiệu cho thấy một nhà phát triển cần phải thực sự ngồi xuống và tự tin vào những điều cơ bản trong ngôn ngữ của họ?

Nếu không ai khác phải xem lại mã của tôi, tôi không nghĩ mình sẽ quan tâm.

Nhưng, từ kinh nghiệm của tôi:

  • Thỉnh thoảng tôi nhìn lại mã của mình (đôi khi nhiều năm sau khi viết nó)
  • Những người khác đôi khi nhìn vào mã của tôi
    • Hoặc thậm chí phải mở rộng / sửa chữa nó!
  • Cả tôi và người khác đều nhớ chính xác những gì tôi đã nghĩ khi viết nó
  • Viết mã "tối thiểu hóa số ký tự" làm tổn thương khả năng đọc

Tôi hầu như luôn luôn làm điều này bởi vì tôi tin tưởng vào khả năng đọc nhanh và không mắc lỗi nhỏ nhiều hơn với parens hơn là không có gì khác.

Trong trường hợp của bạn, tôi gần như chắc chắn sẽ làm một cái gì đó như:

if (a AND b) then ab = true
if (c AND d) then cd = true
If (ab OR cd) Then ...

Vâng, đó là nhiều mã hơn. Vâng, tôi có thể làm toán tử bool ưa thích thay thế. Không, tôi không thích cơ hội khi lướt qua mã 1+ năm trong tương lai Tôi đọc sai các toán tử bool ưa thích. Điều gì xảy ra nếu tôi đang viết mã bằng một ngôn ngữ có quyền ưu tiên AND / OR khác nhau và phải quay lại để sửa lỗi này? Tôi sẽ đi đây, "aha! Tôi nhớ điều nhỏ bé thông minh này mà tôi đã làm! Tôi đã không bao gồm các parens khi tôi viết vào năm ngoái, điều tốt là tôi nhớ bây giờ!" nếu điều đó xảy ra (hoặc tệ hơn, một người nào khác không biết về sự thông minh này hoặc bị ném vào tình huống loại "sửa càng sớm càng tốt")?

Việc tách với () làm cho nó trở nên đơn giản hơn rất nhiều để nhanh chóng đọc lướt và hiểu sau ...


7
Nếu bạn sẽ làm điều đó, tại sao không ab = a AND b?
Eric

1
Có lẽ bởi vì absẽ không thay đổi nếu không a AND b.
Armali

3

Trường hợp chung

Trong C #, phép nhân và phép chia có quyền ưu tiên hơn phép cộng và phép trừ.

Tuy nhiên, StyleCop, một công cụ thực thi kiểu phổ biến trên cơ sở mã với mục tiêu bổ sung để giảm thiểu rủi ro lỗi do mã giới thiệu có thể không đủ rõ ràng, có quy tắc SA1407 . Quy tắc này sẽ tạo ra một cảnh báo với một đoạn mã như thế này:

var a = 1 + 2 * 3;

Rõ ràng là kết quả là 7và không 9, nhưng vẫn, StyleCop đề nghị đặt dấu ngoặc đơn:

var a = 1 + (2 * 3);

Trường hợp cụ thể của bạn

Trong trường hợp cụ thể của bạn, có một ưu tiên AND so với OR trong ngôn ngữ cụ thể bạn sử dụng.

Đây không phải là cách mọi ngôn ngữ ứng xử. Nhiều người khác đối xử VÀ VÀ HOẶC như nhau.

Là một nhà phát triển làm việc chủ yếu với C #, khi tôi nhìn thấy câu hỏi của bạn lần đầu tiên và đọc đoạn mã mà không đọc những gì bạn đã viết trước đó, cám dỗ đầu tiên của tôi là nhận xét rằng hai biểu thức không giống nhau. Hy vọng rằng, tôi đã đọc toàn bộ câu hỏi trước khi bình luận.

Tính đặc biệt này và rủi ro mà một số nhà phát triển có thể tin rằng AND và OR có cùng mức độ ưu tiên khiến cho việc thêm dấu ngoặc đơn càng quan trọng hơn.

Đừng viết mã với mục tiêu để cho thấy rằng bạn thông minh. Viết mã với mục tiêu dễ đọc, bao gồm cả những người có thể không quen thuộc với mọi khía cạnh của ngôn ngữ.


1
"Điều này rất không phổ biến": Theo Stroustrup2013, C ++ 11 dường như có các ưu tiên khác nhau của AND và OR (trang 257). Tương tự đối với Python: docs.python.org/2/reference/expressions.html
Dirk

10
Re: "Mọi ngôn ngữ tôi biết đều đối xử VÀ VÀ HOẶC như nhau": Tôi nghi ngờ đó là sự thật. Nếu đó sự thật, thì bạn không biết bất kỳ ngôn ngữ nào trong số mười ngôn ngữ phổ biến nhất (C, Java, C ++, PHP, JavaScript, Python, C #, Perl, SQL và Ruby) và không thể bình luận về "không phổ biến" là gì, hãy để một mình "rất không phổ biến".
ruakh

1
Tôi đồng ý với ruakh và tìm kiếm C ++ 11, python, matlab và java.
Dirk

3
Các ngôn ngữ trong đó AND và OR là các toán tử nhị phân và không coi AND là có mức độ ưu tiên cao hơn OR, là các crap braindamaged có tác giả là các tác giả khoa học máy tính. Điều này xuất phát từ ký hiệu logic. Xin chào, "tổng sản phẩm" không có nghĩa gì sao? Thậm chí còn có một ký hiệu boolean sử dụng phép nhân (vị trí các yếu tố) cho AND và ký hiệu + cho OR.
Kaz

3
@ruakh Bạn chỉ cần đưa ra quan điểm của tôi cho tôi. Bởi vì có một số ít các trường hợp bệnh lý cạnh không có nghĩa là bạn không nên học ưu tiên Boolean tiêu chuẩn và cho rằng nó giữ cho đến khi được chứng minh khác đi. Chúng ta không nói về các quyết định thiết kế tùy ý ở đây; Đại số Boolean được phát minh từ lâu trước khi máy tính. Ngoài ra, hãy cho tôi xem thông số Pascal mà bạn đang nói đến. Ở đâyở đây hiển thị VÀ trước HOẶC.
dodgethesteamler

1

Như mọi người đã nói, sử dụng dấu ngoặc đơn mỗi lần nó làm cho biểu thức dễ đọc hơn. Tuy nhiên, nếu biểu thức phức tạp, tôi khuyên bạn nên giới thiệu các chức năng mới cho các biểu thức con .


0

Hay đó là một dấu hiệu cho thấy một nhà phát triển cần phải thực sự ngồi xuống và tự tin vào những điều cơ bản trong ngôn ngữ của họ?

Nếu bạn nghiêm túc sử dụng ngôn ngữ ở số ít, có thể. Bây giờ, hãy sử dụng tất cả các ngôn ngữ bạn biết, từ cũ đến hiện đại nhất, từ được biên dịch sang viết mã thành SQL đến DSL của riêng bạn mà bạn đã phát minh ra vào tháng trước.

Bạn có nhớ các quy tắc ưu tiên chính xác cho từng ngôn ngữ này mà không cần tìm kiếm không?


1
Và như @Cape Cod Gunny ở trên đã lưu ý, ngay cả khi bạn nghĩ rằng bạn biết ngôn ngữ lạnh, trình biên dịch / thời gian chạy có thể thay đổi bên dưới bạn.
Jordan

0

"Tôi có nên sử dụng dấu ngoặc đơn trong các câu lệnh logic ngay cả khi không cần thiết."

Có, bởi vì hai người sẽ thấy chúng hữu ích:

  • Lập trình viên tiếp theo, kiến ​​thức, năng lực hoặc phong cách có thể khác nhau

  • Tương lai bạn trở lại mã này vào một ngày nào đó sau này!


-1

Các điều kiện phức tạp là "đại số boolean", mà bạn viết theo một số cách, làm cho nó trông khá giống với đại số, và bạn chắc chắn sẽ sử dụng parens cho đại số , phải không?

Các quy tắc thực sự hữu ích là những quy tắc phủ định:

!(A || B) <=> !A && !B
!(A && B) <=> !A || !B

Hoặc, trong một định dạng rõ ràng hơn một chút:

!(A + B) <=> !A * !B
!(A * B) <=> !A + !B

thực sự rõ ràng chỉ là đại số khi được viết là:

-1*(A + B) = -A + -B
-1*(A * B) = -A * -B

Nhưng chúng ta cũng có thể áp dụng tư duy cho đơn giản hóa và mở rộng đại số:

(A && B) || (C && D) => 
((A && B) || C) && ((A && B) || D) => 
(AC && BC) && (AD && BD) =>
AC && BC && AD && BD

mặc dù trong mã bạn phải viết:

(A||C) && (B||C) && (A||D) && (B||D)

hoặc, trong một định dạng rõ ràng hơn một chút:

(A + B) * (C + D) => 
((A + B) * C) + ((A + B) * D) => 
(AC + BC) + (AD + BD) =>
AC + BC + AD + BD

Về cơ bản, một điều kiện vẫn chỉ là một biểu thức đại số và bằng cách sử dụng dấu ngoặc đơn rõ ràng, bạn có thể dễ dàng áp dụng các quy tắc đại số khác nhau mà bạn đã biết vào biểu thức, bao gồm cả khái niệm "đơn giản hóa hoặc mở rộng công thức này".


2
Tôi không chắc bạn thực sự đang trả lời câu hỏi, vì bạn dẫn câu trả lời của mình với một giả định không nhất thiết là đúng. Tôi sẽ sử dụng dấu ngoặc đơn cho đại số? Không phải tất cả thời gian. Nếu nó giúp với khả năng đọc, thì chắc chắn, nhưng những người khác đã thể hiện điều đó ở đây. Và việc mở rộng đại số toán học sang các dạng khác không chính xác có sự tương ứng một-một với lập trình - điều gì xảy ra nếu bạn đang kiểm tra trạng thái của một vài giá trị chuỗi?
Derek

Nếu đại số boolean tương ứng đủ phức tạp để đảm bảo parens, điều kiện của bạn có lẽ nên sử dụng parens. Nếu nó đủ đơn giản để không đảm bảo parens, bạn sẽ không phải hoặc không nên. Dù bằng cách nào, nghĩ về nó như bạn sẽ có một biểu thức toán học có thể làm rõ vấn đề.
Người kể chuyện

Ví dụ của tôi ở trên sử dụng hai và bốn booleans. Nếu bạn đang kiểm tra trạng thái của hai hoặc nhiều giá trị chuỗi, nó sẽ ánh xạ. Mỗi kiểm tra tương ứng với một biến boolean; bất kể kiểm tra đó là số nguyên hay chuỗi bằng; bao gồm chuỗi, mảng hoặc hàm băm; một biểu hiện phức tạp ... Không thành vấn đề; tất cả vấn đề là bạn có nhiều hơn một phép đo đúng / sai trong biểu thức của bạn.
Người kể chuyện

2
Chỉ cần săm soi, nhưng trong !(A + B) <=> !A + !B-1*(A + B) = -A + -Bkhông nên các nhà điều hành đã được lật từ +để *trong biểu thức thứ hai?
Jeff Bridgman

-1

Tôi sẽ sử dụng dấu ngoặc đơn ngay cả khi nó là tùy chọn, tại sao vì nó giúp hiểu rõ hơn cho mọi người, cho người viết mã cũng như người sẵn sàng xem mã đó. Trong trường hợp của bạn, ngay cả các toán tử boolean đã được ưu tiên, nó có thể hoạt động tốt lúc đầu, nhưng chúng tôi không thể nói rằng nó sẽ giúp bạn trong mọi trường hợp. Vì vậy, tôi thích sử dụng dấu ngoặc đơn của người dùng trong bất kỳ điều kiện nào mà nó có thể yêu cầu hoặc tùy chọn.


-1

Đúng. Bạn nên sử dụng trong mọi trường hợp khi bạn cảm thấy mã của mình sẽ rõ ràng hơn. Hãy nhớ mã của bạn phải đủ rõ ràng để người khác có thể hiểu mà không cần đọc bình luận của bạn bên trong mã. Vì vậy, đó là một thực hành tốt để sử dụng dấu ngoặc đơn và niềng răng. Ngoài ra, hãy nhớ rằng nó có thể phụ thuộc vào thực tiễn cụ thể của công ty / nhóm của bạn. Chỉ cần duy trì một cách tiếp cận và không trộn lẫn.

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.