Có phải là một thực hành xấu khi sử dụng một câu lệnh if mà không có dấu ngoặc nhọn? [đóng cửa]


130

Tôi đã thấy mã như thế này:

if(statement)
    do this;
else
    do this;

Tuy nhiên, tôi nghĩ rằng điều này dễ đọc hơn:

if(statement){
    do this;
}else{
    do this;
}

Vì cả hai phương pháp đều hoạt động, đây có phải chỉ đơn giản là vấn đề ưu tiên sử dụng hoặc một cách sẽ được đề xuất so với phương pháp kia?



Theo tôi thì nó tệ, bởi vì bạn bắt đầu dựa vào vết lõm khoảng trắng gần như không bao giờ hoàn toàn nhất quán. Nó làm trật bánh suy nghĩ của người đọc khi họ phải lo lắng về những điều như vậy.
Sridhar Sarnobat

Câu trả lời:


212

Vấn đề với phiên bản đầu tiên là nếu bạn quay lại và thêm một câu lệnh thứ hai vào mệnh đề if hoặc khác mà không nhớ thêm dấu ngoặc nhọn, mã của bạn sẽ bị hỏng theo những cách bất ngờ và gây cười.

Duy trì khôn ngoan, luôn luôn thông minh hơn khi sử dụng hình thức thứ hai.

EDIT: Ned chỉ ra điều này trong các bình luận, nhưng tôi cũng đáng liên kết đến đây. Đây không chỉ là một chuyện nhảm nhí giả thuyết tháp ngà: https://www.imperialviolet.org/2014/02/22/appleorms.html


17
Và bạn nên luôn luôn mã cho khả năng bảo trì. Rốt cuộc, tôi khá chắc chắn trình biên dịch không quan tâm bạn sử dụng hình thức nào. Đồng nghiệp của bạn, tuy nhiên có thể là pist nếu bạn giới thiệu một lỗi vì một lỗi niềng răng ngớ ngẩn.
Esteban Araya

12
Hoặc bạn có thể sử dụng ngôn ngữ không sử dụng dấu ngoặc cho khối mã ...
Tor Valamo

10
@ lins314159 - Không, ý tôi là giống trăn. Bởi vì tôi chau chuốt về vấn đề này.
Tor Valamo

17
Những sai lầm chứng minh khác có thể (và làm) xảy ra: Imperialialviolet.org/2014/02/22/appleorms.html
Ned

8
Khẳng định rằng lỗi SSL là một đối số có lợi cho niềng răng là không rõ ràng. Không phải như thể nhà phát triển có ý định viết if (…) { goto L; goto L; }mà quên mất niềng răng. Hoàn toàn ngẫu nhiên khi `` if (Mạnh) {goto L; goto L; } `xảy ra không phải là một lỗi bảo mật, bởi vì nó vẫn là một lỗi (chỉ không phải là một lỗi có hậu quả bảo mật). Trong một ví dụ khác, mọi thứ có thể đi theo hướng ngược lại và mã không thể vô tình có thể vô tình an toàn. Trong một ví dụ thứ ba, mã không có lỗi ban đầu sẽ không có lỗi và nhà phát triển sẽ giới thiệu một lỗi đánh máy trong khi thêm dấu ngoặc nhọn.
Pascal Cuoq

112

Một vấn đề với việc loại bỏ các khối lệnh là sự mơ hồ khác. Đó là ngôn ngữ lấy cảm hứng từ C bỏ qua thụt lề và vì vậy không có cách nào để phân tách điều này:

if(one)
    if(two)
        foo();
    else
        bar();

Từ đây:

if(one)
    if(two)
        foo();
else
    bar();

8
Đây là một vấn đề nghiêm trọng hơn nhiều so với vấn đề được đề cập trong câu trả lời hàng đầu (thêm một tuyên bố thứ hai).

3
thật vậy, câu trả lời này thực sự đã đưa tôi từ việc đọc những câu trả lời này một cách cay độc đến mức quan tâm nhẹ tôi có thể đã thực sự mắc lỗi này.
omike

2
Nếu bất cứ ai khác tự hỏi như tôi là cách mà C thực sự diễn giải nó, thì một thử nghiệm tôi đã làm với GCC diễn giải mã này theo cách đầu tiên. tpcg.io/NIYeqx
horta

2
"Sự mơ hồ" là thuật ngữ sai. Không có bất kỳ sự mơ hồ nào trong cách trình phân tích cú pháp sẽ thấy điều này: các elseràng buộc tham lam đến gần nhất, trong cùng if. Vấn đề phát sinh khi C hoặc các ngôn ngữ tương tự đang được mã hóa bởi những người không biết điều này, không nghĩ về nó hoặc chưa có đủ cà phê - vì vậy họ viết mã mà họ nghĩ sẽ làm một việc, nhưng spec spec nói rằng trình phân tích cú pháp phải làm một cái gì đó khác, có thể rất khác nhau. Và vâng, đó là một lập luận vững chắc khác về việc luôn luôn bao gồm cả niềng răng ngay cả khi ngữ pháp đánh dấu chúng theo lý thuyết là 'không cần thiết'.
gạch dưới

35

Mô hình chung của tôi là nếu nó phù hợp trên một dòng, tôi sẽ làm:

if(true) do_something();

Nếu có một mệnh đề khác hoặc nếu mã tôi muốn thực thi truecó độ dài đáng kể, hãy niềng răng theo mọi cách:

if(true) {
    do_something_and_pass_arguments_to_it(argument1, argument2, argument3);
}

if(false) {
    do_something();
} else {
    do_something_else();
}

Cuối cùng, nó đi đến một vấn đề chủ quan về phong cách và khả năng đọc. Tuy nhiên, thế giới lập trình chung, chia ra thành hai bên (đối với các ngôn ngữ sử dụng dấu ngoặc nhọn): sử dụng chúng mọi lúc mà không có ngoại lệ hoặc sử dụng chúng mọi lúc với ngoại lệ. Tôi là một phần của nhóm sau.


4
Mặc dù, dễ như viết if(true){ do_something(); }, tại sao lại có cơ hội để một lập trình viên khác giới thiệu một lỗi nghiêm trọng trên đường đi (tra cứu "goto fail" của tổng công ty mã ssl).
Craig

9
Không có số lượng dấu ngoặc sẽ giải phóng người bảo trì khỏi việc sử dụng bộ não của anh ta. Tôi ủng hộ ý tưởng "không có dấu ngoặc nếu nó khớp trong một dòng" bởi vì, đối với tôi, đó chỉ là một phiên bản của ternary nếu toán tử mà người ta không cần phải làm gì trong phần "sau:" chim nhạn Và tại sao bất cứ ai sẽ giới thiệu dấu ngoặc cho ternary nếu ?
Michal M

Tôi không đồng ý với tất cả rằng cuối cùng nó là chủ quan, cũng không chỉ ảnh hưởng đến phong cách và khả năng đọc. Là một người đã lãng phí thời gian để cố gắng gỡ lỗi các vấn đề mà hóa ra là do thiếu dấu phân cách khối (và không nhận thấy sự vắng mặt của họ), vì tôi phải sử dụng một kiểu mã hóa bỏ qua chúng khi 'không cần thiết' - và người đã đọc về rất nhiều lỗi khủng khiếp rất có thể gây ra bởi phong cách mã hóa như vậy - tôi nghĩ rằng đây là một vấn đề rất khách quan, thực tế. Chắc chắn, với một dấu phân cách bắt buộc theo phong cách, chúng ta vẫn có thể quên chúng, nhưng chắc chắn - ít nhất - bộ nhớ cơ làm cho chúng ta ít có khả năng hơn.
gạch dưới

10

Tôi đang sử dụng bộ định dạng mã của IDE tôi sử dụng. Điều đó có thể khác nhau, nhưng nó có thể được thiết lập trong Tùy chọn / Tùy chọn.

Tôi thích cái này:

if (statement)
{
    // comment to denote in words the case
    do this;
    // keep this block simple, if more than 10-15 lines needed, I add a function for it
}
else
{
    do this;
}

5
Đây là một vấn đề phong cách hoàn toàn chủ quan, cá nhân tôi không thích sự dư thừa của các dòng chỉ niềng răng. Nhưng này.
Matchu

14
Tôi ủng hộ phong cách này. Hầu hết mọi người đọc mã từ trái sang phải và nó làm cho mắt chúng ta neo vào cạnh trái của màn hình. Nó giúp phân tách trực quan và trích xuất mã thành các khối logic của các bước.
mloskot

6
Tôi luôn thích phong cách này. Dễ dàng hơn nhiều để tìm dấu ngoặc đóng tương ứng. Vì vậy, nó cần rất nhiều không gian? Sử dụng một phông chữ nhỏ hơn.
timday

4
Tôi luôn thấy việc "quét" qua mã dễ dàng hơn khi các dấu ngoặc nằm trên các dòng riêng biệt. Điều đó đi cho tất cả mọi thứ; các lớp, phương thức, if- và while-statement, et cetera. Không bao giờ thích có cú đúp đầu tiên trên cùng một dòng ...
Svish

2
Khoảng trắng là rẻ, đặc biệt là khi bạn có một IDE có khả năng gấp mã.
Moo

10

"Quy tắc" tôi tuân theo là:

Nếu câu lệnh "if" đang thử nghiệm để thực hiện điều gì đó (chức năng gọi IE, cấu hình biến, v.v.), hãy sử dụng dấu ngoặc nhọn.

if($test)
{
    doSomething();
}

Điều này là bởi vì tôi cảm thấy bạn cần phải làm rõ các chức năng đang được gọi và dòng chảy của chương trình đang diễn ra ở đâu, trong những điều kiện nào. Để lập trình viên hiểu chính xác các hàm được gọi và các biến nào được đặt trong điều kiện này rất quan trọng để giúp họ hiểu chính xác chương trình của bạn đang làm gì.

Nếu câu lệnh "if" đang thử nghiệm để dừng thực hiện điều gì đó (điều khiển luồng IE trong một vòng lặp hoặc hàm), hãy sử dụng một dòng duy nhất.

if($test) continue;
if($test) break;
if($test) return;

Trong trường hợp này, điều quan trọng đối với lập trình viên là phát hiện nhanh những trường hợp đặc biệt là nơi bạn không muốn mã chạy, và tất cả được bao phủ trong $ test, không phải trong khối thực thi.


8

Có niềng răng ngay từ giây phút đầu tiên sẽ giúp bạn không phải gỡ lỗi này:

if (statement)
     do this;
else
     do this;
     do that;

1
Đó dường như là lý do được chấp nhận, nhưng (để chơi người ủng hộ quỷ dữ ở đây) sẽ không một quy tắc tô sáng cú pháp bổ sung nào cũng giải quyết điều này, trong khi lưu một dòng?
Ken

2
Vì vậy, sẽ có một IDE sửa lỗi thụt lề khi bạn nhấn ;:)
Sam Harwell

6

Sử dụng niềng răng cho tất cả các câu lệnh if ngay cả những người đơn giản. Hoặc, viết lại một câu lệnh if đơn giản để sử dụng toán tử ternary:

if (someFlag) {
 someVar= 'someVal1';
} else {
 someVar= 'someVal2';
}

Trông đẹp hơn như thế này:

someVar= someFlag ? 'someVal1' : 'someVal2';

Nhưng chỉ sử dụng toán tử ternary nếu bạn hoàn toàn chắc chắn rằng không có gì khác cần phải đi trong khối if / khác!



2

Theo kinh nghiệm của tôi, lợi thế nhỏ (rất) của hình thức đầu tiên là khả năng đọc mã, hình thức thứ hai thêm "nhiễu".

Nhưng với IDE hiện đại và tự động mã (hoặc tự động hoàn thành) tôi khuyên bạn nên sử dụng biểu mẫu thứ hai, bạn sẽ không mất thêm thời gian để gõ dấu ngoặc nhọn và bạn sẽ tránh được một số lỗi thường gặp nhất.

Có đủ lỗi tiêu thụ năng lượng, mọi người chỉ không mở cửa cho lãng phí thời gian lớn.

Một trong những quy tắc quan trọng nhất cần nhớ khi viết mã là tính nhất quán. Mỗi dòng mã nên được viết theo cùng một cách, bất kể ai đã viết nó. Việc nghiêm ngặt ngăn ngừa lỗi "xảy ra";)

Điều này giống với việc đặt tên rõ ràng & rõ ràng các biến, phương thức, tệp của bạn hoặc với việc thụt lề chính xác ...

Khi sinh viên của tôi chấp nhận thực tế này, họ ngừng chiến đấu chống lại mã nguồn của chính họ và họ bắt đầu thấy mã hóa là một hoạt động thực sự thú vị, kích thích và sáng tạo. Họ thách thức tâm trí của họ, không phải thần kinh của họ!


2

Đó là một vấn đề ưu tiên. Cá nhân tôi sử dụng cả hai phong cách, nếu tôi chắc chắn rằng tôi sẽ không cần thêm các câu lệnh nữa, tôi sử dụng kiểu đầu tiên, nhưng nếu có thể, tôi sử dụng kiểu thứ hai. Vì bạn không thể thêm các câu lệnh nữa vào kiểu đầu tiên, tôi đã nghe một số người khuyên không nên sử dụng nó. Tuy nhiên, phương thức thứ hai không phải chịu một dòng mã bổ sung và nếu bạn (hoặc dự án của bạn) sử dụng kiểu mã hóa này, phương thức đầu tiên được ưu tiên rất nhiều cho các câu lệnh if đơn giản:

if(statement)
{
    do this;
}
else
{
    do this;
}

Tuy nhiên, tôi nghĩ giải pháp tốt nhất cho vấn đề này là ở Python. Với cấu trúc khối dựa trên khoảng trắng, bạn không có hai phương thức khác nhau để tạo câu lệnh if: bạn chỉ có một:

if statement:
    do this
else:
    do this

Mặc dù điều đó có "vấn đề" là bạn hoàn toàn không thể sử dụng niềng răng, nhưng bạn có được lợi ích rằng đó không phải là dòng đầu tiên theo kiểu đầu tiên và nó có sức mạnh để thêm nhiều câu lệnh hơn.


Bản thân tôi nghĩ cách Python xử lý các câu lệnh if-
other

1

Tôi đã luôn cố gắng làm cho mã của mình đạt tiêu chuẩn và trông gần giống nhất có thể. Điều này giúp người khác dễ đọc nó hơn khi họ chịu trách nhiệm cập nhật nó. Nếu bạn làm ví dụ đầu tiên của bạn và thêm một dòng vào giữa nó sẽ thất bại.

Không làm việc:

nếu (tuyên bố) làm điều này; và điều này; người khác làm điều này;


1

Cá nhân tôi sử dụng kiểu đầu tiên chỉ ném ngoại lệ hoặc trả về từ một phương thức sớm. Giống như đối số Kiểm tra ở đầu một hàm, bởi vì trong những trường hợp này, hiếm khi tôi có nhiều việc phải làm, và không bao giờ có việc khác.

Thí dụ:

if (argument == null)
    throw new ArgumentNullException("argument");

if (argument < 0)
    return false;

Nếu không tôi sử dụng phong cách thứ hai.


1

Sở thích cá nhân của tôi là sử dụng hỗn hợp khoảng trắng và dấu ngoặc như thế này:

if( statement ) {

    // let's do this

} else {

    // well that sucks

}

Tôi nghĩ rằng điều này có vẻ sạch sẽ và làm cho mã của tôi rất dễ đọc và quan trọng nhất - gỡ lỗi.


0

Tôi đồng ý với hầu hết các câu trả lời trong thực tế rằng tốt hơn là nên rõ ràng trong mã của bạn và sử dụng dấu ngoặc nhọn. Cá nhân tôi sẽ áp dụng một bộ tiêu chuẩn mã hóa và đảm bảo rằng tất cả mọi người trong nhóm biết chúng và tuân thủ. Nơi tôi làm việc, chúng tôi sử dụng các tiêu chuẩn mã hóa được xuất bản bởi IDesign.net cho các dự án .NET.


0

Tôi thích đặt một cái nẹp xoăn. Nhưng đôi khi, điều hành ternary giúp.

Thay vì :

int x = 0;
if (condition) {
    x = 30;
} else {
    x = 10;
}

Một cách đơn giản nên làm: int x = condition ? 30 : 20;

Cũng hãy tưởng tượng một trường hợp:

if (condition)
    x = 30;
else if (condition1)
    x = 10;
else if (condition2)
    x = 20;

Sẽ tốt hơn nhiều nếu bạn đặt nẹp xoăn vào.

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.