รหัส Buggy Rails: 10 ข้อผิดพลาดที่พบบ่อยที่สุดที่นักพัฒนา Rails ทำ
เผยแพร่แล้ว: 2022-03-11Ruby on Rails (“Rails”) เป็นเฟรมเวิร์กโอเพ่นซอร์สยอดนิยม โดยอิงจากภาษาการเขียนโปรแกรม Ruby ที่พยายามทำให้กระบวนการพัฒนาเว็บแอปพลิเคชันง่ายขึ้นและคล่องตัว
Rails สร้างขึ้นบนหลักการของการประชุมเกี่ยวกับการกำหนดค่า พูดง่ายๆ ก็คือ ตามค่าเริ่มต้น Rails ถือว่านักพัฒนาที่เชี่ยวชาญจะปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุด "มาตรฐาน" (สำหรับสิ่งต่างๆ เช่น การตั้งชื่อ โครงสร้างโค้ด และอื่นๆ) และหากคุณทำเช่นนั้น สิ่งต่างๆ ก็จะทำงานให้คุณ "อัตโนมัติ" - อย่างน่าอัศจรรย์” โดยที่คุณไม่ต้องระบุรายละเอียดเหล่านี้ แม้ว่ากระบวนทัศน์นี้มีข้อดี แต่ก็ไม่ได้ไม่มีข้อผิดพลาดเช่นกัน สิ่งที่น่าสังเกตมากที่สุดคือ "เวทย์มนตร์" ที่เกิดขึ้นเบื้องหลังในเฟรมเวิร์กบางครั้งอาจนำไปสู่การเข้าใจผิด ความสับสน และ "เกิดอะไรขึ้น" ประเภทของปัญหา นอกจากนี้ยังอาจมีการแตกสาขาที่ไม่พึงประสงค์เกี่ยวกับความปลอดภัยและประสิทธิภาพ
ดังนั้น แม้ว่า Rails จะใช้งานง่าย แต่ก็ไม่ยากที่จะนำไปใช้ในทางที่ผิด บทช่วยสอนนี้จะกล่าวถึงปัญหาทั่วไปของ Rails 10 ประการ รวมถึงวิธีหลีกเลี่ยงปัญหาเหล่านี้และปัญหาที่เกิดขึ้น
ข้อผิดพลาดทั่วไป #1: ใส่ตรรกะมากเกินไปในคอนโทรลเลอร์
Rails ใช้สถาปัตยกรรม MVC ในชุมชน Rails เราได้พูดถึงโมเดลอ้วน ตัวควบคุมแบบบางมาระยะหนึ่งแล้ว แต่แอปพลิเคชั่น Rails ล่าสุดหลายตัวที่ฉันสืบทอดมานั้นละเมิดหลักการนี้ ทั้งหมดนั้นง่ายเกินไปที่จะย้ายตรรกะการดู (ซึ่งดีกว่าอยู่ในตัวช่วย) หรือตรรกะของโดเมน/รุ่น ไปยังตัวควบคุม
ปัญหาคืออ็อบเจ็กต์ตัวควบคุมจะเริ่มละเมิดหลักการความรับผิดชอบเดียว ทำให้การเปลี่ยนแปลงในอนาคตกับฐานโค้ดทำได้ยากและเกิดข้อผิดพลาดได้ง่าย โดยทั่วไป ตรรกะประเภท เดียว ที่คุณควรมีในคอนโทรลเลอร์คือ:
- การจัดการเซสชันและคุกกี้ ซึ่งอาจรวมถึงการตรวจสอบสิทธิ์/การให้สิทธิ์หรือการประมวลผลคุกกี้เพิ่มเติมใดๆ ที่คุณต้องทำ
- การเลือกรุ่น ตรรกะในการค้นหาโมเดลวัตถุที่ถูกต้องตามพารามิเตอร์ที่ส่งผ่านมาจากคำขอ ตามหลักการแล้ว นี่ควรเป็นการเรียกไปยังเมธอด find เดียวโดยตั้งค่าตัวแปรอินสแตนซ์เพื่อใช้ในภายหลังเพื่อแสดงการตอบสนอง
- ขอการจัดการพารามิเตอร์ รวบรวมพารามิเตอร์คำขอและเรียกใช้เมธอดโมเดลที่เหมาะสมเพื่อคงไว้
- การแสดงผล/เปลี่ยนเส้นทาง แสดงผล (html, xml, json เป็นต้น) หรือเปลี่ยนเส้นทางตามความเหมาะสม
แม้ว่าสิ่งนี้จะยังผลักดันขีดจำกัดของหลักการความรับผิดชอบเดียว แต่มันก็เป็นขั้นต่ำที่เฟรมเวิร์กของ Rails กำหนดให้เราต้องมีในคอนโทรลเลอร์
ข้อผิดพลาดทั่วไป #2: ใส่ตรรกะมากเกินไปในมุมมอง
ERB เอ็นจิ้นการสร้างเทมเพลต Rails ที่พร้อมใช้งานทันที เป็นวิธีที่ยอดเยี่ยมในการสร้างเพจที่มีเนื้อหาตัวแปร อย่างไรก็ตาม ถ้าคุณไม่ระวัง ไม่นานคุณก็จะได้ไฟล์ขนาดใหญ่ที่มีโค้ด HTML และ Ruby ผสมกันซึ่งยากต่อการจัดการและบำรุงรักษา นอกจากนี้ยังเป็นพื้นที่ที่สามารถนำไปสู่การทำซ้ำจำนวนมากซึ่งนำไปสู่การละเมิดหลักการ DRY (อย่าทำซ้ำตัวเอง)
สิ่งนี้สามารถแสดงออกได้หลายวิธี หนึ่งคือการใช้ตรรกะแบบมีเงื่อนไขมากเกินไปในมุมมอง เป็นตัวอย่างง่ายๆ ให้พิจารณากรณีที่เรามีเมธอด current_user
ที่ส่งคืนผู้ใช้ที่ล็อกอินอยู่ในปัจจุบัน มักจะจบลงด้วยโครงสร้างตรรกะแบบมีเงื่อนไขเช่นนี้ในไฟล์มุมมอง:
<h3> Welcome, <% if current_user %> <%= current_user.name %> <% else %> Guest <% end %> </h3>
วิธีที่ดีกว่าในการจัดการสิ่งนี้คือทำให้แน่ใจว่าอ็อบเจกต์ที่ส่งคืนโดย current_user
นั้นได้รับการตั้งค่า เสมอ ไม่ว่าจะมีคนล็อกอินหรือไม่ และมันจะตอบเมธอดที่ใช้ในมุมมองด้วยวิธีที่เหมาะสม (บางครั้งเรียกว่า null วัตถุ). ตัวอย่างเช่น คุณอาจกำหนดตัวช่วย current_user
ใน app/controllers/application_controller
ดังนี้:
require 'ostruct' helper_method :current_user def current_user @current_user ||= User.find session[:user_id] if session[:user_id] if @current_user @current_user else OpenStruct.new(name: 'Guest') end end
ซึ่งจะทำให้คุณสามารถแทนที่ตัวอย่างโค้ดการดูก่อนหน้าด้วยโค้ดง่ายๆ หนึ่งบรรทัดนี้:
<h3>Welcome, <%= current_user.name -%></h3>
แนวทางปฏิบัติที่ดีที่สุดของ Rails ที่แนะนำเพิ่มเติมสองสามข้อ:
- ใช้เค้าโครงมุมมองและบางส่วนอย่างเหมาะสมเพื่อสรุปสิ่งที่ทำซ้ำบนหน้าเว็บของคุณ
- ใช้ผู้นำเสนอ/นักตกแต่ง เช่น Draper gem เพื่อสรุปตรรกะการสร้างมุมมองในวัตถุ Ruby จากนั้นคุณสามารถเพิ่มวิธีการลงในวัตถุนี้เพื่อดำเนินการทางตรรกะที่คุณอาจใส่ไว้ในโค้ดมุมมองของคุณ
ข้อผิดพลาดทั่วไป #3: ใส่ตรรกะมากเกินไปในแบบจำลอง
จากคำแนะนำในการลดตรรกะในมุมมองและตัวควบคุม ที่เดียวที่เหลืออยู่ในสถาปัตยกรรม MVC ที่จะนำตรรกะทั้งหมดนั้นมาไว้ในโมเดล ใช่ไหม
ก็ไม่เชิง
นักพัฒนา Rails หลายคนทำผิดพลาดจริง ๆ และจบลงด้วยการยึดทุกอย่างในคลาสโมเดล ActiveRecord
ของพวกเขาที่นำไปสู่ไฟล์ mongo ที่ไม่เพียงละเมิดหลักการความรับผิดชอบเดียว แต่ยังเป็นฝันร้ายในการบำรุงรักษาอีกด้วย
ฟังก์ชันต่างๆ เช่น การสร้างการแจ้งเตือนทางอีเมล การเชื่อมต่อกับบริการภายนอก การแปลงเป็นรูปแบบข้อมูลอื่นๆ และอื่นๆ ในทำนองเดียวกัน ไม่ได้เกี่ยวข้องกับความรับผิดชอบหลักของโมเดล ActiveRecord
มากนัก ซึ่งควรทำมากกว่าการค้นหาและรักษาข้อมูลในฐานข้อมูลเพียงเล็กน้อย
ดังนั้น ถ้าตรรกะไม่ควรไปในมุมมอง และไม่ควรไปในตัวควบคุม และไม่ควรไปในแบบจำลอง แล้ว มันควรไปที่ไหน
ป้อนวัตถุ Ruby เก่าธรรมดา (PORO) ด้วยเฟรมเวิร์กที่ครอบคลุมอย่าง Rails นักพัฒนารุ่นใหม่ๆ มักไม่เต็มใจที่จะสร้างคลาสของตนเองนอกเฟรมเวิร์ก อย่างไรก็ตาม การย้ายตรรกะออกจากแบบจำลองไปยัง PORO มักจะเป็นสิ่งที่แพทย์สั่งเพื่อหลีกเลี่ยงแบบจำลองที่ซับซ้อนมากเกินไป ด้วย PORO คุณสามารถสรุปสิ่งต่าง ๆ เช่น การแจ้งเตือนทางอีเมลหรือการโต้ตอบ API ลงในคลาสของตนเอง แทนที่จะรวมเข้ากับโมเดล ActiveRecord
ด้วยเหตุนี้ โดยทั่วไปแล้ว ตรรกะเดียวที่ควรคงอยู่ในแบบจำลองของคุณคือ:
- การกำหนดค่า
ActiveRecord
(เช่น ความสัมพันธ์และการตรวจสอบ) - วิธีการกลายพันธุ์อย่างง่าย เพื่อสรุปการอัพเดตแอตทริบิวต์จำนวนหนึ่งและบันทึกไว้ในฐานข้อมูล
- เข้าถึง wrappers เพื่อซ่อนข้อมูลโมเดลภายใน (เช่น วิธี
full_name
ที่รวมฟิลด์first_name
และlast_name
ในฐานข้อมูล) - ข้อความค้นหาที่ซับซ้อน (กล่าวคือ ซับซ้อนกว่าการ
find
ทั่วไป ); โดยทั่วไปแล้ว คุณไม่ควรใช้วิธีwhere
หรือวิธีการสร้างแบบสอบถามอื่น ๆ เช่น นอกคลาสโมเดลเอง
ข้อผิดพลาดทั่วไป #4: การใช้คลาสตัวช่วยทั่วไปเป็นพื้นทิ้ง
ข้อผิดพลาดนี้เป็นผลสืบเนื่องมาจากความผิดพลาด #3 ด้านบน ตามที่กล่าวไว้ เฟรมเวิร์ก Rails ให้ความสำคัญกับองค์ประกอบที่มีชื่อ (เช่น โมเดล มุมมอง และคอนโทรลเลอร์) ของเฟรมเวิร์ก MVC มีคำจำกัดความที่ดีพอสมควรเกี่ยวกับประเภทของสิ่งต่าง ๆ ที่อยู่ในคลาสของแต่ละองค์ประกอบเหล่านี้ แต่บางครั้งเราอาจต้องการวิธีการที่ดูเหมือนจะไม่เข้ากับทั้งสามอย่าง
ตัวสร้าง Rails สร้างไดเร็กทอรีตัวช่วยและคลาสตัวช่วยใหม่อย่างสะดวกเพื่อใช้กับทรัพยากรใหม่แต่ละรายการที่เราสร้างขึ้น อย่างไรก็ตาม กลายเป็นสิ่งที่น่าดึงดูดใจเกินกว่าที่จะเริ่มยัดฟังก์ชันการทำงานใดๆ ที่ไม่เข้ากับโมเดล มุมมอง หรือคอนโทรลเลอร์อย่างเป็นทางการในคลาสตัวช่วยเหล่านี้
แม้ว่า Rails จะเน้นที่ MVC เป็นหลัก แต่ก็ไม่มีอะไรจะป้องกันคุณจากการสร้างประเภทคลาสของคุณเองและเพิ่มไดเร็กทอรีที่เหมาะสมเพื่อเก็บโค้ดสำหรับคลาสเหล่านั้น เมื่อคุณมีฟังก์ชันการทำงานเพิ่มเติม ให้นึกถึงเมธอดที่รวมกลุ่มเข้าด้วยกัน และค้นหาชื่อที่ดีสำหรับคลาสที่มีเมธอดเหล่านั้น การใช้เฟรมเวิร์กที่ครอบคลุมอย่าง Rails ไม่ใช่ข้ออ้างที่จะปล่อยให้แนวทางปฏิบัติที่ดีในการออกแบบเชิงวัตถุที่ดีหลุดมือไป
ข้อผิดพลาดทั่วไป #5: ใช้อัญมณีมากเกินไป
Ruby and Rails ได้รับการสนับสนุนโดยระบบนิเวศของอัญมณีที่รวบรวมความสามารถทุกอย่างที่นักพัฒนาสามารถคิดได้ นี่เป็นสิ่งที่ดีสำหรับการสร้างแอปพลิเคชันที่ซับซ้อนอย่างรวดเร็ว แต่ฉันได้เห็นแอปพลิเคชันที่บวมจำนวนมากซึ่งจำนวนอัญมณีใน Gemfile
ของแอปพลิเคชันนั้นใหญ่เกินสัดส่วนเมื่อเทียบกับฟังก์ชันที่มีให้
สิ่งนี้ทำให้เกิดปัญหา Rails หลายประการ การใช้อัญมณีมากเกินไปทำให้ขนาดของกระบวนการ Rails มีขนาดใหญ่กว่าที่ควรจะเป็น ซึ่งจะทำให้ประสิทธิภาพในการผลิตลดลง นอกเหนือจากความหงุดหงิดของผู้ใช้แล้ว ยังส่งผลให้ต้องกำหนดค่าหน่วยความจำเซิร์ฟเวอร์ที่ใหญ่ขึ้นและค่าใช้จ่ายในการดำเนินการเพิ่มขึ้น นอกจากนี้ยังใช้เวลานานขึ้นในการเริ่มแอปพลิเคชัน Rails ที่ใหญ่ขึ้น ซึ่งทำให้การพัฒนาช้าลงและทำให้การทดสอบอัตโนมัติใช้เวลานานขึ้น (และตามกฎแล้ว การทดสอบที่ช้ามักไม่ทำงานบ่อยนัก)
พึงระลึกไว้เสมอว่าอัญมณีแต่ละเม็ดที่คุณนำเข้ามาในแอปพลิเคชันของคุณอาจมีการพึ่งพาอัญมณีอื่น ๆ และในทางกลับกันก็อาจมีการพึ่งพาอัญมณีอื่น ๆ เป็นต้น การเพิ่มอัญมณีอื่น ๆ สามารถมีผลทบต้นได้ ตัวอย่างเช่น การเพิ่ม rails_admin
gem จะทำให้มีอัญมณีเพิ่มขึ้นอีก 11 เม็ด เพิ่มขึ้นมากกว่า 10% จากการติดตั้ง Rails พื้นฐาน
ในขณะที่เขียนนี้ การติดตั้ง Rails 4.1.0 ใหม่รวมถึง 43 gem ในไฟล์ Gemfile.lock
เห็นได้ชัดว่านี่เป็นมากกว่าที่รวมอยู่ใน Gemfile
และแสดงถึงอัญมณีทั้งหมดที่อัญมณี Rails มาตรฐานจำนวนหนึ่งนำมาเป็นการอ้างอิง
พิจารณาอย่างรอบคอบว่าค่าใช้จ่ายส่วนเกินนั้นคุ้มค่าหรือไม่เมื่อคุณเพิ่มอัญมณีแต่ละเม็ด ตัวอย่างเช่น นักพัฒนามักจะเพิ่ม rails_admin
gem เพราะมันมีเว็บฟรอนต์เอนด์ที่ดีให้กับโครงสร้างโมเดล แต่จริงๆ แล้วมันไม่ได้เป็นมากกว่าเครื่องมือเรียกดูฐานข้อมูลแฟนซี แม้ว่าแอปพลิเคชันของคุณต้องการผู้ดูแลระบบที่มีสิทธิ์เพิ่มเติม คุณอาจไม่ต้องการให้สิทธิ์เข้าถึงฐานข้อมูลดิบแก่พวกเขา และคุณจะได้รับบริการที่ดีกว่าโดยการพัฒนาฟังก์ชันการดูแลระบบของคุณเองที่คล่องตัวมากกว่าการเพิ่มอัญมณีนี้
ข้อผิดพลาดทั่วไป #6: ละเว้นไฟล์บันทึกของคุณ
แม้ว่านักพัฒนา Rails ส่วนใหญ่จะทราบถึงล็อกไฟล์เริ่มต้นที่มีอยู่ระหว่างการพัฒนาและในเวอร์ชันที่ใช้งานจริง พวกเขามักจะไม่ใส่ใจกับข้อมูลในไฟล์เหล่านั้นมากพอ แม้ว่าแอปพลิเคชั่นจำนวนมากจะใช้เครื่องมือตรวจสอบบันทึก เช่น Honeybadger หรือ New Relic ในการผลิต สิ่งสำคัญคือต้องคอยดูไฟล์บันทึกของคุณตลอดกระบวนการพัฒนาและทดสอบแอปพลิเคชันของคุณ
ดังที่ได้กล่าวไว้ก่อนหน้านี้ในบทช่วยสอนนี้ เฟรมเวิร์กของ Rails จะสร้าง “เวทย์มนตร์” ให้คุณโดยเฉพาะในโมเดล การกำหนดความสัมพันธ์ในแบบจำลองของคุณทำให้ง่ายต่อการดึงความสัมพันธ์และมีทุกอย่างพร้อมสำหรับมุมมองของคุณ SQL ทั้งหมดที่จำเป็นในการเติมวัตถุแบบจำลองของคุณจะถูกสร้างขึ้นสำหรับคุณ ที่ที่ดี แต่คุณรู้ได้อย่างไรว่า SQL ที่สร้างขึ้นนั้นมีประสิทธิภาพ?

ตัวอย่างหนึ่งที่คุณมักจะพบคือปัญหาการสืบค้น N+1 แม้ว่าปัญหาจะเป็นที่เข้าใจกันดีอยู่แล้ว แต่วิธีเดียวที่จะสังเกตสิ่งที่เกิดขึ้นได้จริงคือตรวจสอบการสืบค้น SQL ในไฟล์บันทึกของคุณ
ตัวอย่างเช่น คุณมีข้อความค้นหาต่อไปนี้ในแอปพลิเคชันบล็อกทั่วไป ซึ่งจะแสดงข้อคิดเห็นทั้งหมดสำหรับชุดโพสต์ที่เลือก:
def comments_for_top_three_posts posts = Post.limit(3) posts.flat_map do |post| post.comments.to_a end end
เมื่อเราดูที่ล็อกไฟล์ของคำขอที่เรียกใช้เมธอดนี้ เราจะเห็นสิ่งต่อไปนี้ โดยที่เคียวรีเดียวถูกสร้างขึ้นเพื่อรับออบเจกต์โพสต์สามรายการ จากนั้นจึงสร้างการสืบค้นอีกสามรายการเพื่อรับความคิดเห็นของออบเจ็กต์แต่ละรายการ:
Started GET "/posts/some_comments" for 127.0.0.1 at 2014-05-20 20:05:13 -0700 Processing by PostsController#some_comments as HTML Post Load (0.4ms) SELECT "posts".* FROM "posts" LIMIT 3 Comment Load (5.6ms) ELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 1]] Comment Load (0.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 2]] Comment Load (1.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 3]] Rendered posts/some_comments.html.erb within layouts/application (12.5ms) Completed 200 OK in 581ms (Views: 225.8ms | ActiveRecord: 10.0ms)
ความสามารถในการโหลดที่กระตือรือร้นของ ActiveRecord
ใน Rails ทำให้สามารถลดจำนวนการสืบค้นลงได้อย่างมากโดยให้คุณระบุการเชื่อมโยงทั้งหมดที่จะโหลด ล่วงหน้า สิ่งนี้ทำได้โดย includes
เรียกเมธอด include (หรือ preload
) บนวัตถุ Arel ( ActiveRecord::Relation
) ที่กำลังสร้างขึ้น includes
ActiveRecord
ช่วยให้แน่ใจว่าการเชื่อมโยงที่ระบุทั้งหมดถูกโหลดโดยใช้จำนวนการสืบค้นขั้นต่ำที่เป็นไปได้ เช่น:
def comments_for_top_three_posts posts = Post.includes(:comments).limit(3) posts.flat_map do |post| post.comments.to_a end end
เมื่อมีการเรียกใช้โค้ดที่แก้ไขข้างต้น เราจะเห็นในไฟล์บันทึกว่าความคิดเห็นทั้งหมดถูกรวบรวมในแบบสอบถามเดียวแทนที่จะเป็นสามรายการ:
Started GET "/posts/some_comments" for 127.0.0.1 at 2014-05-20 20:05:18 -0700 Processing by PostsController#some_comments as HTML Post Load (0.5ms) SELECT "posts".* FROM "posts" LIMIT 3 Comment Load (4.4ms) SELECT "comments".* FROM "comments" WHERE"comments "."post_id" IN (1, 2, 3) Rendered posts/some_comments.html.erb within layouts/application (12.2ms) Completed 200 OK in 560ms (Views: 219.3ms | ActiveRecord: 5.0ms)
มีประสิทธิภาพมากขึ้น
วิธีแก้ปัญหา N+1 นี้มีขึ้นเพื่อเป็นตัวอย่างของความไร้ประสิทธิภาพที่สามารถมีอยู่ "ที่ด้อยประสิทธิภาพ" ในแอปพลิเคชันของคุณเท่านั้น หากคุณไม่ได้ให้ความสนใจเพียงพอ ประเด็นสำคัญที่นี่คือ คุณควรตรวจสอบการพัฒนาและทดสอบไฟล์บันทึกระหว่างการพัฒนา เพื่อตรวจสอบ (และที่อยู่!) ที่ไม่มีประสิทธิภาพในโค้ดที่สร้างคำตอบของคุณ
การตรวจสอบไฟล์บันทึกเป็นวิธีที่ยอดเยี่ยมในการชี้ให้เห็นถึงความไร้ประสิทธิภาพในโค้ดของคุณ และแก้ไขไฟล์เหล่านั้นก่อนที่แอปพลิเคชันของคุณจะเข้าสู่กระบวนการผลิต มิฉะนั้น คุณอาจไม่ทราบถึงปัญหาด้านประสิทธิภาพของ Rails ที่เป็นผลลัพธ์จนกว่าระบบของคุณจะใช้งานได้ เนื่องจากชุดข้อมูลที่คุณทำงานด้วยในการพัฒนาและทดสอบมักจะมีขนาดเล็กกว่าที่ใช้งานจริงมาก หากคุณกำลังทำงานกับแอปใหม่ แม้แต่ชุดข้อมูลการผลิตของคุณก็อาจเริ่มต้นเพียงเล็กน้อย และแอปของคุณก็ดูเหมือนว่าจะทำงานได้ดี อย่างไรก็ตาม เมื่อชุดข้อมูลการผลิตของคุณเติบโตขึ้น ปัญหา Rails เช่นนี้จะทำให้แอปพลิเคชันของคุณทำงานช้าลงและช้าลง
หากคุณพบว่าไฟล์บันทึกของคุณเต็มไปด้วยข้อมูลจำนวนมากที่คุณไม่ต้องการ นี่คือบางสิ่งที่คุณสามารถทำได้เพื่อล้างข้อมูลเหล่านี้ (เทคนิคที่ใช้ได้สำหรับการพัฒนาและบันทึกการใช้งานจริง)
ข้อผิดพลาดทั่วไป #7: ขาดการทดสอบอัตโนมัติ
Ruby and Rails ให้ความสามารถในการทดสอบอัตโนมัติอันทรงพลังตามค่าเริ่มต้น นักพัฒนา Rails หลายคนเขียนการทดสอบที่ซับซ้อนมากโดยใช้สไตล์ TDD และ BDD และใช้เฟรมเวิร์กการทดสอบที่ทรงพลังยิ่งขึ้นด้วย gem เช่น rspec และ cucumber
แม้จะง่ายเพียงใดในการเพิ่มการทดสอบอัตโนมัติลงในแอปพลิเคชัน Rails ของคุณ แต่ฉันแปลกใจมากกับจำนวนโปรเจ็กต์ที่ฉันได้รับหรือเข้าร่วมโดยที่ ไม่มี การทดสอบเป็นลายลักษณ์อักษร (หรืออย่างดีที่สุด น้อยมาก) โดยก่อนหน้านี้ ทีมพัฒนา. แม้ว่าจะมีการถกเถียงกันมากมายเกี่ยวกับความครอบคลุมของการทดสอบของคุณ แต่ก็ค่อนข้างชัดเจนว่าอย่างน้อยควรมีการทดสอบอัตโนมัติ บาง รายการสำหรับทุกแอปพลิเคชัน
ตามหลักการทั่วไป ควรมีการทดสอบการรวมระดับสูงอย่างน้อยหนึ่งครั้งสำหรับแต่ละการดำเนินการในคอนโทรลเลอร์ของคุณ ในอนาคต นักพัฒนา Rails คนอื่นๆ มักจะต้องการขยายหรือแก้ไขโค้ด หรืออัปเกรดเวอร์ชัน Ruby หรือ Rails และเฟรมเวิร์กการทดสอบนี้จะให้วิธีการตรวจสอบว่าฟังก์ชันพื้นฐานของแอปพลิเคชันนั้นชัดเจน ทำงาน. ประโยชน์เพิ่มเติมของแนวทางนี้คือช่วยให้นักพัฒนาในอนาคตสามารถระบุชุดฟังก์ชันการทำงานทั้งหมดที่มีให้โดยแอปพลิเคชันได้อย่างชัดเจน
ข้อผิดพลาดทั่วไป #8: การบล็อกการโทรไปยังบริการภายนอก
ผู้ให้บริการ Rails บุคคลที่สามมักจะทำให้ง่ายต่อการรวมบริการของพวกเขาในแอปพลิเคชันของคุณผ่าน gem ที่รวม API ของพวกเขา แต่จะเกิดอะไรขึ้นหากบริการภายนอกของคุณขัดข้องหรือเริ่มทำงานช้ามาก
เพื่อหลีกเลี่ยงการบล็อกการโทรเหล่านี้ แทนที่จะเรียกใช้บริการเหล่านี้โดยตรงในแอปพลิเคชัน Rails ของคุณในระหว่างการประมวลผลคำขอตามปกติ คุณควรย้ายบริการเหล่านี้ไปยังบริการจัดคิวงานในเบื้องหลังที่สามารถทำได้ อัญมณียอดนิยมบางส่วนที่ใช้ในแอปพลิเคชัน Rails เพื่อจุดประสงค์นี้ ได้แก่:
- งานล่าช้า
- Resque
- Sidekiq
ในกรณีที่ไม่สามารถดำเนินการได้หรือเป็นไปไม่ได้ที่จะมอบหมายการประมวลผลไปยังคิวงานเบื้องหลัง คุณจะต้องตรวจสอบให้แน่ใจว่าแอปพลิเคชันของคุณมีการจัดการข้อผิดพลาดที่เพียงพอและข้อกำหนดการเฟลโอเวอร์สำหรับสถานการณ์ที่หลีกเลี่ยงไม่ได้เมื่อบริการภายนอกหยุดทำงานหรือกำลังประสบปัญหา . คุณควรทดสอบแอปพลิเคชันของคุณโดยไม่มีบริการภายนอก (อาจโดยการลบเซิร์ฟเวอร์ที่แอปพลิเคชันของคุณเปิดอยู่ออกจากเครือข่าย) เพื่อตรวจสอบว่าไม่มีผลที่ตามมาใดๆ ที่ไม่คาดคิด
ข้อผิดพลาดทั่วไป #9: การแต่งงานกับการย้ายฐานข้อมูลที่มีอยู่
กลไกการย้ายฐานข้อมูลของ Rails ช่วยให้คุณสร้างคำแนะนำเพื่อเพิ่มและลบตารางและแถวฐานข้อมูลโดยอัตโนมัติ เนื่องจากไฟล์ที่มีการโยกย้ายเหล่านี้มีการตั้งชื่อตามลำดับ คุณจึงสามารถเล่นได้ตั้งแต่เริ่มต้นเพื่อนำฐานข้อมูลเปล่าไปยังสคีมาเดียวกันกับที่ใช้งานจริง ดังนั้นจึงเป็นวิธีที่ยอดเยี่ยมในการจัดการการเปลี่ยนแปลงแบบละเอียดในสคีมาฐานข้อมูลของแอปพลิเคชันของคุณ และหลีกเลี่ยงปัญหา Rails
แม้ว่าวิธีนี้จะใช้งานได้ดีในช่วงเริ่มต้นของโครงการของคุณ แต่เมื่อเวลาผ่านไป กระบวนการสร้างฐานข้อมูลอาจใช้เวลาค่อนข้างนาน และบางครั้งการโยกย้ายอาจวางผิดที่ ใส่ไม่เป็นระเบียบ หรือนำมาใช้จากแอปพลิเคชัน Rails อื่นๆ โดยใช้เซิร์ฟเวอร์ฐานข้อมูลเดียวกัน
Rails สร้างการแสดงแทนสคีมาปัจจุบันของคุณในไฟล์ชื่อ db/schema.rb
(โดยค่าเริ่มต้น) ซึ่งมักจะถูกอัพเดตเมื่อมีการเรียกใช้การโยกย้ายฐานข้อมูล ไฟล์ schema.rb
ยังสามารถสร้างขึ้นได้เมื่อไม่มีการโยกย้าย โดยการรันงาน rake db:schema:dump
ข้อผิดพลาดทั่วไปของ Rails คือการตรวจสอบการโยกย้ายใหม่ไปยัง repo ต้นทางของคุณ แต่ไม่ใช่ไฟล์ schema.rb
ที่อัปเดตตามลำดับ
เมื่อการย้ายข้อมูลหลุดมือและใช้เวลานานเกินไปในการดำเนินการ หรือสร้างฐานข้อมูลไม่ถูกต้องอีกต่อไป นักพัฒนาไม่ควรกลัวที่จะล้างไดเร็กทอรีการโยกย้ายเก่า ทิ้งสคีมาใหม่ และดำเนินการต่อจากที่นั่น การตั้งค่าสภาพแวดล้อมการพัฒนาใหม่จะต้องใช้ rake db:schema:load
มากกว่า rake db:migrate
ที่นักพัฒนาส่วนใหญ่พึ่งพา
ปัญหาเหล่านี้บางส่วนมีการกล่าวถึงใน Rails Guide เช่นกัน
ข้อผิดพลาดทั่วไป #10: การตรวจสอบข้อมูลที่ละเอียดอ่อนในที่เก็บซอร์สโค้ด
เฟรมเวิร์กของ Rails ทำให้ง่ายต่อการสร้างแอปพลิเคชันที่ปลอดภัยซึ่งป้องกันการโจมตีได้หลายประเภท บางส่วนสามารถทำได้โดยใช้โทเค็นลับเพื่อรักษาความปลอดภัยเซสชันด้วยเบราว์เซอร์ แม้ว่าตอนนี้โทเค็นนี้จะถูกเก็บไว้ใน config/secrets.yml
และไฟล์นั้นอ่านโทเค็นจากตัวแปรสภาพแวดล้อมสำหรับเซิร์ฟเวอร์ที่ใช้งานจริง Rails เวอร์ชันที่ผ่านมาได้รวมโทเค็นไว้ใน config/initializers/secret_token.rb
ไฟล์นี้มักถูกตรวจสอบอย่างผิดพลาดในที่เก็บซอร์สโค้ดกับส่วนที่เหลือของแอปพลิเคชันของคุณ และเมื่อสิ่งนี้เกิดขึ้น ใครก็ตามที่เข้าถึงที่เก็บนั้นสามารถประนีประนอมผู้ใช้แอปพลิเคชันของคุณทั้งหมดได้อย่างง่ายดาย
ดังนั้น คุณควรตรวจสอบให้แน่ใจว่าไฟล์การกำหนดค่าที่เก็บของคุณ (เช่น .gitignore
สำหรับผู้ใช้ git) ไม่รวมไฟล์ที่มีโทเค็นของคุณ เซิร์ฟเวอร์ที่ใช้งานจริงของคุณสามารถเลือกโทเค็นจากตัวแปรสภาพแวดล้อมหรือจากกลไกเช่นเดียวกับที่ dotenv gem จัดเตรียมให้
สรุปการสอน
Rails เป็นเฟรมเวิร์กที่ทรงพลังซึ่งซ่อนรายละเอียดที่น่าเกลียดมากมายที่จำเป็นต่อการสร้างเว็บแอปพลิเคชันที่แข็งแกร่ง แม้ว่าสิ่งนี้จะทำให้การพัฒนาเว็บแอปพลิเคชัน Rails เร็วขึ้นมาก นักพัฒนาควรให้ความสนใจกับข้อผิดพลาดในการออกแบบและการเขียนโค้ดที่อาจเกิดขึ้นได้ เพื่อให้แน่ใจว่าแอปพลิเคชันของพวกเขาสามารถขยายและบำรุงรักษาได้ง่ายเมื่อเติบโตขึ้น
นักพัฒนายังต้องตระหนักถึงปัญหาที่ทำให้แอปพลิเคชันของตนทำงานช้าลง เชื่อถือได้น้อยลง และปลอดภัยน้อยลง สิ่งสำคัญคือต้องศึกษากรอบงานและตรวจสอบให้แน่ใจว่าคุณเข้าใจอย่างถ่องแท้ถึงการแลกเปลี่ยนเชิงสถาปัตยกรรม การออกแบบ และการเข้ารหัสที่คุณทำอยู่ตลอดกระบวนการพัฒนา เพื่อช่วยให้มั่นใจว่าแอปพลิเคชันมีคุณภาพสูงและมีประสิทธิภาพสูง