Cách tốt nhất để định dạng câu lệnh if với nhiều điều kiện


88

Nếu bạn muốn một số mã để thực thi dựa trên hai hoặc nhiều điều kiện thì cách tốt nhất để định dạng câu lệnh if đó là gì?

ví dụ đầu tiên: -

if(ConditionOne && ConditionTwo && ConditionThree)
{
   Code to execute
}

Ví dụ thứ hai: -

if(ConditionOne)
{
   if(ConditionTwo )
   {
     if(ConditionThree)
     {
       Code to execute
     }
   }
}

dễ hiểu và dễ đọc nhất, hãy nhớ rằng mỗi điều kiện có thể là một tên hàm dài hoặc một cái gì đó.


Thật đáng tiếc khi không ai trên trang này đề cập đến chuỗi con "nhanh" hoặc "hiệu suất". Đó là những gì tôi đến đây để học hỏi.
Chủ tịch Dreamspace

Câu trả lời:


131

Tôi thích Lựa chọn A hơn

bool a, b, c;

if( a && b && c )
{
   //This is neat & readable
}

Nếu bạn có các biến / điều kiện phương thức đặc biệt dài, bạn có thể ngắt dòng

if( VeryLongConditionMethod(a) &&
    VeryLongConditionMethod(b) &&
    VeryLongConditionMethod(c))
{
   //This is still readable
}

Nếu chúng thậm chí còn phức tạp hơn, thì tôi sẽ xem xét thực hiện các phương thức điều kiện riêng biệt bên ngoài câu lệnh if

bool aa = FirstVeryLongConditionMethod(a) && SecondVeryLongConditionMethod(a);
bool bb = FirstVeryLongConditionMethod(b) && SecondVeryLongConditionMethod(b);
bool cc = FirstVeryLongConditionMethod(c) && SecondVeryLongConditionMethod(c);

if( aa && bb && cc)
{
   //This is again neat & readable
   //although you probably need to sanity check your method names ;)
}

IMHO Lý do duy nhất cho tùy chọn 'B' là nếu bạn có các elsechức năng riêng biệt để chạy cho từng điều kiện.

ví dụ

if( a )
{
    if( b )
    {
    }
    else
    {
        //Do Something Else B
    }
}
else
{
   //Do Something Else A
}

Tôi thích nó. Mặc dù tôi không phải là một fan hâm mộ lớn của ý tưởng phương thức, trừ khi các phương thức đã tồn tại và trả về giá trị boolean.
Thomas Owens

2
Chẳng phải bạn đang đánh giá mọi thứ mà không có lý do trong ví dụ thứ hai sao?
Odys

Tôi sẽ sử dụng '&&' trước điều kiện. Khó có điều kiện có cùng độ dài ký tự như trong ví dụ.
Darkov

28

Các câu trả lời khác giải thích tại sao tùy chọn đầu tiên thường là tốt nhất. Nhưng nếu bạn có nhiều điều kiện, hãy xem xét việc tạo một hàm (hoặc thuộc tính) riêng biệt thực hiện kiểm tra điều kiện trong tùy chọn 1. Điều này làm cho mã dễ đọc hơn nhiều, ít nhất là khi bạn sử dụng các tên phương thức tốt.

if(MyChecksAreOk()) { Code to execute }

...

private bool MyChecksAreOk()
{ 
    return ConditionOne && ConditionTwo && ConditionThree;
}

Điều kiện chỉ dựa vào các biến phạm vi cục bộ, bạn có thể làm cho hàm mới ở trạng thái tĩnh và chuyển mọi thứ bạn cần. Nếu có sự kết hợp, hãy chuyển những thứ địa phương vào.


2
Tôi thấy điều này là hiệu quả nhất và dễ dàng hơn để thêm các điều kiện sau này
pbojinov

+1 lúc đầu tôi nhướng mày nhưng đây thực sự là câu trả lời tốt nhất imho. có boolean đó isOkToDoWhateverlàm thuộc tính rất có ý nghĩa.
Grinch

1
Nhưng điều này chỉ di chuyển cùng một điều kiện phức tạp đến nơi khác, nơi nó cũng cần phải đọc được, vì vậy chúng ta quay lại hình vuông với điều này. Nó không chỉ là về ifkhả năng đọc câu lệnh mà còn là khả năng đọc điều kiện.
Robert Koritnik

@RobertKoritnik Tôi hiểu bạn đang nói gì, nhưng tôi không nghĩ rằng chúng ta quay trở lại bình phương một vì chúng tôi đã giảm độ phức tạp mà người đọc cần xem xét trong một lần. Cô ấy có thể xem xét các điều kiện, HOẶC cô ấy có thể xem mã bằng cách sử dụng các điều kiện trong đó các điều kiện có tên đẹp (hy vọng). Ít nhất thì tôi thường thấy điều này dễ tìm hiểu hơn, nhưng một lần nữa, đôi khi thật tuyệt khi có tất cả các chi tiết ở một nơi. Như mọi khi, nó phụ thuộc.
Torbjørn

Điểm tuyệt vời khi sử dụng các tên phương thức tốt và cấu trúc lại logic.
JB Lovell

10

Ví dụ đầu tiên là "dễ đọc" hơn.

Trên thực tế, theo ý kiến ​​của tôi, bạn chỉ nên sử dụng cái thứ hai bất cứ khi nào bạn phải thêm một số "logic khác", nhưng đối với một Điều kiện đơn giản, hãy sử dụng hương vị đầu tiên. Nếu bạn lo lắng về thời gian kéo dài của tình trạng, bạn luôn có thể sử dụng cú pháp tiếp theo:

if(ConditionOneThatIsTooLongAndProbablyWillUseAlmostOneLine
                 && ConditionTwoThatIsLongAsWell
                 && ConditionThreeThatAlsoIsLong) { 
     //Code to execute 
}

Chúc may mắn!


9

Câu hỏi đã được đặt ra và cho đến nay, đã được trả lời như thể quyết định nên được đưa ra hoàn toàn dựa trên cơ sở "cú pháp".

Tôi muốn nói rằng câu trả lời đúng về cách bạn đặt ra một số điều kiện trong if, cũng phải phụ thuộc vào "ngữ nghĩa". Vì vậy, các điều kiện nên được chia nhỏ và nhóm lại theo những gì mọi thứ đi cùng nhau về mặt khái niệm.

Nếu hai phép thử thực sự là hai mặt của cùng một đồng tiền ví dụ. if (x> 0) && (x <= 100) sau đó đặt chúng cùng nhau trên cùng một dòng. Nếu một điều kiện khác xa hơn về mặt khái niệm, ví dụ. user.hasPermission (Admin ()) sau đó đặt nó trên dòng riêng của nó

Ví dụ.

if user.hasPermission(Admin()) {
   if (x >= 0) && (x < 100) {
      // do something
   }
}

7
if (   ( single conditional expression A )
    && ( single conditional expression B )
    && ( single conditional expression C )
   )
{
   opAllABC();
}
else
{
   opNoneABC();
}

Định dạng nhiều biểu thức điều kiện trong câu lệnh if-else theo cách này:

  1. cho phép nâng cao khả năng đọc:
    a. tất cả các phép toán logic nhị phân {&&, ||} trong biểu thức được hiển thị đầu tiên
    b. cả hai toán hạng có điều kiện của mỗi phép toán nhị phân đều hiển nhiên vì chúng sắp xếp theo chiều dọc
    c. các phép toán biểu thức logic lồng nhau được thực hiện rõ ràng bằng cách sử dụng thụt đầu dòng, giống như các câu lệnh lồng nhau bên trong mệnh đề
  2. yêu cầu dấu ngoặc đơn rõ ràng (không dựa vào quy tắc ưu tiên toán tử)
    a. điều này tránh một lỗi phân tích tĩnh phổ biến
  3. cho phép gỡ lỗi dễ dàng hơn
    a. vô hiệu hóa các kiểm tra điều kiện đơn lẻ chỉ bằng một //
    b. đặt điểm nghỉ ngay trước hoặc sau bất kỳ điểm thử nghiệm cá nhân nào
    ...
// disable any single conditional test with just a pre-pended '//'
// set a break point before any individual test
// syntax '(1 &&' and '(0 ||' usually never creates any real code
if (   1
    && ( single conditional expression A )
    && ( single conditional expression B )
    && (   0
        || ( single conditional expression C )
        || ( single conditional expression D )
       )
   )
{
   ... ;
}

else
{
   ... ;
}

Đây là phương pháp của tôi. Vấn đề duy nhất tôi có là tôi vẫn chưa tìm thấy một beautifier mã mà cung cấp này như một tùy chọn
Speed8ump

4

Cái thứ hai là một ví dụ cổ điển về kiểu Chống mũi tên Vì vậy, tôi muốn tránh nó ...

Nếu điều kiện của bạn quá dài, hãy giải nén chúng thành các phương thức / thuộc tính.


3

Câu đầu tiên dễ hơn, bởi vì, nếu bạn đọc nó từ trái sang phải, bạn sẽ nhận được: "If something AND somethingelse AND somethingelse THEN", đây là một câu dễ hiểu. Ví dụ thứ hai là "If something THEN if somethingelse THEN if something else THEN", câu này khá vụng về.

Ngoài ra, hãy xem xét nếu bạn muốn sử dụng một số OR trong mệnh đề của mình - bạn sẽ làm điều đó như thế nào trong kiểu thứ hai?


0

Trong Perl, bạn có thể làm điều này:

{
  ( VeryLongCondition_1 ) or last;
  ( VeryLongCondition_2 ) or last;
  ( VeryLongCondition_3 ) or last;
  ( VeryLongCondition_4 ) or last;
  ( VeryLongCondition_5 ) or last;
  ( VeryLongCondition_6 ) or last;

  # Guarded code goes here
}

Nếu bất kỳ điều kiện nào không thành công, nó sẽ chỉ tiếp tục, sau khi khối. Nếu bạn đang xác định bất kỳ biến nào mà bạn muốn giữ lại sau khối, bạn sẽ cần xác định chúng trước khối.


1
Điều đó trông Perlish - trong "it does GÌ?" cảm giác;) Nhưng nó thực sự có thể đọc được, khi bạn đã quen với nó.
Piskvor rời tòa nhà vào

-2

Tôi đã đối mặt với tình huống khó xử này trong một thời gian dài và tôi vẫn không thể tìm ra một giải pháp thích hợp. Theo tôi, cách tốt nhất là trước tiên hãy cố gắng loại bỏ các điều kiện trước để bạn không đột nhiên so sánh 5 trong số chúng.

Nếu không có giải pháp thay thế nào thì giống như những người khác đã đề xuất - hãy chia nó thành những cái riêng biệt và rút ngắn tên hoặc nhóm chúng lại và ví dụ: nếu tất cả phải đúng thì hãy sử dụng một cái gì đó như "nếu không có sai trong mảng x thì chạy".

Nếu tất cả đều thất bại, @Eoin Campbell đã đưa ra những ý tưởng khá hay.


Điều này không thêm bất cứ điều gì mới vào các câu trả lời đã có.
Jerney

-4

Khi điều kiện thực sự phức tạp, tôi sử dụng kiểu sau (ví dụ PHP trong cuộc sống thực):

if( $format_bool &&
    (
        ( isset( $column_info['native_type'] )
            && stripos( $column_info['native_type'], 'bool' ) !== false
        )
        || ( isset( $column_info['driver:decl_type'] )
            && stripos( $column_info['driver:decl_type'], 'bool' ) !== false
        )
        || ( isset( $column_info['pdo_type'] )
            && $column_info['pdo_type'] == PDO::PARAM_BOOL
        )
    )
)

Tôi tin rằng nó đẹp và dễ đọc hơn là lồng nhiều cấp độ if(). Và trong một số trường hợp như thế này, bạn không thể chia điều kiện phức tạp thành nhiều phần vì nếu không, bạn sẽ phải lặp lại các câu lệnh giống nhau trong if() {...}khối nhiều lần.

Tôi cũng tin rằng thêm một số "không khí" vào mã luôn là một ý kiến ​​hay. Nó cải thiện khả năng đọc rất nhiều.

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.