1 คะแนน โดย GN⁺ 1 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Ruby อาจไม่ใช่ภาษาที่เร็วที่สุดหรือกำลังเป็นกระแสที่สุด แต่แม้จะผ่านการใช้งานมาหลายภาษาตลอดกว่า 15 ปี ก็ยังคงเป็นภาษาที่ถูกเลือกกลับมาใช้อีกครั้งเมื่ออยากทำงานอย่างมีความสุข
  • refinements, Forwardable, SimpleDelegator, Object#then, Kernel#tap และ numbered parameters มอบความสะดวกทางไวยากรณ์เล็กๆ พร้อมลำดับการอ่านที่เข้าใจง่าย
  • Thread::Queue, json, csv ใน standard library รวมถึง RuboCop และ Ruby LSP ช่วยให้คงสภาพแวดล้อมการพัฒนาที่ใช้งานได้จริงโดยไม่ต้องพึ่ง gem ย่อยมากมายหรือการตั้งค่าที่ซับซ้อน
  • YJIT ใน Ruby 3.x และ ZJIT ใน 4.x กำลังลดช่องว่างในงานที่ใช้ CPU หนักลง และในการเปรียบเทียบ Fibonacci แบบง่าย Ruby with ZJIT อยู่ห่างจาก Go เพียงราว 2–3 เท่า
  • แม้ Rust·Go·Python จะเหมาะกว่าในบางด้าน แต่สำหรับเว็บแอป งานเบื้องหลัง และเครื่องมือภายใน จุดแข็งของ Ruby ก็ยังอยู่ที่ ความสุขของนักพัฒนา และความเร็วในการทำซ้ำ

เหตุผลทางภาษาที่ทำให้ Ruby ใช้งานแล้วรู้สึกสบาย

  • Ruby อาจไม่ใช่ ภาษาที่เร็วที่สุดหรือเป็นกระแสที่สุด แต่แม้จะสลับไปมาระหว่างหลายภาษาตลอดกว่า 15 ปี ก็ยังเป็นภาษาที่ทำให้เลือกกลับมาใช้เมื่ออยากสนุกกับการทำงานจริงๆ
  • refinements เปิดคลาสได้เฉพาะในขอบเขตจำกัด จึงเพิ่มความสะดวกทางไวยากรณ์เล็กๆ ภายในไฟล์หรือบล็อกได้โดยไม่ทำให้ namespace ทั้งหมดปนเปื้อน
    • เหมาะกับ test helper หรือ internal DSL ในโค้ดเบสขนาดใหญ่
    • สามารถใช้เมธอดอย่าง "hello".quote ได้เฉพาะตำแหน่งที่เรียก using QuotingRefinement
  • Forwardable และ SimpleDelegator ใน standard library ช่วยให้ทำ delegation ได้อย่างสะอาด โดยไม่ต้องเขียน wrapper method เองหรือดึง gem เพิ่มเข้ามา
    • ถ้าใช้ Rails อยู่แล้ว delegate ของ Active Support อาจสะดวกกว่า แต่เวอร์ชัน Ruby แกนหลักช่วยให้สคริปต์ทั่วไปยังคงเบา
  • Object#then และ Kernel#tap ช่วยเชื่อมงานต่อกันเป็น chain ที่อ่านจากบนลงล่างได้ โดยไม่ต้องสร้างตัวแปรกลาง
    • สามารถเขียนลำดับการสร้าง บันทึก log ทำ normalization และบันทึกข้อมูลต่อเนื่องได้ เช่น User.new(params).tap { ... }.then { ... }.save
  • numbered parameters ตั้งแต่ Ruby 2.7 ช่วยลดความรกใน callback สั้นๆ
    • ไม่จำเป็นต้องประกาศ block argument อย่างชัดเจน เช่น items.map { _1.price * 1.1 }
  • fiber scheduler ทำให้เขียนโค้ด concurrency ที่หน้าตาเหมือนโค้ดแบบลำดับได้เมื่อเชื่อมกับ event loop
    • ใช้รูปแบบ Fiber.schedule do ... end เพื่อแสดงโค้ดที่ทำงานร่วมกับ fiber อื่น

ภาพปัจจุบันของเครื่องมือ ประสิทธิภาพ และ ecosystem

  • Ruby LSP ของ Shopify ให้การทำงานร่วมกับ editor ด้วยการตั้งค่าน้อยมาก และทำงานร่วมกับ Steep หรือ RBS สำหรับการเพิ่ม type แบบค่อยเป็นค่อยไปได้ดี
  • RuboCop ช่วยรักษาความสม่ำเสมอของสไตล์ได้โดยไม่ต้องผ่านพิธีกรรมที่เป็นทางการเหมือนใน ecosystem อื่น
  • standard library ยังคงเป็นจุดแข็งเงียบๆ ที่ช่วยให้ไม่ต้องเพิ่ม gem ย่อยจำนวนมากสำหรับงานทั่วไป
    • ถ้าต้องการคิว สามารถใช้ Thread::Queue ได้
    • การ parse JSON หรือ CSV ก็มี json และ csv ที่รองรับกรณีใช้งานจริงส่วนใหญ่ได้โดยไม่ต้องมีขั้นตอนมาก
  • ต่อจาก YJIT ใน Ruby 3.x ตอนนี้ซีรีส์ 4.x กำลังนำ ZJIT เข้ามา
    • ZJIT เป็น JIT ที่ทำงานเชิงรุกมากขึ้นบนฐานเดียวกัน และคอมไพล์เส้นทางการทำงานที่ร้อนจัดได้อย่างมีประสิทธิภาพกว่า
    • จากตัวเลขเบื้องต้น ช่องว่างระหว่าง Ruby กับภาษาที่เคยทิ้งห่างมากในงานที่ใช้ CPU หนักลดลงอย่างมีนัยสำคัญ
    • CRuby ZJIT กำลังพัฒนาอยู่ใน repository หลักของ Ruby
  • ใน benchmark แบบง่ายที่เปรียบเทียบการทำ Fibonacci แบบ recursive บนเครื่องเดียวกัน Ruby with ZJIT อยู่ห่างจาก Go เพียงราว 2–3 เท่า และในกรณีนั้นก็ไม่ได้ห่างจาก Rust ที่ปรับแต่งมาอย่างดีมากนัก ขณะที่ Python with pypy ตามหลัง
    • แม้ microbenchmark จะมีข้อจำกัด แต่ในเส้นทางโค้ดที่อุ่นแล้วและมีเวลาให้ JIT ปรับแต่ง แอปพลิเคชันจริงก็อาจได้ประโยชน์มากกว่า
  • เมื่อเทียบกับ Rust แล้ว Ruby เด่นกว่าในเรื่อง ความเร็วในการวนซ้ำของ business logic
    • ใน Rust อาจต้องใช้เวลาไปกับการต่อสู้กับ borrow checker แม้ในเรื่องที่ชัดเจนอยู่แล้วตอนรันจริง
    • Go มีพื้นฐานด้าน concurrency ที่ยอดเยี่ยม แต่จนไม่นานมานี้ยังไม่มี generics และการจัดการข้อผิดพลาดที่ค่อนข้างแข็งทื่ออาจทำให้สคริปต์ง่ายๆ หนักเกินความจำเป็น
    • Python เป็นญาติทางความคิดที่ใกล้ที่สุด แต่ต้องใช้ boilerplate มากกว่าในการแสดงแนวคิดระดับสูงแบบเดียวกัน โดยเฉพาะรอบๆ class และ decorator
  • เมื่อใส่โค้ดลงในโมเดล ประสิทธิภาพต่อโทเค็น ก็เป็นข้อได้เปรียบจริงของ Ruby
    • สามารถใช้ do/end หรือวงเล็บปีกกาเพื่อแทน block และแทบไม่ต้องใส่วงเล็บใน method call หากยังอ่านง่าย
    • hash และ keyword argument เป็นฟีเจอร์หลักที่กระชับ จึงใส่ logic จริงลงใน context window เดียวกันได้มากกว่าภาษาที่มีโครงสร้างรกกว่า
  • utility ด้าน metaprogramming ของ Ruby เหมาะกับการสร้าง API ที่เล็กและอ่านง่าย
    • ฟีเจอร์อย่าง define_method, class_eval และการดักจับ missing method ช่วยสร้าง API ที่แสดงพลังได้มากโดยไม่ต้องมีขั้นตอนสร้างโค้ด
    • ไลบรารีอย่าง dry-rb หรือ aasm ใช้ความสามารถนี้อย่างพอดีเพื่อให้ได้ state machine และชั้น validation ที่สะอาด
  • เครื่องมือของชุมชนและกระบวนการ deploy ก็สุกงอมขึ้นมากแล้ว
    • byebug และ pry ให้ความรู้สึกยืดหยุ่นกว่าดีบักเกอร์หลายตัวที่เคยใช้ในที่อื่น
    • สำหรับงาน background job นั้น solid_queue และ good_job เรียบง่ายพอที่คนคนหนึ่งจะทำความเข้าใจการทำงานทั้งระบบได้ภายในบ่ายเดียว
    • Kamal เข้ามาแทนขั้นตอนแบบ capistrano รุ่นเก่าสำหรับหลายคน และให้ความรู้สึกเหมือนเป็นเครื่องมือที่สร้างโดยคนที่ดูแลทีมเล็กจริงๆ
  • ทั้งหมดนี้ไม่ได้หมายความว่า Ruby จะชนะ Rust หรือ Go ในทุกงาน และก็ยังมีหลายด้านที่ Rust หรือ Go เหมาะกว่า
  • แต่ในพื้นที่ตรงกลางอันกว้างของเว็บแอป การประมวลผลงานเบื้องหลัง และเครื่องมือภายใน Ruby ยังคงมอบ ความสุขของนักพัฒนา ได้อย่างต่อเนื่องโดยไม่ต้องมีพิธีรีตองมากเกินไปหรือสลับบริบทบ่อย
  • ความสะดวกเล็กๆ น้อยๆ และสัมผัสโดยรวมของภาษา ยังคงเป็นสิ่งที่ทำให้คนเอื้อมมือไปหา Ruby ก่อนแม้เวลาจะผ่านไปเกินสิบปี และงานด้าน JIT ใหม่ๆ รวมถึงการพัฒนาภาษาอย่างต่อเนื่องก็ยิ่งตอกย้ำเหตุผลนั้น

1 ความคิดเห็น

 
GN⁺ 1 시간 전
ความคิดเห็นจาก Lobste.rs
  • รู้สึกว่าเห็นด้วยกับคำว่า “no ceremony RuboCop” ได้ยาก
    RuboCop มีขั้นตอนให้ถกกันพอสมควรว่าจะเลือกและปรับ cop ตัวไหนบ้าง และจะเปิด cop ใหม่ที่เพิ่มมาในอัปเดตล่าสุดหรือไม่
    StandardRB ใกล้เคียงกับแนวทางที่ไร้พิธีรีตองกว่ามาก แต่สุดท้ายก็ยังต้องเลือกมันอยู่ดี
    ภาษาที่มี lint ฝังมาในตัวนั้นยุ่งยากน้อยกว่า Ruby มาก และมีข้อถกเถียงเรื่องสไตล์เล็ก ๆ น้อย ๆ น้อยกว่าด้วย

    • เมื่อราว ๆ 10 ปีก่อน ผมเลือก Standard ให้กับโค้ดเบสของ Sidekiq และไม่เคยเสียใจกับมันเลย
      ข้อจำกัดกลับให้เสรีภาพ
    • ใช้ค่าเริ่มต้นทั้งหมดไปเลยไม่ได้หรือ?
      โดยทั่วไปผมค่อนข้างไม่ชอบการตั้งค่า linter และอยากปล่อยให้การตัดสินใจแบบนี้เป็นหน้าที่ของ ค่าเริ่มต้นจากชุมชน
    • พูดตามตรง ผมเองก็ลังเลไปมาบนประเด็นนี้
      ด้านหนึ่ง ผมคิดว่าค่าเริ่มต้นของ RuboCop ก็ดีพออยู่แล้ว จึงควรยึดตามและค่อย ๆ พัฒนาไปด้วยกัน มากกว่าจะไปแยกย่อยสไตล์การเขียนโค้ดเพิ่ม
      แต่อีกด้านหนึ่ง บางครั้งมันก็มีความเห็นจัดเกินไป จนดูเหมือนว่าจำเป็นต้องมีอะไรอย่าง standard.rb
      ผมเขียนจากมุมมองที่ว่า ถ้าใครจะเริ่มเรียน Ruby หรือกลับมาใช้ใหม่ เขาควรเขียนโค้ดได้อย่างราบรื่นโดยไม่ต้องไปรับมือกับ gem จำนวนมหาศาล
    • เห็นด้วย 100%
      ตอนที่ Go ออกมา ผมคิดว่าการมีระบบจัดรูปแบบอย่างเป็นทางการเพียงหนึ่งเดียวนั้นเป็นสิ่งที่ทำได้ดีมาก
      สมองเป็นเครื่องจักรจับแพตเทิร์น พอคุ้นแล้วมันก็จะมองข้ามไปเอง แต่ถ้ามีตัวเลือก เราจะรู้สึกไม่สบายใจ และทุกคนก็จะถูกดึงไปคนละทาง
      ปัญหาคือทั้ง RuboCop และ Standard ต่างก็ไม่มีทางมีสถานะความชอบธรรมแบบนั้นใน Ruby ได้
      ความชอบธรรมนั้นต้องมาจาก ทีม core แต่คงไม่เกิดขึ้นเพราะขัดกับปรัชญาของ Ruby
      ในโปรเจกต์ของผม ผมปิด RuboCop cop ทั้งหมดแล้วเปิดใช้แค่บางตัว
      single quote ดีที่สุด 😀
    • ผมก็สะดุดกับส่วนนั้นเหมือนกัน
      ดูเหมือนอีกบทความหนึ่งก็พูดถึงประเด็นนี้ไว้: https://caio.ca/blog/coding/my-complicated-relationship - “The Wild West of Code Formatting”
      ประมาณว่า “มันไม่ใช่วิธีแก้แบบเรียบง่ายที่ฝังมาในตัว แต่เป็น cop ที่ตั้งค่าได้หลายร้อยตัว ซึ่งนำไปสู่การถกเถียงไม่รู้จบว่าจะเปิดกฎไหนบ้าง”
  • โดยรวมเห็นด้วย แต่ค่อนข้างเสียดายที่ยก refinements เป็นตัวอย่างแรก
    ผมเข้าใจว่าทำไมถึงชอบมัน แต่ก็ใกล้เคียงกับสิ่งที่ไม่รู้วิธีทำไส้กรอกน่าจะดีกว่า
    semantics ของมันซับซ้อนมาก จนแม้จะผ่านมากว่า 10 ปีหลังการเปิดตัว ก็ยังเจอบั๊กชวนปวดหัวใน MRI อยู่เรื่อย ๆ
    อย่างเช่นในช่วง 2 สัปดาห์ล่าสุดก็มี https://bugs.ruby-lang.org/issues/22071 และ https://bugs.ruby-lang.org/issues/22058
    ในแง่ประสิทธิภาพ มันก็ทำให้การทำ optimization หลายอย่างยากขึ้น และตอนนี้สิ่งคล้ายกันก็กำลังเกิดขึ้นอีกกับ boxes

    • ไอเดียของ boxes ดูเหมือนจะยัดเข้าไปทีหลังได้ยากในภาษาที่ทุกอย่างอยู่ใน global namespace เดียวกันมาหลายสิบปี
      แม้ในระดับ implementation เอง ก็น่าจะยังมีบั๊กซ่อนอยู่อีกมาก และฝั่งไลบรารีก็คงเช่นกัน
      ตอนนี้ผมไม่ได้ใช้ Ruby มากแล้ว แต่ก็อยากรู้ว่ามันจะลงเอยอย่างไร
      ดูน่าสนุกดี
  • บทความนี้ทับซ้อนกับประสบการณ์ของผมในบทความ “Returning to Rails” [1] มากเหมือนกัน
    อาจเป็น confirmation bias ก็ได้ แต่ดูเหมือนจะมีคนมากขึ้นที่กลับมาค้นพบหรืออย่างน้อยก็ยอมรับความงามของโค้ด Rails อีกครั้ง
    อย่างไรก็ตาม มันก็ทำให้นึกถึงปรากฏการณ์ที่รสนิยมทางดนตรีหรือศิลปะมักจะตกผลึกในช่วงปลายวัยรุ่นถึงวัย 20 ต้น ๆ
    คนที่ได้รู้จัก Ruby ครั้งแรกใน “ยุคทอง” ของ Rails อาจกำลังมองย้อนกลับไปยังยุคของ Rails 3 และ Capistrano ผ่าน แว่นสีชมพู อยู่หรือเปล่า
    ตอนนั้นผมจมลึกอยู่ในโลก Ruby “shop” และรอบตัวก็มีแต่คนพัฒนา Rails เลยรู้สึกเหมือน Ruby อยู่ทุกที่
    แต่เมื่อเห็นความเห็นในเธรด lobste.rs [2] ว่า Ruby จริง ๆ แล้วเป็นภาษานิชมาตลอด ก็อาจเป็นอิทธิพลจากตรงนั้นด้วย
    ถึงอย่างนั้น Ruby ก็ยังให้ความรู้สึกเหมือนบ้าน และดูเหมือนทำงานตรงกับวิธีคิดในหัวของผม
    แทบไม่ต้องมีขั้นตอนแปลความ ไม่มีอะไรให้แปลกใจ และให้ความรู้สึกเหมือนคุยกับเพื่อนมากกว่ากำลังเขียนบทความเชิงวิชาการอย่างเป็นทางการ
    ผมยังไม่เจอภาษาอื่นที่เข้ากับตัวเองได้ขนาดนี้ และไม่คิดว่ามันเป็นเพียงความคิดแบบ “เด็กสมัยนี้นี่นะ” เท่านั้น
    ยังไงก็ตาม ผมดีใจที่มันยังอยู่รอดมาได้ยาวนานขนาดนี้
    และขอบคุณที่แนะนำ chain แบบ “tap / new”
    โครงสร้างนั้นสวยและมีประโยชน์มากจนผมต้องหยุดดูอยู่พักหนึ่ง และน่าจะได้ลองใช้แน่ ๆ
    PS - แม้จะไม่เกี่ยวกับหัวข้อโดยตรง แต่ AI avatar บนหน้าโฮมเพจน่าขนลุกนิดหน่อย
    มันให้ความรู้สึก uncanny valley แบบแรง ๆ ว่า “บทความนี้บอตเป็นคนเขียนหรือเปล่า?”
    ทุกครั้งที่เห็นอะไรแบบนั้น ผมจะเผลอสงสัยอยู่ชั่วครู่ว่ากำลังคุยกับมนุษย์จริงหรือเปล่า
    [1]=https://www.markround.com/blog/2026/03/05/returning-to-rails-in-2026/
    [2]=https://lobste.rs/s/jreqtw/returning_rails_2026

    • ผมยืนยันได้เลยว่าผมเป็นคนจริง
      แค่ไม่อยากเปิดเผยรูปจริงของตัวเอง และ avatar นั้นก็คล้ายพอที่คนที่รู้จักผมจริงจะจำได้
  • Ruby 3.4 เพิ่ม พารามิเตอร์บล็อก it เข้ามา และสามารถใช้แทน _1 ในตัวอย่างได้

    items.map { it.price * 1.1 }  
    

    https://rubyreferences.github.io/rubychanges/3.4.html/…

    • ผมลืมพูดถึง it ไป
      มันเป็นฟีเจอร์ที่ค่อนข้างใหม่ เลยยังไม่ชินมือที่จะพิมพ์ it ใน iterator เอาเสียเลย
  • ผมชอบการเขียนโค้ดด้วย Ruby มากจริง ๆ แต่ ภาระเรื่องการทดสอบ มันหนักเกินไปแล้ว
    ผมคิดว่าการเพิ่ม type safety ให้ภาษาอีกสักหน่อยน่าจะช่วยได้ แต่ใน #{last_job} พอเราใส่ Sorbet ลงในโค้ดเบส แรงส่งและความสนุกในการเขียนโค้ดก็หายไปหมด
    อาจเป็นความเห็นที่ไม่เป็นที่นิยม แต่ผมมองว่าการที่มีสิ่งอย่าง Sorbet อยู่ได้ตั้งแต่แรกนั้น เป็นเหมือนกลิ่นไม่ดีของ Ruby มากกว่า
    ตัว Ruby เองเป็นภาษาที่ทรงพลังและสนุก แต่คนเริ่มเอามันไปใช้กับงานที่เดิมทีไม่ได้ออกแบบมาเพื่อรองรับ และในกระบวนการนั้นก็เริ่มเสริมเครื่องมือต่าง ๆ เพื่อกลบ anti-feature ของภาษา
    ตอนนี้ทุกบรรทัดให้ความรู้สึกเหมือนงานน่าเบื่อชวนทรมาน และผมใช้เวลารอเครื่องมือ build, test, lint ต่าง ๆ มากกว่าที่ได้เขียนโค้ดจริงเสียอีก
    พอรวมกับกระบวนการ build และ deploy ที่ออกแบบเกินความจำเป็นเข้าไปอีก แม้แต่งานพื้นฐานก็ใช้เวลานานและทำงานอย่างทุกข์ทรมาน
    ผมคิดถึงโลกของ Ruby ราวปี 2012 มาก
    มองย้อนกลับไป มันเป็นช่วงเวลาที่ดีจริง ๆ

    • จากประสบการณ์ของคุณ มีภาษาไหนที่เหมาะกว่า?
      ผมเข้าใจว่าสิ่งที่เรียกว่า “งานที่เดิมทีไม่ได้ออกแบบมาเพื่อรองรับ” หมายถึงแอปพลิเคชัน Rails ขนาดใหญ่
  • ผมกลับมาใช้ Ruby อีกครั้งหลังผ่านไป 10 ปี และในยุค “AI” การที่เราสามารถเข้าใจโค้ดที่ไหลผ่านตาไปอย่างรวดเร็วได้จริง และควบคุมหรือหยุด LLM ได้ ก็เป็นข้อดีมาก
    ในภาษาที่เยิ่นเย้อกว่านี้ มันทำได้ยากกว่า

  • ผมคิดถึง Ruby และยิ่งไปกว่านั้น ผมคิดถึงการมีอยู่ของภาษาลักษณะนั้นในงานโปรดักชันประจำวันด้วย
    มันคือความหวัง หรือไม่ก็ เป็นตัวความหวังเอง
    อย่างน้อยสำหรับผม มันเป็นแบบนั้นมาอยู่นาน

    • เกิดอะไรขึ้นเหรอ?
  • อ่านแล้วเหมือนบทความที่ AI ปั่นแบบลวก ๆ
    บล็อกโพสต์อื่น ๆ ช่วงหลังก็คล้ายกัน

    • ผมไม่รู้สึกถึงสัญญาณแบบนั้นเลย
      มีเบาะแสอะไรที่ทำให้คุณคิดแบบนั้น?
      การชี้ว่ามีบทความ AI คุณภาพต่ำในเว็บนี้เป็นเรื่องที่ดี แต่ก็ควรหลีกเลี่ยง false positive และบอกให้ชัดด้วยว่าคิดอย่างนั้นเพราะอะไร
    • สำหรับผม มันไม่ได้อ่านเหมือนบทความที่ AI ปั่นแบบลวก ๆ เลย
      ทำไมคุณถึงคิดอย่างนั้น?
      ผมชอบการเตือนแบบนี้นะ แต่จะชอบมากกว่าถ้ามีเหตุผลแนบมาด้วย
  • ผมมีความทรงจำที่ดีจากการทำงานกับ Ruby ในช่วงต้นอาชีพ
    Ruby มีบางอย่างที่ให้ความรู้สึกดีจริง ๆ
    แต่ตอนที่ผมน่าจะได้ใช้ Ruby ล่าสุดเล็กน้อยเมื่อปีที่แล้ว ผมรู้สึกว่าเอกสาร standard library แบบเว็บนั้นค้นดูยาก
    หรือมีแค่ผมคนเดียว? มีทางเลือกอื่นแทนเอกสารบน ruby-lang.org ไหม?

  • บทความนี้ให้ความรู้สึกแปลก ๆ นิดหน่อย
    ผมเคยมีโอกาสเขียนโปรเจกต์หนึ่งกับ SDK อีกตัวหนึ่งด้วย Ruby และมันทำให้ผมไม่อยากใช้ Ruby อีกเลย