2011-01-23 40 views
23

Thực sự là một cách hay để tránh sử dụng toán tử NOT trong điều kiện IF để làm cho mã của bạn dễ đọc hơn? Tôi nghe thấy số if (doSomething()) tốt hơn là if (!doSomething()).Sử dụng toán tử NOT trong điều kiện IF

+2

"' if (...) 'là tốt hơn' if (...!) '" - Đợi đã, wat? – delnan

+0

Câu hỏi đã được mở rộng một chút để làm cho nó rõ ràng hơn. – Eugene

+0

Đối với tôi không phải là thực tế của một tốt hơn khác, chỉ đơn giản là bạn phải sử dụng mà là thích hợp trong mọi tình huống, thế giới có điều kiện là rất rộng và đa dạng. –

Trả lời

32

Nó thực sự phụ thuộc vào những gì bạn đang cố gắng hoàn thành. Nếu bạn không có mệnh đề nào khác thì if(!doSomething()) có vẻ ổn. Tuy nhiên, nếu bạn có

if(!doSomething()) { 
    ... 
} 
else { 
    // do something else 
} 

tôi có lẽ muốn đảo ngược mà logic để loại bỏ các nhà điều hành ! và làm cho mệnh đề if hơi rõ ràng hơn.

+0

+1 Rất đúng điều đó. –

+1

Tôi (gần như) luôn luôn cấu trúc nếu elses để các chi nhánh phổ biến nhất của thực hiện đến đầu tiên. – Dunes

+1

Có quy tắc PMD ConfusingTernary để kiểm tra điều này: http://pmd.sourceforge.net/pmd-5.0.3/rules/java/design.html#ConfusingTernary –

11

Không, hoàn toàn không có gì sai khi sử dụng toán tử ! trong câu lệnh if..then..else.

Đặt tên biến và trong ví dụ của bạn, các phương pháp là điều quan trọng. Nếu bạn đang sử dụng:

if(!isPerson()) { ... } // Nothing wrong with this 

Tuy nhiên:

if(!balloons()) { ... } // method is named badly 

Tất cả đều đi xuống đến khả năng đọc. Luôn luôn nhằm mục đích cho những gì là dễ đọc nhất và bạn sẽ không đi sai. Luôn cố giữ mã của bạn liên tục, ví dụ: xem Bill the Lizards answer.

0

Tôi chưa bao giờ nghe nói đến điều này trước đây.

thế nào là

if (doSomething()) { 
} else { 
    // blah 
} 

tốt hơn so với

if (!doSomething()) { 
    // blah 
} 

này sau đó là rõ ràng hơn và súc tích.

Bên cạnh đó! toán tử có thể xuất hiện trong các điều kiện phức tạp như (! a || b). Làm thế nào để bạn tránh nó sau đó?

Sử dụng! điều hành khi bạn cần.

+1

bạn không làm điều gì đó trong tình trạng – Mikey

19

Như một tuyên bố chung, tốt để làm cho điều kiện của bạn nếu có thể đọc được càng tốt. Ví dụ của bạn, sử dụng! được rồi. vấn đề là khi mọi thứ trông giống như

if ((a.b && c.d.e) || !f) 

bạn có thể muốn làm điều gì đó như

bool isOk = a.b; 
bool isStillOk = c.d.e 
bool alternateOk = !f 

sau đó bạn câu lệnh if được đơn giản hóa để

if ((isOk && isStillOk) || alternateOk) 

Nó chỉ làm cho mã dễ đọc hơn. Và nếu bạn phải gỡ lỗi, bạn có thể gỡ lỗi tập hợp isOk của vars thay vì phải khai thác thông qua các biến trong phạm vi. Nó cũng hữu ích cho việc đối phó với NPEs - phá vỡ mã ra thành các khối đơn giản luôn luôn là tốt.

1

Thường không phải là ý tưởng tồi để tránh! -operator nếu bạn có lựa chọn. Một lý do đơn giản là nó có thể là một nguồn lỗi, bởi vì nó có thể bỏ qua nó. Dễ đọc hơn có thể là: if (conditionA == false) trong một số trường hợp. Điều này chủ yếu đóng một vai trò nếu bạn bỏ qua phần khác. Nếu bạn có một khối khác, bạn không nên sử dụng sự phủ định trong điều kiện if.

Trừ gồm điều kiện như thế này:

if(!isA() && isB() && !isNotC()) 

Ở đây bạn phải sử dụng một số loại phủ định để có được logic mong muốn. Trong trường hợp này, những gì thực sự đáng để suy nghĩ là đặt tên cho các hàm hoặc các biến. Hãy thử đặt tên cho chúng để bạn có thể thường xuyên sử dụng chúng trong điều kiện đơn giản mà không cần phủ định.

Trong trường hợp này, bạn nên suy nghĩ về logic của isNotC() và nếu nó có thể được thay thế bằng một phương thức isC() nếu nó có ý nghĩa. Cuối cùng ví dụ của bạn có một vấn đề khác khi nói đến khả năng đọc mà thậm chí còn nghiêm trọng hơn câu hỏi có nên sử dụng phủ định hay không: Người đọc mã thực sự biết khi nào doSomething() trả về true và khi false? Nếu nó đã được sai là nó được thực hiện anyway? Đây là một vấn đề rất phổ biến, mà kết thúc trong người đọc cố gắng để tìm ra những gì các giá trị trả về của các chức năng thực sự có ý nghĩa.

4

Nói chung,! là một toán tử logic logic hoàn toàn tốt và dễ đọc. Không có lý do gì để không sử dụng nó trừ khi bạn đơn giản hóa bằng cách loại bỏ hai âm bản hoặc áp dụng luật của Morgan.

!(!A) = A 

hoặc

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

Như một quy tắc của ngón tay cái, giữ chữ ký của boolean phương pháp trở lại ghi nhớ của bạn và phù hợp với Công ước. Vấn đề với kịch bản mà @hvgotcodes đề xuất là tất nhiên a.b và c.d.e không phải là những ví dụ rất thân thiện để bắt đầu. Giả sử bạn có chuyến bay và Hạng chỗ ngồi cho đơn đăng ký chuyến bay. Sau đó, điều kiện đặt chuyến bay hoàn toàn có thể là một cái gì đó như

if(flight.isActive() && !seat.isTaken()) 
{ 
    //book the seat 
} 

Mã dễ đọc và dễ hiểu này. Bạn có thể xác định lại logic boolean của bạn cho lớp Seat và thay đổi điều kiện cho điều này.

if(flight.isActive() && seat.isVacant()) 
{ 
    //book the seat 
} 

Vì vậy, hãy xóa! nhà điều hành nếu nó thực sự làm phiền bạn, nhưng bạn sẽ thấy rằng tất cả phụ thuộc vào ý nghĩa của các phương thức boolean của bạn.

1

thử như thế này

if (!(a | b)) { 
    //blahblah 
} 

Đó là cùng với

if (a | b) {} 
else { 
    // blahblah 
} 
Các vấn đề liên quan