คุณอาจเคยได้ยิน (หรือแม้แต่พูดกับตัวเอง) ว่า Rails / Ruby มีเวทย์มนตร์มากเกินไป…
- แต่ความคิดนั้นมาจากไหน?
- เวทมนตร์ของ Rails คืออะไรกันแน่?
- แล้วคุณจะทำอย่างไรเพื่อขจัดเวทมนตร์นั้นได้
นี่คือสิ่งที่ฉันคิด :
เมื่อบางอย่างรู้สึกเหมือนมีมนต์ขลัง นั่นก็เพราะมีบางอย่างที่คุณไม่รู้ จึงมีข้อมูลบางส่วนที่ขาดหายไป
ก็เหมือนกลลวง ถ้ารู้เคล็ดลับก็ไม่มีเวทมนตร์ .

ในการพัฒนาซอฟต์แวร์ การรู้เทคนิคนั้นเทียบเท่ากับการมีความเข้าใจว่าสิ่งต่างๆ ทำงานอย่างไร .
มาดูตัวอย่างกัน!
ตัวอย่างนี้เกี่ยวกับ BCrypt ซึ่งเป็นอัลกอริธึมการแฮชที่ใช้เก็บรหัสผ่านอย่างปลอดภัย มันถูกนำไปใช้ใน Ruby ผ่าน bcrypt พลอย
นี่คือวิธีใช้ BCrypt แฮชคำว่า “การทดสอบ”:
require 'bcrypt'BCrypt::Password.create("testing")# "$2a$10$3o.xrISG8fqKfzKqDpgKn.3cwjFV//9C9cZ7MuK5S9sNKFBivB7YG"BCrypt::Password.create("testing")# "$2a$ BFb/e3cWuAIyelcmkfGtE.GTifXHxig4IzVbdZs9C1zSpF/Jr6c3W"BCrypt::Password.create("กำลังทดสอบ")# "$2a$10$Q952BVgM783Y4kPvwvxwC.CS2DWUX6q2jQupreZoP"
สังเกตว่าคุณได้รับแฮชที่แตกต่างกันทุกครั้ง แต่ถ้าคุณใช้บางอย่างเช่น MD5 (อย่า!) หรือ SHA1 คุณจะได้รับผลลัพธ์เดียวกันสำหรับสตริงที่กำหนดเสมอ
ทำไม BCrypt ประพฤติตัวแตกต่างไปหรือไม่
ฉันจะอธิบายสิ่งที่เกิดขึ้นในอีกสักครู่ แต่ก่อนอื่น มาดูว่าคุณเปรียบเทียบ bcrypt สองรายการอย่างไร แฮช อันหนึ่งมาจากฐานข้อมูล &อันหนึ่งมาจากอินพุตของผู้ใช้ (เช่น แบบฟอร์มหรืออะไรทำนองนั้น)
BCrypt::Password.new(@user.hash) ==params[:password]# true
ส่วนทางด้านซ้าย (BCrypt::Password.new ) เป็น BCrypt ออบเจ็กต์ซึ่งรับแฮชที่เก็บไว้ในฐานข้อมูลเป็นพารามิเตอร์
ส่วนทางด้านขวา (params[:password] ) เป็นรหัสผ่านแบบข้อความธรรมดาที่ผู้ใช้พยายามเข้าสู่ระบบ
ในกรณีนี้ เราถือว่ามีการใช้รหัสผู้ใช้ / รหัสผ่านที่ถูกต้อง
เหตุใดจึงประเมินเป็น true ?
เพื่อให้เข้าใจสิ่งนี้ คุณต้องรู้สองสิ่ง:
- BCrypt ใช้สิ่งที่เรียกว่า “เกลือ” ซึ่งเป็น ค่าสุ่มที่ใช้เพื่อเพิ่มความปลอดภัย เทียบกับแฮชที่คำนวณไว้ล่วงหน้า เกลือจะถูกเก็บไว้ในแฮชเอง
- ใน Ruby หลายๆ อย่างที่ดูเหมือนวากยสัมพันธ์เป็นเพียงเมธอด . นี่เป็นกรณีของโอเปอเรเตอร์ double equals (
== )
รู้แล้วบอกได้เลยว่า BCrypt กำหนด == . ของตัวเอง ซึ่งรู้วิธีดึงค่า “เกลือ” นั้นมาพิจารณาเมื่อเปรียบเทียบรหัสผ่าน
กล่าวอีกนัยหนึ่ง :
BCrypt#== รับค่า "เกลือ" จากแฮชที่เก็บไว้
จากนั้นแฮชรหัสผ่านแบบข้อความธรรมดา (อินพุตของผู้ใช้) โดยใช้เกลือนี้ เพื่อให้แฮชทั้งสองจะเหมือนกันหากรหัสผ่านถูกต้อง
หากคุณต้อง ดูซอร์สโค้ด มันจะมีลักษณะดังนี้:
def ==(secret) super( BCrypt::Engine.hash_secret(secret, @salt) ) สิ้นสุด
จำไว้ว่า super จะเรียกวิธีการเดียวกัน (ในกรณีนี้ == ) ในชั้นเรียนหลัก
คลาสหลักของ BCrypt::Password คือ String .
มันเป็นเรื่องของวิธีการ
สิ่งสำคัญอย่างหนึ่งที่ต้องทำความเข้าใจคือ นอกจากคีย์เวิร์ดสองสามคำและองค์ประกอบทางไวยากรณ์บางส่วน (เช่น วงเล็บ) ทั้งหมดเกี่ยวกับคลาสและเมธอด
หากคุณรู้ว่าคุณกำลังทำงานกับชั้นเรียนใด (ซึ่งคุณสามารถตรวจสอบได้โดยใช้ class method) คุณจะสามารถทราบได้เสมอว่ามีการดำเนินการ (วิธีการ) ใดบ้าง
แต่บางครั้งเราก็มีการเรียกใช้เมธอดโดยไม่มีอ็อบเจ็กต์
ซึ่งมักจะหมายถึงวิธีการที่กำหนดไว้ในคลาสปัจจุบัน แต่ก็ไม่เป็นเช่นนั้นเสมอไป
ตัวอย่าง :
ใส่ 123
puts . อยู่ที่ไหน กำหนด? มาดูกัน:
method(:puts).owner# Kernel
อีกสิ่งหนึ่งที่อาจสร้างความสับสนคือ metaprogramming เพราะด้วย metaprogramming คุณสามารถสร้าง แก้ไข หรือแม้แต่ลบวิธีการระหว่างการทำงานของโปรแกรม สิ่งเหล่านี้ทำให้โค้ดมีความทึบและคลุมเครือมากขึ้น
คุณลดความสับสนได้ด้วยการรู้ว่าเมตาโปรแกรมมิ่งมีวิธีการใดและทำงานอย่างไร
สรุป
คุณได้เรียนรู้ว่าความเข้าใจอย่างลึกซึ้งเกี่ยวกับวิธีการทำงานของสิ่งต่างๆ สามารถช่วยขจัด "เวทมนตร์" ใดๆ เขียนโค้ดได้ดีขึ้น และทำให้คุณเป็นนักพัฒนาที่ดีขึ้นได้อย่างไร
หากคุณต้องการพัฒนาทักษะ Ruby ลองดูหนังสือ Ruby Deep Dive ของฉัน ซึ่งออกแบบมาเพื่อเชื่อมช่องว่างระหว่างพื้นฐานและแนวคิดขั้นสูง 🙂