if ('constant' == $ variable) vs. if ($ variable == 'constant')

49

Akhir-akhir ini, saya telah banyak bekerja di PHP dan khususnya dalam kerangka WordPress. Saya memperhatikan banyak kode dalam bentuk:

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

Di mana saya diharapkan untuk melihat:

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

Apakah ini sebuah konvensi yang ditemukan dalam bahasa / kerangka kerja tertentu? Adakah alasan mengapa pendekatan yang pertama lebih disukai daripada yang terakhir (dari perspektif pemrosesan, atau perspektif parsing atau bahkan perspektif manusia?)

Atau itu hanya masalah selera? Saya selalu berpikir lebih baik ketika melakukan tes, bahwa item variabel yang diuji terhadap beberapa konstanta ada di sebelah kiri. Tampaknya memetakan lebih baik dengan cara kita akan mengajukan pertanyaan dalam bahasa alami: "jika kue adalah cokelat" daripada "jika coklat adalah kue".

Tom Auger
sumber
1
Saya tidak pernah menulis kode seperti itu tetapi bersikap adil "jika cokelat adalah rasa kue" memang terdengar alami. Bahasa alami lebih fleksibel.
Rick Sladkey
4
@Rick Ini mungkin terdengar alami dalam bahasa, tetapi Anda tidak dapat menyangkal bahwa ketika Anda melihat kode seperti itu, Anda harus berhenti dulu (mungkin hanya sedetik) untuk memikirkan apa yang coba dilakukan.
Edgar Gonzalez
4
@ Edgar Gonzalez: Setuju, saya dengan tegas menentangnya dalam kode.
Rick Sladkey
3
Bab 19 dari Kode Selesaikan Edisi ke-2 (di bawah bagian "Ekspresi Boolean: Masalah Umum Dengan Ekspresi Boolean") sebenarnya merekomendasikan praktik ini untuk alasan yang tepat yang dinyatakan dalam banyak jawaban di sini: untuk mencegah penugasan dalam bahasa yang diturunkan dari bahasa C ketika perbandingan dimaksudkan .
CraigTP
4
Saya sering melihat ini disebut sebagai "Kondisi Yoda"
Brian

Jawaban:

84

Alasan utama untuk melakukan ini (disebut "Yoda conditional") adalah untuk mencegah kecelakaan di mana Anda secara tidak sengaja menggunakan operator penugasan ( =) alih-alih operator pembanding yang sama ( ==).

Yaitu, jika Anda melakukan kesalahan dengan melakukan:

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

Pernyataan ini akan dievaluasi untuk true(atau, dalam kasus beberapa bahasa — seperti PHP — nilai kebenaran) dan Anda akan memiliki bug yang sulit ditemukan.

Tetapi jika Anda melakukannya:

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

Anda akan menerima kesalahan fatal karena Anda tidak dapat menetapkan $foobilangan bulat.

Tetapi seperti yang Anda tunjukkan, membalik urutan biasanya membuat hal-hal menjadi kurang mudah dibaca. Jadi, banyak standar pengkodean (tetapi tidak semua, termasuk WordPress ) menyarankan atau mengharuskan $foo == 1terlepas dari manfaat bug berburu 1 == $foo.

Secara umum, saran saya adalah mengikuti standar pengkodean apa pun yang ada, jika ada: untuk WordPress, itu berarti menggunakan persyaratan Yoda.

Ketika tidak ada, dan tidak mungkin untuk membangun melalui konsensus dengan rekan-rekan Anda, itu pilihan dealer.

Attila
sumber
2
Saya ingat ketika mendesain bahasa (dahulu kala) yang secara khusus kami jadikan :=operator penugasan (dengan ==untuk uji kesetaraan) untuk menghindari masalah semacam ini.
Donal Fellows
7
Saya telah menulis banyak, banyak, baris kode, dan saya telah tidak pernah sengaja diketik =bukan ==. Perbedaannya sangat ditekankan di mana-mana sehingga saya tidak pernah membuat mereka bingung. Di sisi lain, saya telah membaca banyak potongan kode yang membingungkan atau sulit dipahami. Karena itu, saya akan menempatkan prioritas pada keterbacaan :). Apapun, jawaban yang bagus.
crazy2be
5
Namun alasan bagus lainnya untuk digunakan -Wall -Werroratau kompiler / juru bahasa Anda setara. Ada beberapa situasi di mana penugasan di dalam suatu kondisi benar, apalagi lebih mudah dibaca. Banyak bahasa bahkan tidak mengizinkannya.
Karl Bielefeldt
7
Pedantic: Sementara if($foo = 1)dievaluasi truedalam beberapa bahasa, dalam PHP itu dievaluasi menjadi 1 sebagai gantinya; if($foo = 20)dievaluasi menjadi 20; if($foo = 0)mengevaluasi ke 0, yang tidak seperti yang lain salah. Ini dapat menambahkan seluruh lapisan kompleksitas nother ke bug.
Charles
2
Sebenarnya, Standar Pengodean WordPress TIDAK membutuhkan Yoda Conditionals: codex.wordpress.org/WordPress_Coding_Standards#Yoda_Conditions
Tom Auger
13

Ini adalah mekanisme pengkodean defensif yang dimaksudkan untuk mencegah penggunaan yang tidak sengaja dari operator penugasan.

Pertimbangkan penyalahgunaan / kesalahan operator penugasan sebagai pengganti operator kesetaraan

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

Persyaratan di atas akan selalu kembali benar, tapi itu mungkin tidak apa yang dipikirkan oleh programmer asli. Pertimbangkan, di tempat itu, ini

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

Di sini, PHP (dan sebagian besar bahasa lain) akan menolak untuk dijalankan, karena tidak mungkin untuk menetapkan apa pun ke nilai tetap 1. Dengan mengkode semua pernyataan bersyarat dengan cara ini, Anda secara otomatis memastikan tidak ada penggunaan yang tidak disengaja dari operator penugasan dalam kondisi.

Alan Storm
sumber
9

Saya suka menggunakan konvensi itu di java untuk menghapus kemungkinan pengecualian null pointer. Jadi sesuatu seperti ini tidak akan menyebabkan masalah atau memerlukan kode tambahan:

String foo = null;

if ("bar".equals(foo))
{
    //Do something
}
Ben Newman
sumber
3
Saya suka ini, tapi saya benci idiom umum.
Thomas Eding
3
Jika nilai nol tidak valid pada saat itu dalam kode Anda harus sudah memeriksanya atau merancang kode Anda sedemikian rupa sehingga nilai nol tidak mungkin.
Ed S.
6
ini sepertinya cara mudah untuk menutupi masalah. Debu tidak dibersihkan dengan mengangkatnya ke dalam karpet.
Lie Ryan
0

Dalam praktiknya, banyak kompiler akan memberi Anda peringatan jika Anda menulis "if (x = 1)" alih-alih "if (x == 1)" karena kemungkinan besar kesalahan.

Dengan Dentang, Anda dapat menghindari peringatan dengan secara efektif memberi tahu kompiler "Saya bersungguh-sungguh, dan saya tahu apa yang saya lakukan", dan ini dilakukan dengan menulis "jika ((x = 1))". Perhatikan tanda kurung tambahan. Itu bekerja dalam situasi lain juga. if (false) statement; dapat memberi Anda peringatan bahwa pernyataan itu tidak pernah dieksekusi; if ((false)) statement; tidak memberi peringatan itu.

gnasher729
sumber
Saya sangat menyukainya! Saya menghindari idiom yang sepenuhnya sah dalam PHP karena saya selalu mendapat peringatan di IDE saya:if ($array = getSomething()){ // ..so something with $array }
Tom Auger