if ('hằng' == $ biến) so với if ($ biến == 'hằng')


48

Gần đây, tôi đã làm việc rất nhiều trong PHP và đặc biệt là trong khung WordPress. Tôi nhận thấy rất nhiều mã ở dạng:

if ( 1 == $options['postlink'] )

Nơi mà tôi đã dự kiến ​​sẽ thấy:

if ( $options['postlink'] == 1 )

Đây có phải là một quy ước được tìm thấy trong các ngôn ngữ / khung nhất định? Có bất kỳ lý do nào cách tiếp cận trước thích hợp hơn phương pháp sau (từ góc độ xử lý, hoặc quan điểm phân tích cú pháp hoặc thậm chí là quan điểm của con người?)

Hay đó chỉ là vấn đề của hương vị? Tôi đã luôn nghĩ rằng tốt hơn khi thực hiện một bài kiểm tra, rằng mục biến được kiểm tra đối với một số hằng số nằm ở bên trái. Nó dường như ánh xạ tốt hơn theo cách chúng ta sẽ đặt câu hỏi bằng ngôn ngữ tự nhiên: "nếu bánh là sô cô la" chứ không phải "nếu sô cô la là bánh".


1
Tôi chưa bao giờ viết mã như vậy nhưng công bằng mà nói "nếu sô cô la là hương vị của bánh" nghe có vẻ tự nhiên. Ngôn ngữ tự nhiên linh hoạt hơn.
Rick Sladkey

4
@Rick Nghe có vẻ tự nhiên trong ngôn ngữ, nhưng bạn không thể phủ nhận rằng khi bạn thấy mã như vậy, bạn phải dừng lại trước tiên (có thể chỉ trong một giây) để nghĩ xem nó đang cố gắng làm gì.
Edgar Gonzalez

4
@Edgar Gonzalez: Đồng ý, tôi kiên quyết chống lại nó trong mã.
Rick Sladkey

3
Chương 19 của Code Complete 2nd Edition (trong phần "Biểu thức Boolean: Các vấn đề thường gặp với Biểu thức Boolean") thực sự khuyến nghị thực hành này vì lý do chính xác được nêu trong nhiều câu trả lời ở đây: để tránh gán trong các ngôn ngữ có nguồn gốc C khi so sánh có nghĩa là .
CraigTP

4
Tôi thường thấy những điều này được gọi là "Điều kiện Yoda"
Brian

Câu trả lời:


83

Lý do chính để làm điều này (cái gọi là "Yoda có điều kiện") là để ngăn ngừa tai nạn khi bạn vô tình sử dụng toán tử gán ( =) thay vì toán tử so sánh bằng nhau ( ==).

Đó là, nếu bạn đã sai lầm khi làm:

$foo = 5;
if ($foo = 1) {
  // Stuff
}

Tuyên bố sẽ đánh giá true(hoặc, trong trường hợp một số ngôn ngữ khác như PHP, một giá trị trung thực) và bạn sẽ gặp một lỗi khó tìm.

Nhưng nếu bạn đã làm:

$foo = 5;
if (1 = $foo) {
  // Stuff
}

Bạn sẽ nhận được một lỗi nghiêm trọng vì bạn không thể gán $foocho một số nguyên.

Nhưng như bạn đã chỉ ra, đảo ngược trật tự thường làm cho mọi thứ trở nên khó đọc hơn. Vì vậy, nhiều tiêu chuẩn mã hóa (nhưng không phải tất cả, bao gồm cả WordPress ) đề xuất hoặc yêu cầu $foo == 1bất chấp lợi ích săn lỗi của 1 == $foo.

Nói chung, lời khuyên của tôi là tuân theo bất kỳ tiêu chuẩn mã hóa nào được thiết lập, nếu có: đối với WordPress, điều đó có nghĩa là sử dụng các điều kiện Yoda.

Khi không có, và không thể thiết lập một thông qua sự đồng thuận với các đồng nghiệp của bạn, đó là lựa chọn của người giao dịch.


2
Tôi nhớ khi thiết kế một ngôn ngữ (từ lâu rồi) mà chúng tôi đặc biệt đã thực hiện :=là toán tử gán (với ==kiểm tra đẳng thức) để tránh loại rắc rối này.
Donal Fellows

7
Tôi đã viết rất nhiều, rất nhiều dòng mã và tôi chưa bao giờ vô tình gõ =thay thế ==. Sự khác biệt được nhấn mạnh ở khắp mọi nơi đến nỗi tôi không bao giờ nhầm lẫn chúng. Mặt khác, tôi đã đọc nhiều đoạn mã khó hiểu hoặc khó hiểu. Như vậy, tôi sẽ đặt ưu tiên cho khả năng đọc :). Bất kể, câu trả lời tốt.
crazy2be

5
Một lý do chính đáng khác để sử dụng -Wall -Werrorhoặc tương đương trình biên dịch / trình thông dịch của bạn. Có rất ít tình huống trong đó một bài tập bên trong một điều kiện là chính xác, hãy để một mình dễ đọc hơn. Rất nhiều ngôn ngữ thậm chí không cho phép nó.
Karl Bielefeldt

7
Pedantic: Trong khi if($foo = 1)đánh giá truetheo một số ngôn ngữ, trong PHP, nó đánh giá là 1 thay vào đó; if($foo = 20)đánh giá đến 20; if($foo = 0)đánh giá về 0, không giống như những người khác là sai. Điều này có thể thêm một lớp phức tạp hoàn toàn vào lỗi.
Charles

2
Trên thực tế, Tiêu chuẩn mã hóa WordPress KHÔNG yêu cầu Yoda có điều kiện: codex.wordpress.org/WordPress_Coding_Stiterias#Yoda_Conditions
Tom Auger

13

Đó là một cơ chế mã hóa phòng thủ nhằm ngăn chặn việc sử dụng ngẫu nhiên toán tử gán.

Xem xét việc sử dụng sai / lỗi của toán tử gán thay cho toán tử đẳng thức

if ( $options['postlink'] = 1  )

Các điều kiện trên sẽ luôn luôn trả về đúng, nhưng đó có lẽ không phải là điều mà lập trình viên ban đầu nghĩ đến. Hãy xem xét, ở vị trí của nó, cái này

if( 1 = $options['postlink'])

Ở đây, PHP (và hầu hết các ngôn ngữ khác) sẽ từ chối chạy, vì không thể gán bất cứ thứ gì cho giá trị cố định của 1. Bằng cách mã hóa tất cả các câu lệnh có điều kiện theo cách này, bạn sẽ tự động đảm bảo không sử dụng ngẫu nhiên một toán tử gán trong một điều kiện.


9

Tôi thích sử dụng quy ước đó trong java để loại bỏ khả năng ngoại lệ con trỏ null. Vì vậy, một cái gì đó như thế này sẽ không gây ra cho bạn bất kỳ vấn đề hoặc cần thêm bất kỳ mã nào:

String foo = null;

if ("bar".equals(foo))
{
    //Do something
}

3
Tôi thích điều này, nhưng tôi ghét thành ngữ chung.
Thomas Eding

3
Nếu giá trị null không hợp lệ tại thời điểm đó trong mã, bạn nên đã kiểm tra nó bằng mọi giá hoặc thiết kế mã của bạn theo cách không thể có giá trị null.
Ed S.

6
đây có vẻ là một cách dễ dàng để che giấu vấn đề Bụi không được làm sạch bằng cách nhún chúng bên trong thảm.
Lie Ryan

0

Trong thực tế, nhiều trình biên dịch sẽ đưa ra cảnh báo nếu bạn viết "if (x = 1)" thay vì "if (x == 1)" vì rất có thể đó là một lỗi.

Với Clang, bạn có thể tránh cảnh báo bằng cách nói với trình biên dịch một cách hiệu quả "Ý tôi là nó và tôi biết tôi đang làm gì" và điều này được thực hiện bằng cách viết "if ((x = 1))". Lưu ý các dấu ngoặc đơn phụ. Điều đó làm việc trong các tình huống khác là tốt. câu lệnh if (false); có thể cho bạn một cảnh báo rằng tuyên bố không bao giờ được thực thi; câu lệnh if ((false)); không đưa ra cảnh báo đó.


Tôi thích điều đó rất nhiều! Tôi tránh các thành ngữ sau đây, hoàn toàn hợp pháp trong PHP vì tôi luôn nhận được các cảnh báo trong IDE của mình:if ($array = getSomething()){ // ..so something with $array }
Tom Auger
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.