Các câu lệnh if / other nên được sắp xếp bởi sự hiếm hoi của các trường hợp hoặc khó xử lý chúng?


18

Trong một số mã tôi đang viết ngay bây giờ, tôi có một cái gì đó như thế này:

if (uncommon_condition) {
    do_something_simple();
} else {
    do();
    something();
    long();
    and();
    complicated();
}

Một phần trong tôi nghĩ rằng "Nó ổn theo cách viết của nó. Những trường hợp đơn giản nên đi trước và những trường hợp phức tạp hơn nên đi tiếp." Nhưng một phần khác nói: "Không! elseMã phải tuân theo if, vì iflà để xử lý các trường hợp bất thường và elselà để xử lý tất cả các trường hợp khác." Cái nào đúng hay thích?


4
Đặt hàng bởi sự đơn giản / dễ hiểu của các điều kiện! Phần còn lại có thể được chăm sóc bởi các trình tối ưu hóa, dự đoán nhánh và tái cấu trúc.
Marjan Venema

Đây là lý do tại sao chúng tôi được trả nhiều tiền: để đưa ra những quyết định khó khăn này.

Câu trả lời:


24

Đặt hàng theo khả năng của họ được thực hiện. Các điều kiện phổ biến nhất, rất có thể, v.v. nên đi trước.

"Khó xử lý chúng" nên được xử lý bằng cấu trúc mã, trừu tượng hóa, v.v. trong ví dụ, khối khác có thể được cấu trúc lại thành lệnh gọi phương thức đơn. Bạn muốn các ifmệnh đề của bạn ở cùng một mức độ trừu tượng.

if ( ! LotteryWinner ) {
    GoToWorkMonday();
} else {
    PlanYearLongVacation();
}

6
Đối với hiệu suất tôi có thể đồng ý. Nhưng sau đó, một lần nữa, hầu hết các trình tối ưu hóa và dự đoán nhánh hoàn toàn có khả năng chăm sóc điều đó. Để dễ đọc, tôi có thể đồng ý nếu trường hợp rất có thể có nhiều dòng hơn đáng kể so với trường hợp ít có khả năng hơn. Nhưng với tôi điều đó sẽ sớm chỉ ra sự cần thiết phải trích xuất một phương thức hơn là sử dụng a not. Cá nhân tôi sẽ tập trung vào việc tránh các notđiều kiện. Chúng đã được chứng minh là tạo ra tải trọng nhận thức nhiều hơn để hiểu hơn các điều kiện "tích cực" và gây bất lợi cho khả năng đọc / hiểu mã. Tôi có xu hướng chỉ sử dụng chúng trong các tuyên bố bảo vệ.
Marjan Venema

2
@MarjanVenema, tôi có thể thấy quan điểm của bạn về "không" ing. Nhưng tiêu cực kép là WTF "không" thực sự. Hôm nọ tôi chạy vào đây trong mã của chúng tôi doesNotAllowxxFiles = false. Đủ tệ nhưng sau đó làm điều nàyif(! doesNotAllowxxFiles)
radarbob

Đúng, phủ định kép, phủ định kết hợp với và và hoặc hoặc (sic!) Và phủ định kết hợp với một phương thức / var với Không có trong tên, khiến não tôi bị xoắn mỗi lần :-)
Marjan Venema

nếu bạn thấy mình gặp khó khăn trong việc hiểu chuyện gì đang xảy ra, tôi nghĩ việc này thường hữu ích khi làm những việc như: SimpleBool = (! (ComplexBool | | RandomfFlag)) &&! RandomFlag
TruthOf42

2
Tôi đồng ý với bạn, ngoại trừ sự tồn tại của các Điều khoản bảo vệ (vốn luôn có điều kiện ngoại lệ trong phần THEN của tuyên bố IF, không phải là điều kiện chung).
Robert Harvey

5

Cố gắng tăng cường khả năng đọc. Một cách là đặt khối mã dài hơn vào phần khác.

if (s == null)
     // short code
else 
     // long 
     // code
     // block

dễ đọc hơn

if (s != null)
    // long
    // code
    // block
else
    // short code

2
Tại sao nó dễ đọc hơn? Tôi thấy không có sự khác biệt giữa hai về khả năng đọc
John Demetriou

2
@JohnDemetriou The Else hiển thị rõ hơn nếu Then ngắn. Mọi người quét cấu trúc trước, sau đó gán ý nghĩa cho nó. Mã không có Else khác với mã với một, vì vậy làm cho Else dễ nhìn thấy hơn là điều dễ hiểu hơn. (Tất cả những thứ khác đều bằng nhau, vào thứ ba khi trời không mưa, v.v.)

4

Không có quy tắc cố định như vậy tôi đã nghe về việc sử dụng nhưng tôi làm theo như thế này

if(usual)
{
(more often)
}
else (unusual)
{
(rarely occurring)
}

Nhưng nếu cả hai đều có cùng chức năng với các thuộc tính khác nhau thì tốt nhất nên sử dụng bất thường trước để thông thường để bạn có thể lưu một hướng dẫn.


if(x == 0)  // 1
  {x = 1;}  // 2
else
  {x = 2;}  // 3

Đối với mã lắp ráp mã ở trên sẽ là một cái gì đó như thế này:

1. 000d 837DFC00        cmpl    $0, -4(%ebp)
   0011 7509            jne .L2

2. 0013 C745FC01        movl    $1, -4(%ebp)
   001a EB07            jmp .L3

    .L2:
3.001c C745FC02         movl    $2, -4(%ebp)

        .L3:

Nếu điều kiện bên trong if là true thì luồng là 1-> 2 (4 lần nhập)
Điều kiện bên trong if là false thì luồng là 1-> 3 (3 lần nhập)

Vì vậy, tốt hơn là đặt các sự kiện bất thường hoặc hiếm khi xảy ra nếu một phần và tình trạng bình thường khác để chúng ta có thể lưu một hướng dẫn mỗi lần ;-)


2

Tôi đã thấy rằng mẫu ngược lại chính xác dẫn đến việc đọc mã dễ dàng hơn và giảm hoặc loại bỏ các câu lệnh if lồng nhau. Tôi gọi nó là một mẫu "găng tay". (. Trong câu chuyện kể, một gauntlet sẽ là một loạt các thách thức mà phải được đáp ứng thành công trước khi nhiệm vụ cuối cùng được hoàn thành) Bằng cách xử lý vụ việc cạnh bạn đầu tiên , bạn cho phép phần chính của mã của bạn được sạch sẽ và súc tích:

if(gauntlet_1){ handle the first gauntlet condition }; 
if(gauntlet_2){ handle the second gauntlet condition };
...
// All preconditions (gauntlets) have been successfully handled

// Perform your main task here

Vì vậy, phần "xử lý găng tay" sẽ phải là một sự chuyển giao quyền kiểm soát, như một tuyên bố ném hoặc trả lại, hoặc sẽ phải thực sự sửa lỗi. Một số người cau mày với một loạt các câu lệnh if ... return, nhưng tôi không nghĩ và thực tế nó làm cho mã dễ đọc hơn, như bạn đã nói.

1
Nếu điều kiện găng tay là thứ sẽ ngăn chức năng thành công, nó sẽ trả về lỗi ngay lập tức. Nếu điều kiện găng tay có thể được xử lý, tôi làm như vậy trước khi vào phần chính của mã bất cứ khi nào có thể. Tôi chủ yếu cố gắng tránh các câu lệnh IF lồng nhau, mà theo kinh nghiệm của tôi là một trong những nguyên nhân chính gây ra lỗi tối nghĩa và khó gỡ lỗi.
Byron Jones

0

Đối với tôi, đó là về các điều kiện hơn là sự phức tạp của mã họ thực thi. Bạn cần phải đặt hàng các điều kiện để bẫy các điều kiện bất thường trước, sau đó phổ biến hơn sau. Ngoài ra, nếu mã khác thực sự dài và phức tạp, có lẽ tôi sẽ tạo một phụ cho điều đó, để giữ cho phần điều kiện rõ ràng cho người đọc.


-1

Tôi không có một quy tắc cố định, nhưng nói chung tôi tuân theo quy tắc này - trước tiên, hãy xem xét nơi có một mẫu thiết kế bị bỏ lỡ sẽ đưa ra yếu tố này. Nếu không, tôi viết nó để điều kiện trong if được hiểu rõ nhất. Đó là, tránh tiêu cực kép và tương tự.


-1

Đối với các kịch bản như vậy không có quy tắc ngón tay cái cho nó. Nhưng có lẽ chúng ta có thể làm theo để viết mã dương hoặc rất có thể trong khối if và bỏ qua trong khối khác hoặc các trường hợp mặc định.


này không cung cấp bất cứ điều gì hơn những gì đã được giải thích trong câu trả lời trước đó - programmers.stackexchange.com/a/223093/31260programmers.stackexchange.com/a/223520/31260
một loại muôi
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.