Bug ในซอฟต์แวร์สามารถรบกวน ตลกหลบหลีก ลำบาก และรุกรานได้ จริงๆ แล้ว นักพัฒนาบ่อยครั้งต้องการความขยันของ Edison เพื่อค้นหาและแก้ไขปัญหา
แต่ความขยันไม่ใช่ทรัพย์สินเดียวที่นักพัฒนาต้องการ คนยังต้องการข้อมูลเพื่อ debug โค้ด: อาการและผลกระทบของปัญหาคืออะไร? ความถี่คือเท่าไร? ความแพร่ระพาย? ต้นกำเนิด? หลักฐานและวัตถุโ古董ของ bug — core dump, stack trace, log, หรือ test case — เป็นสิ่งที่มีค่าไม่มีราคา
มาสำรวจเทคนิคและเครื่องมือบางอย่างที่พร้อมใช้งานสำหรับนักพัฒนา Ruby และ Rails สำหรับการรวบรวมและสืบสวนหลักฐานของปัญหา ข้อมูลไม่สามารถแทนที่ความขยันได้ แต่มันช่วยลดความพยายาม (และขจัดการนอนหลับของคุณ)
Rails 提供เครื่องมือยอดเยี่ยมบางอย่างเพื่อมองเข้าไปในแอปพลิเคชันที่กำลังรัน รวมถึง Logger ที่กำหนดค่าได้เพื่อจับ diagnostics ของตัวมันเองและอะไรก็ตามที่คุณอยากเพิ่ม Rails ยังให้ verbose query log เพื่อระบุต้นทางของ database queries และ verbose enqueue log เพื่อ照亮ที่ background jobs ถูก enqueue สอง log สุดท้ายนี้เปิดใช้งานโดย default ใน environment development คุณสามารถเปิดใช้งานทั้งสองใน environments อื่นๆ ด้วยสอง statements
log option ที่รู้จักน้อยกว่าที่มีมาตั้งแต่ Rails 7 ใส่คำอธิบายแต่ละ SQL query ด้วย comments หากคุณเพิ่มสิ่งต่อไปนี้ไปที่ config/application.rb หรือ environment file ใดๆ:
query log ของคุณจะถูกปรับปรุงโดยอัตโนมัติด้วย application name, controller name, action name หรือ background job name ตัวอย่าง output ต่อไปนี้มาจาก Rails debugging guide โดยตรง:
คุณอาจไม่ต้องการเปิดใช้งานฟีเจอร์ทั้งหมดนี้ใน production Log generation อาจมีต้นทุนสูงในแง่ของหน่วยความจำและเวลา (ทรัพยากรจำกัดสำหรับแอปภายใต้โหลด)
อย่างไรก็ตาม มีข้อยกเว้น คุณอาจต้องการเปิดใช้งานฟีเจอร์ on-demand สั้นๆ โดยเฉพาะเมื่อ debugging ใน development และ test modes แทนที่จะเปลี่ยนโค้ด (และอาจต้อง redeploy) เพื่อเปิดหรือปิด diagnostic ให้ใช้ environment variables ควบคุม state ในบาง environments เช่น Heroku การเปลี่ยนการตั้งค่า environment variable ไม่บังคับ new deployment
ตัวอย่างเช่น คุณสามารถกำหนดชุด variables เพื่อควบคุม logging และ verbosity
เพื่อความสะดวก สร้าง class เล็กๆ เพื่อ query configuration settings
ตอนนี้ใช้ variables และโค้ดเพื่อตั้งค่า logging features ใน config/application.rb:
ใช้ shell, dotenv file, continuous integration หรือ hosting และ deployment platform ของคุณเพื่อตั้งค่าแต่ละตัวเลือก คุณยังสามารถใช้ฟีเจอร์ on-demand ได้ เพียงเริ่มแอปพลิเคชันด้วย environment variable ที่กำหนดบน command line
ปรับ Puma สำหรับ Development
สร้างบนส่วนก่อนหน้า มาดูวิธีใช้ environment variables เพื่อปรับแต่ง Puma configuration ของคุณสำหรับ debugging ใน development environment
โดยปกติ Puma ถูกกำหนดค่าเพื่อ maximize throughput ใน production รัน multiple workers และ many threads ต่อ worker ใน development คุณต้องการตรงข้าม: one worker, one thread และ timeout ยาวมากเพื่ออนุญาต interactive debugging แต่ละอย่างคือพารามิเตอร์ที่คุณสามารถปรับได้
แก้ไข config/puma.rb ให้สะท้อนโค้ดต่อไปนี้
ตอนนี้คุณสามารถกำหนดค่า environment variables สามตัวเพื่อควบคุม Puma ในแต่ละ environment ใน development ตั้งค่าเพื่อ optimize สำหรับ interactive debugging
หากคุณต้องการ validate Puma settings ของคุณ ตั้งค่า environment variable PUMA_LOG_CONFIG=true และเริ่มแอปพลิเคชันของคุณ Puma ปล่อย active configuration ของมันเมื่อ startup
โดยบังเอิญ default Puma configuration ใน Rails release ล่าสุดคล้ายกับที่แสดงที่นี่ (ขอบคุณ Nate Matykiewicz สำหรับ tip)
Run Background Jobs Inline
Rails application ของความซับซ้อนใดๆ มักใช้ background jobs เพื่อรัน compute-intensive และ (relative) long-running tasks Background jobs รันแบบ asynchronous ตัดขาดจาก request/response cycle ผู้สมัครที่เหมาะสมสำหรับ "out of band" processing รวมถึง generating reports, ส่งอีเมล และโต้ตอบกับ third-party APIs แต่ลักษณะ asynchronous ของ jobs ยังทำให้ debugging ซับซ้อนขึ้น
เพื่อลดความซับซ้อนในการ troubleshooting ให้รัน jobs ทันที ใน local development และ test environments ของคุณ ใน immediate mode jobs ไม่ถูก queued แต่แทนที่จะ execute instantaneously การรันใน "foreground" คุณสามารถตั้ง breakpoints และ inspect state แบบ interactive
มาดูตัวอย่างโดยใช้ Delayed Job backend คิวยอดนิยมและง่ายต่อการจัดการสำหรับ Active Job Delayed Job ให้ setting เพื่อ enable queueing โดย default setting เป็น true และ jobs ถูก queued ตามปกติ อย่างไรก็ตาม หากตั้งเป็น false jobs จะรันทันที
เพิ่มโค้ดต่อไปนี้ไปยังแอปพลิเคชันของคุณใน config/initializers/delayed_job.rb:
หาก DELAYED_JOBS_DISABLE_JOB_QUEUES ถูกตั้งค่าเป็นค่าใดค่าหนึ่ง queueing จะถูก disable หาก environment variable ว่างหรือไม่ได้กำหนด queueing จะถูก enable
ต่อไป ใน shell ของคุณ บน command line หรือใน dot files ตั้งค่า DELAYED_JOBS_DISABLE_JOB_QUEUES ตามที่ต้องการ
ตั้งค่า environment variable เป็น nothing หรือลบ environment variable เพื่อ restore queueing
ไม่มีกฎสำหรับการตั้งชื่อ environment variables เลือกชื่อที่ meaningful สำหรับคุณ หนึ่ง convention ที่ช่วยเหลือในการจัดกลุ่ม variables คือการเพิ่ม package name เป็น prefix เช่น PUMA_ และ DELAYED_JOB_ ตัวแรกบ่งชี้ variables ที่ส่งผลต่อ Puma ตัวหลังบ่งชี้ variables ที่ใช้โดย Delayed Job
มองเข้าไปใน Network Calls
เหมือน background jobs Rails applications ยังสามารถ consume application programming interfaces (APIs) APIs ให้การเข้าถึง external services เช่น GraphQL databases, e-commerce transactions และ public data sources
นี่คือตัวอย่างอีกตัวหนึ่งที่มีเงื่อนไข emit HTTP requests และ responses จากไลบรารี Net::HTTP หาก environment variable DEBUG_HTTP ถูกตั้งค่าเป็นค่า non-blank ใดๆ outgoing request และ inbound responses จะถูกพิมพ์ไปที่ STDOUT
เพื่อดู network activity เพียงเริ่มแอปพลิเคชันด้วย environment variable ที่กำหนดบน command line
เมธอด debug? ให้ abstraction บางส่วนจากการ implement flag จริง มัน และส่วนที่เหลือของโค้ดนี้ สามารถสร้าง base class สำหรับ network requests ทั้งหมดของคุณได้ ตามที่แสดงใน gist นี้ที่มาจาก production code
จักรวาลของ Ruby gems กว้างใหญ่: ไม่สามารถครอบคลุม gems ยอดเยี่ยมทั้งหมดที่พร้อมใช้งานสำหรับ debugging แทนนั้น มาดูเครื่องมือบางอย่างที่คุณสามารถเพิ่มวันนี้เพื่อ instant boost คุณอาจจะเพิ่มแต่ละตัวไปยัง all projects ของคุณ
-
awesome_printและtable_printสร้าง rich, readable inspections ของ Ruby data structures รวมถึง Active Record models คุณสามารถใช้ gem ใด gem หนึ่งในโค้ดหรือจาก consoleนี่คือตัวอย่างของ model ที่ emitted โดย
awesome_printใน console:แทนที่จะใช้
pให้ใช้apเพื่อแสดง enhanced output awesome_print แสดง attributes ใน alphabetical order หนึ่ง attribute ต่อบรรทัด รวมถึงความสะดวกอื่นๆ -
better_errorsแทนที่ standard Rails error page ด้วย enhanced stack backtrace, parameter list และ interactive console ที่คุณสามารถ probe stack frame และ variables ที่ฉากของ exception คุณยังสามารถ tie source code links ไปยัง editor ที่คุณชอบ นี่คือโค้ดเพื่อ tiebetter_errorsไปยัง Visual Studio Code:รัน
export BETTER_ERRORS_EDITOR=vscodeใน shell ของคุณ และ restart Rails server ตอนนี้ links ไปยังไฟล์จะเปิดอัตโนมัติใน Visual Studio -
เก็บ gems
fakerและfactory_bot(หรือ alternatives) ไว้ในทั้ง testing และ development groups ใน Gemfile ทั้งสองมีค่าไม่มีราคาหากคุณต้องการ generate data รวดเร็วใน console
อีกไอเดียหนึ่ง: หากคุณใช้ AppSignal เป็น application monitoring tool ของคุณ มันมี features เพื่อตีความ logs ของคุณและระบุ source ของ errors ดู Debugging in Ruby with AppSignal สำหรับรายละเอียดเพิ่มเติม
Debugging เป็นทักษะ
การ debug โค้ดเป็นประเภทหนึ่งของศิลปะ และเช่นเดียวกับ creative endeavor ใดๆ ยิ่งคุณมี practice มากเท่าไร คุณจะดีขึ้นเท่านั้น
Debug ขณะ pairing กับนักพัฒนาอีกคน โดยเฉพาะ experienced developer หาก partner ของคุณยินดี ให้คิดออกเสียงด้วยกัน และแลกเปลี่ยน hunches และ insights
Go forth and hack!
P.S. หากคุณอยากอ่าน Ruby Magic posts ทันทีที่พวกเขาออก ให้ subscribe Ruby Magic newsletter ของเรา และไม่เคยพลาดโพสต์เดี่ยว!
Martin Streicher
ผู้เขียนรับเชิญ Martin เป็น professional Ruby developer เขาได้รับ advanced degree ใน Computer Science จาก Purdue University ทำหน้าที่ Editor-in-Chief ของ Linux Magazine (US) ห้าปี และเป็น founding author ของคอลัมน์ "Speaking in Unix" ที่เผยแพร่ใน IBM's former developerWorks portal เมื่อไม่ได้เขียนโค้ดหรือเขียนเกี่ยวกับโค้ด เขาสะสมศิลปะและควบคุมสุนัขเล็กๆ หลายตัว
บทความทั้งหมดโดย Martin Streicher