รหัส Buggy Rails: 10 ข้อผิดพลาดที่พบบ่อยที่สุดที่นักพัฒนา Rails ทำ

เผยแพร่แล้ว: 2022-03-11

Ruby 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 หรือวิธีการสร้างแบบสอบถามอื่น ๆ เช่น นอกคลาสโมเดลเอง
ที่เกี่ยวข้อง: 8 คำถามสัมภาษณ์ Essential Ruby on Rails

ข้อผิดพลาดทั่วไป #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 เร็วขึ้นมาก นักพัฒนาควรให้ความสนใจกับข้อผิดพลาดในการออกแบบและการเขียนโค้ดที่อาจเกิดขึ้นได้ เพื่อให้แน่ใจว่าแอปพลิเคชันของพวกเขาสามารถขยายและบำรุงรักษาได้ง่ายเมื่อเติบโตขึ้น

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

ที่เกี่ยวข้อง: ประโยชน์ของ Ruby on Rails คืออะไร? หลังจากสองทศวรรษของการเขียนโปรแกรม ฉันใช้ Rails