Ruby: if variable vs if variable.nil?


11

ฉันใหม่กับทับทิมและฉันรู้สึกประหลาดใจเมื่อฉันพบว่าวัตถุทั้งหมดเป็นจริงนอกเหนือจากศูนย์และเท็จ แม้แต่ 0 ก็จริง

สิ่งที่ดีเกี่ยวกับคุณสมบัติของภาษานั้นคือคุณสามารถเขียน:

if !variable
  # do stuff when variable is nil
end

เพื่อนร่วมงานของฉันซึ่งเป็นนักพัฒนาทับทิมรุ่นเก๋ามากขึ้นยืนยันว่าฉันควรเลือกสิ่งนั้นแทนที่จะใช้. ชอบมาก:

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

อย่างไรก็ตามฉันเชื่อว่าอันหลังเป็นตัวเลือกที่ดีกว่าด้วยเหตุผลสองประการ: 1. ฉันคิดว่ามันเป็นเชิงวัตถุมากกว่าโดยเฉพาะในภาษาอย่าง Ruby ซึ่งทุกอย่างเป็นการแลกเปลี่ยนวัตถุและข้อความ 2. มันสามารถอ่านได้มากขึ้นในความเห็นของฉันแม้ว่าจะมีขนาดเล็กลงก็ตาม

ฉันกำลังทำผิดพลาด "มือใหม่" ที่นี่?


4
คุณกำลังทดสอบศูนย์หรือไม่ หรือค่าเท็จ

ฉันกำลังทดสอบหาศูนย์ โดยทั่วไปถ้าตัวแปรเป็นศูนย์ที่ฉันทำบางสิ่งบางอย่าง (หรือไม่)
ฮาเวียร์ Holguera

3
หากคุณกำลังทดสอบไม่มีศูนย์ทำไมคุณต้องการให้การทดสอบเป็นเท็จเพื่อป้อนบล็อกนั้นด้วย

เห็นด้วยฉันชี้ให้เห็นว่าเป็นอีกเหตุผลหนึ่งที่จะชอบ. แต่พวกเขายืนยันว่า "if variable do x" เป็นสำนวนที่มากกว่า "if variable.nil? do x" และดีกว่าเมื่อคุณรู้ว่าตัวแปรนั้นไม่ใช่บูลีน
Javier Holguera

คำตอบ:


17

เขียนสิ่งที่คุณหมายถึง หมายถึงสิ่งที่คุณเขียน

ลองทำแบบทดสอบอื่นดู .vowel?

if char == 'a'
   # do stuff
end

VS

if char.vowel?
   # do stuff
end

ตอนนี้มันชัดเจนว่าสิ่งเหล่านี้ไม่ได้ทำสิ่งเดียวกัน แต่ถ้าคุณคาดหวังว่าcharจะเป็นaหรือbมันจะทำงาน แต่มันจะสร้างความสับสนให้กับนักพัฒนาคนต่อไป - บล็อกที่สองจะถูกป้อนเข้าสู่เงื่อนไขที่ตัวละคร[eiou]ยังเป็น แต่aมันจะทำงานได้อย่างถูกต้อง

ใช่เป็นกรณีนั้นnilและfalseเป็นเพียงค่าเท็จใน Ruby อย่างไรก็ตามหากคุณกำลังทำการทดสอบnilโดยการทดสอบnil || falseสิ่งนี้ไม่ได้หมายความว่าคุณต้องการ

หมายความว่าผู้พัฒนารายต่อไป (ซึ่งเป็นฆาตกรขวานบ้าที่รู้ที่อยู่บ้านของคุณ) จะอ่านรหัสและสงสัยว่าทำไมfalseต้องเข้าไปที่นั่นด้วย

เขียนรหัสที่บ่งบอกว่าคุณหมายถึงอะไร


3

พิจารณาสิ่งต่อไปนี้:

response = responses.to_a.first

นี้จะกลับองค์ประกอบแรกของหรือresponses nilจากนั้นเนื่องจากข้อความสั่งแบบมีเงื่อนไขปฏิบัติnilตามที่falseเราเขียนได้:

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

ซึ่งอ่านได้มากกว่า:

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

if (object)รูปแบบเป็นเรื่องธรรมดามากในรหัสทับทิม นอกจากนี้ยังนำไปสู่การ refactoring เช่น:

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

โปรดจำไว้ว่าวิธีการส่งคืนทับทิมเป็นnilค่าเริ่มต้น ดังนั้น:

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

สามารถทำให้เป็น:

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

ดังนั้นเราสามารถ refactor เพิ่มเติม:

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

ตอนนี้คุณสามารถยืนยันว่าการกลับมาnilไม่ใช่ความคิดที่ดีที่สุดเสมอไปเพราะมันหมายถึงการตรวจสอบnilทุกที่ แต่นั่นก็เป็นอีกหนึ่งกาต้มน้ำของปลา จากการทดสอบว่า "การมีอยู่หรือขาด" ของวัตถุนั้นเป็นสิ่งที่ต้องการบ่อยความจริงของวัตถุนั้นเป็นประโยชน์อย่างหนึ่งของทับทิมแม้ว่าจะเป็นเรื่องแปลกสำหรับผู้มาใหม่ในภาษา


2

ไม่เพียง แต่if variable.nil?อ่านได้เหมือนภาษาธรรมชาติเท่านั้น แต่ยังป้องกันโปรแกรมเมอร์ที่ตั้งใจกำหนดfalseค่าและตกหลุมifคำสั่งของคุณเนื่องจาก Ruby เป็นภาษาที่พิมพ์อย่างหลวม ๆ


1
ดังนั้นความคิดเห็นเริ่มต้นในคำถามเดิมจึงผิด ควรจะ "ทำสิ่งต่าง ๆ เมื่อตัวแปรเป็นศูนย์หรือเท็จ"? และเนื่องจากรหัสที่ไม่ตรงกับความคิดเห็นเป็นข้อผิดพลาดมีข้อบกพร่องทันทีหรือไม่
gnasher729

แก้ไข. การทดสอบความจริงง่าย ๆ สามารถแนะนำข้อผิดพลาดเชิงตรรกะ
Greg Burghardt

0

idiomatically, เป็นที่นิยมunless variable ข้อความif !variableเมื่อตะกี้ifมักจะถูกพิจารณาว่าเป็นกลิ่นของรหัสเพราะง่ายกว่าที่จะคิดถึงการปฏิเสธเมื่ออ่าน

ภาพใหญ่ขึ้นที่นี่คือการnilตรวจสอบการทำเช่นนี้เป็นกลิ่นรหัสเล็กน้อย สำหรับ OO ที่เหมาะสมมุ่งหวังที่จะใช้รูปแบบวัตถุ null เพื่อให้การตรวจสอบประเภทนี้ไม่จำเป็น http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/

บอกวัตถุว่าจะทำอย่างไรอย่าถามพวกเขาว่าพวกเขาทำอะไร บางครั้งนี้เป็นที่รู้จักกันในนามบอกอย่าถาม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.