Ruby: if variable vs if variable.nil?

11

Saya baru di Ruby dan saya terkejut ketika saya mengetahui bahwa semua objek benar selain nil dan salah. Bahkan 0 adalah benar.

Yang menyenangkan tentang properti bahasa itu adalah Anda dapat menulis:

if !variable
  # do stuff when variable is nil
end

Rekan-rekan saya, yang lebih berpengalaman sebagai pengembang Ruby, bersikeras saya harus memilih itu daripada menggunakan .nil? seperti itu:

if variable.nil?
  # do stuff when variable is nil
end

Namun saya percaya bahwa yang terakhir adalah pilihan yang lebih baik karena dua alasan: 1. Saya pikir itu lebih berorientasi objek, terutama dalam bahasa seperti Ruby di mana semuanya adalah objek dan pertukaran pesan. 2. Ini lebih mudah dibaca, menurut pendapat subjek saya, bahkan jika itu kurang kompak.

Apakah saya membuat kesalahan "pemula" di sini?

Javier Holguera
sumber
4
Apakah Anda menguji nol? atau nilai yang salah?
Saya sedang menguji nol. Pada dasarnya jika variabelnya nol, saya melakukan sesuatu (atau tidak)
Javier Holguera
3
Jika Anda menguji untuk nil, mengapa Anda ingin tes untuk false juga memasuki blok itu?
Setuju, saya menunjukkan itu sebagai alasan lain untuk memilih. Tetapi mereka bersikeras bahwa "jika variabel do x" lebih idiomatis daripada "jika variable.nil? Do x" dan lebih disukai ketika Anda tahu bahwa variabel tidak boolean
Javier Holguera

Jawaban:

17

Tulis apa yang Anda maksud. Berarti apa yang Anda tulis.

Mari kita ambil tes yang berbeda. .vowel?

if char == 'a'
   # do stuff
end

vs.

if char.vowel?
   # do stuff
end

Sekarang, sudah jelas bahwa ini tidak melakukan hal yang sama. Tapi jika Anda hanya mengharapkan charuntuk menjadi aatau bia akan bekerja. Tapi itu akan membingungkan pengembang berikutnya - blok kedua akan dimasukkan ke dalam kondisi di mana char [eiou]juga. Tetapi untuk a, itu akan bekerja dengan benar.

Ya, inilah masalahnya nildan falsemerupakan satu-satunya nilai falsy di Ruby. Namun, jika Anda menguji nildengan menguji nil || false, ini bukan yang Anda maksud.

Ini berarti bahwa pengembang berikutnya (yang kebetulan adalah pembunuh kapak gila yang mengetahui alamat rumah Anda) akan membaca kode, dan bertanya-tanya mengapa falseharus masuk ke sana juga.

Menulis kode yang menyampaikan persis apa yang Anda maksud.

Per Lundberg
sumber
3

Pertimbangkan yang berikut ini:

response = responses.to_a.first

Ini akan mengembalikan elemen pertama responses, atau nil. Kemudian karena pernyataan bersyarat berlaku nilseperti yang falsedapat kita tulis:

response = responses.to_a.first
if response
  # do something ('happy path')
else
  # do something else
end

Yang lebih mudah dibaca daripada:

if response.nil?
  # do something else
else
  # do something ('happy path')
end

The if (object)Pola ini sangat umum dalam kode Ruby. Ini juga mengarah dengan baik ke refactoring, misalnya:

if response = responses.to_a.first
  do_something_with(response)
else
  # response is equal to nil
end

Ingat juga bahwa metode Ruby kembali nilsecara default. Begitu:

def initial_response
  if @condition
    @responses.to_a.first
  else
    nil
  end
end

dapat disederhanakan untuk:

def initial_response
  if @condition
    @responses.to_a.first
  end
end

Jadi kami dapat melanjutkan refactor:

if response = initial_response
  do_something_with(response)
else
  # response is equal to nil
end

Sekarang Anda dapat berpendapat bahwa kembali niltidak selalu merupakan ide terbaik, karena itu berarti memeriksa di nilmana - mana. Tapi itu adalah ketel ikan. Mengingat bahwa pengujian untuk objek "ada atau tidaknya" adalah persyaratan yang sering, kebenaran objek adalah aspek yang berguna dari Ruby, meskipun mengejutkan bagi pendatang baru ke bahasa.

zetetik
sumber
2

Tidak hanya if variable.nil?dibaca lebih seperti bahasa alami, itu juga melindungi terhadap seorang programmer yang secara tidak sengaja memberikan falsenilai dan jatuh ke dalam ifpernyataan Anda , karena Ruby adalah bahasa yang diketik secara longgar.

Greg Burghardt
sumber
1
Jadi komentar awal dalam pertanyaan awal salah? Seharusnya "melakukan hal-hal ketika variabel nil atau salah"? Dan karena kode yang tidak cocok dengan komentar adalah bug, langsung ada bug?
gnasher729
Benar. Tes kebenaran sederhana dapat menyebabkan kesalahan logika.
Greg Burghardt
0

Secara idiomatis, unless variablelebih disukai daripada if !variable. ifPernyataan yang dinegasikan sering dianggap sebagai bau kode karena lebih mudah untuk melewatkan negasi ketika membaca sekilas.

Gambaran yang lebih besar di sini adalah melakukan nilpengecekan seperti ini juga sedikit bau kode. Untuk OO yang tepat, bertujuan untuk menggunakan pola objek nol sehingga pemeriksaan semacam ini tidak pernah diperlukan. http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/

Katakan objek apa yang harus dilakukan, jangan tanya mereka apa itu. Ini kadang-kadang dikenal sebagai kirim jangan tanya

Matt Gibson
sumber