เรียนรู้แนวคิดนี้จาก Confident Ruby หนังสือ Ruby โปรด หากชอบบทความนี้ ควรซื้ออ่านทั้งเล่ม มี มาก อยู่ในนั้น
method current_user คืน User แตตอนไม่มี user คืน nil method search คืน Array ผลลัพธ์ แตมีผลลัพธ์เดียว คืนแค่ result นั้น ฟังดูสมเหตุสมผล สะดวก!
แตเร็วๆ นี้ 決策เหล่านี้จะฝังโค้ดใต้ภูเขา if statements อาจเป็น if kind_of? กระจายไปหมด หรือรู้สึกต้อง check nil ทุกที่ หรือแย่กว่า NoMethodErrors โผล่ตอน deploy feature ใหม่ ถึงเวลาอีก hotfix!
มีวิธีป้องกัน แค่ใส่ใจนิดหน่อย
The Robustness Principle
มีหลักการใน computing ว่า
Be conservative in what you do, be liberal in what you accept from others.
นำไปใช้กับ Ruby methods ได้ Methods ที่คุณเขียน ควรรับ input ที่สมเหตุสมผล และคืน output ตรงกัน
โฟกัสส่วนท้าย: ตอนใครเรียก method ที่คุณเขียน เขาควรรู้แน่ชัดว่าจะได้อะไรกลับมา
ใส่ใจ output ของคุณ
ดู Rails 2.1 ActiveRecord::Errors#on:
# File activerecord/lib/active_record/validations.rb, line 212
def on(attribute)
attribute = attribute.to_s
return nil unless @errors.has_key?(attribute)
errors = @errors[attribute].map(&:to_s)
errors.size == 1 ? errors.first : errors
endตอนเรียก อาจคืน Array ของ Strings, String, หรือ nil ขึ้นกับ caller ที่จะ understand จัดการ type ไหน นี่ bad idea:
Caller ต้องปนโค้ดเองด้วย type-checking รบกวน
Caller ต้องรู้ มาก เกี่ยว method ที่เรียก ต้องรู้ทุก type ที่อาจคืน และเมื่อไหร่คืน type ไหน
Edge cases ทดสอบมากขึ้น ต้องลองทั้ง 3 scenarios เพื่อเชื่อมั่น
Methods ควร consistent เกี่ยวกับสิ่งที่คืน ถ้าปกติคืน Array ทำให้ เสมอ คืน Array ถ้าปกติคืน User แตบางครั้ง nil สร้าง Null User object คืน มัน แทน nil
อาจ flexible กว่า: "คืน something ที่ include Taggable module" หรือ generic: "คืน something ที่มี id และ name attributes" สำคัญคือ consistency และ caller รู้คาดหวัง
jQuery ตัวอย่างน่าสนใจ jQuery methods ส่วนใหญ่คืน array-like object ชนิดเดียวกัน ทำให้ composable มาก ทำงานเยอะในบรรทัดเดียว
Rails แก้ method นี้ใน version ใหม่:
# File activemodel/lib/active_model/errors.rb, line 133
def [](attribute)
get(attribute.to_sym) || set(attribute.to_sym, [])
endตอนนี้คืน Array เสมอ 簡單สำหรับพวกเขา และเรา
กำจัด inconsistency
ครั้งหน้าที่คืน "Array หรือ nil" ให้คืน Array ดู codebase ที่ใช้ kind_of? และ respond_to? ลอง refactor methods ที่ถูกเรียก ให้คืน single type
ดู assumptions เกี่ยว return values ไหลผ่านโปรเจกต์ ลดความซับซ้อนโค้ดรอบๆ