ถาม Software Engineer 任何人 Review ส่วนสำคัญของ Production Code พวกเขาจะชี้ให้เห็น 3 อย่างที่ต้อง Refactor ทำไม Bad, Brittle, หรือ Misunderstood Code เยอะมากยังคง Run ใน Production?
คำตอบง่าย: Engineer กลัวจะมาสัมผัสมัน Refactoring Tasks ถูกระบุและเพิ่มใน Backlog แต่ทีไรทำเข้า Sprint ได้บ้าง
มีหลายเหตุผล โค้ดอาจเขียนโดย Engineer ที่ลาออกไปหลายปีแล้ว ไม่มีใครเข้าใจมันหมด ในบางกรณี Capability นั้น Critical ต่อธุรกิจ ไม่มีใครอยากรับผิดชอบ Outage หรือ Revenue Loss ที่อาจเกิดขึ้น
ในบทความนี้ เราจะตรวจสอบวิธีใช้ Scientist เพื่อ Migrate, Refactor, และเปลี่ยน Critical Ruby Production Code ด้วยความมั่นใจ
แตก่อน คุณอาจถาม — เราใช้ Tests ขุด Code Issues ไม่ได้ไหม?
นี่คือสิ่งที่ Rails Testing ทำได้ ไหม?
ใช่และไม่ใช่ ยากมายที่จะได้ Confidence เต็มที่ใน Code Changes ก่อน Deploy Unit และ System Tests ผ่าน พร้อม Deploy แล้วไหม?
ความจริงคือ ไม่มี Substitute สำหรับ Real World คือ Production ถ้า Data Quality ไม่ดี หรือ Tests ขาดหาย? คุณจะรู้ยังไงว่า Software ใหม่ Perform 夠ดีสำหรับ Production Throughput?
ทีมที่มี Public Services บางทีพบว่าต้อง Deal กับ "Bugwards Compatibility" Issues เมื่อ Bug มีอยู่ใน Production นาน Client อาจ Code 依赖 Consistent Incorrect Behavior Customers มักใช้ Software แบบไม่คาดคิด
สังเกตการเปลี่ยนแปลง Production ใน Ruby และ Rails ด้วย Scientist
ถ้า Production คือที่ดีที่สุดเพื่อได้ Confidence ในการเปลี่ยนแปลง ให้พิจารณาสังเกตพฤติกรรมโค้ดที่นั่น อาจดูน่ากลัว ตรงข้ามกับ Classic Software Engineering Practices
แต่ข่าวดีคือ ทำได้ง่ายและปลอดภัยใน Ruby และ Rails ด้วย Gem Scientist ชื่อ Scientist มาจาก Scientific Method การทดลองเพื่อ Verify Hypothesis ที่กำหนด ในกรณีนี้ Hypothesis คือ โค้ดใหม่ทำงานได้
เหตุผลที่เราทำได้อย่างปลอดภัย มาจากว่า Experiments ยังใช้ Result ของ Existing Code โค้ดใหม่ถูก Evaluate เพื่อ Observation และ Comparison เท่านั้น ทั้ง Accuracy และ Performance เรา Mitigate Test Coverage Concerns ที่พูดไปโดย Evaluate Performance ด้วย Real-world Data และ Parameters Experiments ทั่วไป Evaluate Sample Rate ของ Requests ที่เลือก เพื่อ Minimize Impact บน Production แต่คุณสามารถ Evaluate ทุก Request ได้หากต้องการ
มาดู Quick Look ว่า Scientist ทำงานใน Branch by Abstraction Way ยังไง
Branch by Abstraction Pattern ใน Ruby's Scientist
Approach ของ Scientist เริ่มจาก Branch by Abstraction Pattern ที่ Martin Fowler อธิบายว่า "ทำ Large-scale Change ให้ Software System แบบ Gradual"
เรา Introduce Abstraction Layer เพื่อ Isolate Code ที่กำลัง Update Layer นี้ Decide ว่าใช้ Implementation ไหน ทำให้ Experiment Transparent ต่อ System ส่วนที่เหลือ เทคนิคนี้เกี่ยวข้องกับ Feature Flag ที่ Determine Code Path
Gem Scientist ซึ่งมาจาก Github Implement Pattern นี้ด้วย Experiment โค้ดเดิมเรียกว่า Control และ Implementation ใหม่คือ Candidate ทั้งสอง Code Paths Run ใน Randomized Order แต่แค่ Control Result ถูก Return ให้ Client
ใช้ Scientist Refactor Ruby Service
พิจารณา Ruby Service ที่ Return Largest Prime Factor สำหรับตัวเลขที่กำหนด สมมติเราระบุ Optimizations เพื่อ Prune Required Candidate Set ทำให้ Service เร็วขึ้น
แต Owner ของ Service อยากแน่ใจว่าไม่มี Bug ถูก Introduce พวกเขายังอยาก Observe Performance Improvements Introduce โค้ดต่อไป แก้ไข Clients ให้เรียก Method นี้:
จุดนี้มีแค่ Expression use (Control) ถูก Invoke เพื่อให้ Experiment Worthwhile กำหนด Custom Experiment Class เพื่อ Enable (100% ด้านล่าง) และ Publish Results (ในกรณีนี้แค่ Logging) Scientist Generate Data ยอดเยี่ยม แต่ Default ไม่ทำอะไรกับมัน ส่วนนั้นขึ้นกับคุณ
Results ของ Experiment จะ Logged และเราสามารถ Improve ตามเวลาจาก Feedback เมื่อโค้ดใหม่ Meet Requirements และ Confidence สูง ทำ Cutover ไป Implementation ใหม่โดยแทนที่ Science Code ด้วย Delegation ไป Implementation ใหม่
LabTech ทำให้ Scientist Experiments ใน Ruby on Rails เรียบง่าย
คุณสามารถใช้ Gem LabTech ใน Rails App เพื่อ Config Scientist อย่างง่ายและ Handle Results
App ที่ใช้ AppSignal สามารถใช้ Appsignal.instrument Custom Instrumentation Helper เพื่อ Track ว่า Scientist Events ใช้เวลานานแค่ไหน Wrap รอบ Experiment Code Blocks ต่างๆ เพื่อเห็น Events ใน Performance Timeline
กลับไป LabTech — หน้าเว็บด้านล่างรับ Number เพื่อ Factor

Getting Started ง่ายถ้าคุณเข้าถึง Console ก่อน เพิ่ม Gem LabTech ใน Gemfile และรัน bundle install
Tables เก็บ Results และ Experiment Config ดังนั้นรัน Database Migration
Abstraction Layer เหมือนเดิม แต่ใช้ LabTech Module โค้ดเต็มมีบน GitHub
จุดนี้ Experiment Disabled ใช้ Console Enable ในทุก Case หรือ Percentage ของเวลา
เราสามารถรัน Tests และ Experiment จะ Evaluated สำหรับ Textual View ของ Results ใช้ Command ต่อไปจาก Rails Console
หลังจาก Successful Runs หลายครั้งและ Manufactured Error 1 ครั้ง นี่คือ Results Summary ตัวอย่าง มี Overview ของ Successes และ Failures รวม ASCII Chart แสดง Performance Differences
Gem Blazer ให้วิธี Analyze Results ได้ง่าย Install 简单 และรัน SQL Queries ต่อ Tables Query ที่นี่แสดง Candidate Implementation เร็วกว่า Original มาก

ใน Example Prime Factoring Service Speedup ใน Improved Implementation มาจาก Heuristic ที่ Eliminate Possible Factors บางส่วน เมื่อเราพิจารณาตัวเลขสูงและหา Prime Factor เราสามารถหยุด Search หลังจากถึง Target Number หารด้วย Factor นั้น โค้ด Path ใหม่เพิ่มแค่ 1 Statement ทำได้นี้
เรายังเห็น Reduction ใน Execution Time ด้วย Blazer Query ต่อ LabTech Tables

Use Cases และ Limitations ของ Scientist
Optimal Use Cases สำหรับ Scientist รวมถึง Searches, Calculations, และ Code ที่ไม่มี Side Effects Code ที่รวม Transactional Updates หรือ External Integrations อย่าง Email ไม่ Fit เข้า Model ใส่สะอาด เพราะ Capability Run สองครั้ง (ทั้ง Old และ New Implementations)
นี่ไม่ใช่ Limitation เล็กน้อย เพราะ Eliminate Use Cases หลายอย่าง แต่มี Workarounds หาก Experiment Critical ต่อความสำเร็จ พิจารณาว่า Side Effects Relevant หรือ Duplication เป็น Issue ไหม เช่นบางกรณีอาจไม่สำคัญถ้าส่ง Email 2 ครั้งระหว่าง Evaluation อีก Option ให้ New Code Determine Result แต่ไม่ Persist มัน จะ Prevent Meaningful Performance Comparisons แต่ Allow Verify Accuracy
Limitations อื่นมาจาก Focus ของ Scientist บน Return Values บางกรณี Valid Results อาจแสดง Differences ตามเวลา ไม่ว่าจะรวม Timestamps ใน Response หรือ Factors ต่างๆ Vary ในหลายกรณี เราสามารถเขียน Custom Comparison Logic ใน Experiment เพื่อ Verify Accuracy เหนือ Basic String Comparisons
สุดท้าย Limitation ของ LabTech คือยังไม่ Ported ไป Rails 7 ณ เวลาเขียน
Best Practices สำหรับ Scientist Experiments ที่มีประสิทธิภาพใน Rails
พิจารณา Items นี้ตอน Implement Experiments:
- ใน Rails Projects Scientist Config ได้ใน Initializer หรือ Wrapper เช่น Rails LabTech Gem ほとんど Rails Apps มี Database แล้ว LabTech ใช้ ActiveRecord เก็บ Results
- เพื่อไม่ Slow Down Development และ Testing Enable Experiment แค่ Staging และ Production Environments
- เพื่อ Minimize Impact บน Production รัน Experiment แค่ Percentage ของ Requests LabTech รองรับ Out-of-the-box เป็น Optional Parameter ตอน Enable Experiment (Disabled โดย Default เริ่มต้น) ใช้ Pure Scientist Logic นี้ง่ายใน Experiment's
enabled?Method - Logic บางอย่าง Resource-Intensive ดังนั้น Low Sampling Rate อาจเป็น Starting Point ที่ดี เมื่อ Confident กับ Results Ramp Up Percentage ของ Requests ที่ Evaluate
- คุณสามารถเพิ่ม Context Attributes เพื่อได้มากที่สุดจาก Results Experiment Context สามารถ Set เป็น Symbol-keyed Hash ของ Data ที่ Available ใน Published Results เช่น:
สรุป: สังเกตและ Monitor Ruby App ด้วย Scientist
ในบทความนี้ เราสำรวจการใช้ Gem Scientist เพื่อเปลี่ยน Migrate และ Refactor Ruby Code ใน Production
เราตรวจสอบ Origin ของ Scientist ใน Branch by Abstraction Pattern แล้วเจาะลึก Refactoring ต่อมาเราเห็นว่า LabTech ช่วยเกี่ยวกับการเก็บ Results และ Config Scientist ของคุณ
เราแล้วแตะ Limitations ของ Scientist ก่อน Outline Best Practices เล็กน้อย
คุณต้อง Observe และ Monitor สิ่งที่เกิดขึ้นใน System ของคุณ Integrate Scientist เข้า Development Process เพื่อทำ Critical Changes ใน Ruby Code ด้วย Confidence มากขึ้น
Happy Coding!
P.S. หากต้องการอ่านบทความ Ruby Magic ทันทีที่เผยแพร่ สมัคร Newsletter Ruby Magic ของเราและจะไม่พลาดบทความเด็ดๆ ไป!
Darren Broemmer
Darren ชอบ Inspire ผ่านคำเขียน และทำให้ Complex Things เข้าใจง่าย ความสนใจรวม Science และ Physics และ Math พอที่จะทำความเข้าใจทั้งสอง เขาสร้าง High-quality Content และ Technology Solutions และ Tweet บางครั้ง
บทความทั้งหมดโดย Darren Broemmer