2 คะแนน โดย GN⁺ 2023-12-07 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Jepsen เป็นเครื่องมือสำหรับตรวจสอบ ระบบที่ทำงานพร้อมกัน (concurrent systems) เช่นฐานข้อมูล ดังนั้นโมเดล concurrency และการรองรับเธรดจริงของภาษาที่ใช้พัฒนาจึงเป็นเกณฑ์สำคัญในการเลือก
  • โครงสร้างข้อมูลแบบ immutable และ persistent ของ Clojure รวมถึงเครื่องมือ concurrency บน JVM ช่วยลดโอกาสเกิดข้อผิดพลาดในโค้ดทดสอบ และเข้ากันได้ดีกับไคลเอนต์ฐานข้อมูลที่ใช้ Java
  • งานของ Jepsen คล้ายการทดลองและการสำรวจมากกว่าการพัฒนาผลิตภัณฑ์ที่กำหนดไว้ตายตัว ฟีเจอร์ของ Clojure เช่น REPL, macro, threading macro และ EDN จึงได้เปรียบในการประมวลผลข้อมูลที่ซับซ้อน
  • แม้ประสิทธิภาพจะไม่ได้อยู่ในกลุ่มสูงสุด แต่ Clojure ที่เขียนตามแนวทางทั่วไปมักช้ากว่า Java ในระดับไม่เกินหนึ่งถึงสองหลัก และจุดที่จำเป็นก็จัดการได้ด้วยการปรับแต่งและ เครื่องมือ profiling ของ JVM
  • แม้จะมีจุดอ่อนอย่างชุมชนขนาดเล็ก การไม่มีระบบ static type ที่ประสบความสำเร็จและยอมรับกันกว้างขวาง ความไม่สะดวกในการจัดการ primitive และข้อความผิดพลาด แต่สำหรับ Jepsen ที่มีคนดูแลและใช้งาน 1–3 คน ถือเป็นการประนีประนอมที่รับได้

เงื่อนไขของภาษาที่เหมาะกับเครื่องมือทดสอบ concurrency

  • Jepsen ถูกสร้างขึ้นเพื่อทดสอบ ระบบที่ทำงานพร้อมกัน (concurrent systems) และเป้าหมายทดสอบส่วนใหญ่คือฐานข้อมูล
  • Clojure ตอบโจทย์พื้นฐานที่จำเป็นต่อการเขียนโค้ดทดสอบ concurrency ได้ดี
    • โครงสร้างข้อมูลแบบ immutable และ persistent ช่วยลดโอกาสเกิดข้อผิดพลาดในโค้ดที่จัดการ shared state
    • ใช้งานเธรดจริง, promise, future, atom, lock, queue, cyclic barrier, java.util.concurrent และอื่น ๆ ได้
    • แม้จะเคยพิจารณาภาษาที่ควบคุม side effect เข้มงวดกว่าอย่าง Haskell แต่แนวทางของ Clojure ที่ไม่ยึดหลักเคร่งครัดเกินไปเหมาะกับ Jepsen มากกว่า
  • การทดสอบฐานข้อมูลจำเป็นต้องเชื่อมต่อกับไคลเอนต์หลากหลายแบบ
    • ฐานข้อมูลแทบทุกตัวมักมี ไคลเอนต์ JVM ที่เขียนด้วย Java ให้ใช้งาน
    • Clojure มี Java interoperability ที่ดี จึงนำไคลเอนต์เหล่านี้มาใช้ได้ง่าย

ฟีเจอร์ของ Clojure ที่เหมาะกับการทดลองและสำรวจข้อมูล

  • การทดสอบของ Jepsen เป็นงานเชิงทดลอง จึงต้องการภาษาที่กระชับ เปลี่ยนแปลงง่าย และเหมาะกับการทำ prototype
    • ไวยากรณ์ที่กระชับและ ระบบ macro ของ Clojure เข้ากับรูปแบบการทำงานนี้ได้ดี
    • threading macro ทำให้การแปลงข้อมูลแบบต่อเนื่องอ่านง่ายขึ้น
    • macro ช่วยให้สร้างการจัดการข้อผิดพลาดที่ใช้ซ้ำได้และการควบคุมขอบเขตทรัพยากรได้ง่าย
    • Clojure REPL มีประโยชน์ในการสำรวจข้อมูลผลลัพธ์จากการรันทดสอบได้ทันที
  • ระหว่างการทดสอบ ต้องแสดง แปลง และตรวจสอบโครงสร้างข้อมูลที่ซับซ้อนและซ้อนกันหลายชั้น
    • โครงสร้างข้อมูลและฟังก์ชันในไลบรารีมาตรฐานของ Clojure แข็งแกร่งกับงานนี้
    • เมื่อต้องพิมพ์ข้อมูลแบบมีโครงสร้างจำนวนมากไปยังคอนโซลและไฟล์ ไวยากรณ์ข้อมูล EDN ก็เหมาะสมมาก

การประนีประนอมระหว่างประสิทธิภาพกับการบำรุงรักษาระยะยาว

  • Jepsen ไม่ใช่ระบบขนาดใหญ่มาก แต่จัดการข้อมูลในปริมาณพอสมควร จึงต้องการประสิทธิภาพที่ “ดีพอ”
    • Clojure ไม่ใช่ภาษาที่เร็วที่สุด
    • Clojure ที่เขียนตามแนวทางทั่วไปมักมีความต่างด้านประสิทธิภาพจาก Java อยู่ในระดับไม่เกินหนึ่งถึงสองหลัก
    • ในคอขวดที่สำคัญสามารถลดช่องว่างนี้ได้
    • เครื่องมือ profiling ของ JVM ทำงานร่วมกับ Clojure ได้ดี
  • Jepsen เป็นโปรเจกต์อายุราว 10 ปี จึงให้ความสำคัญกับแกนหลักที่成熟และความเสถียร
    • Clojure มีความเสถียรทั้งในแง่เป้าหมาย JVM และตัวภาษาเอง
    • ไลบรารีไม่ “เน่า” เร็วเท่า Scala หรือ Ruby

จุดอ่อนของ Clojure ที่ต้องยอมรับ

  • Clojure มีข้อเสียที่รับมือได้ในระดับขนาดของ Jepsen แต่อาจเป็นภาระสำหรับทีมที่ใหญ่กว่า
    • ชุมชนวิศวกรรมมีขนาดเล็ก
    • ไม่มี ระบบ static type ที่ได้รับการยอมรับกว้างขวางและประสบความสำเร็จ
    • Jepsen มีคนดูแลและใช้งานพร้อมกันเพียง 1–3 คน ข้อจำกัดนี้จึงส่งผลน้อยกว่า
  • เมื่อต้องจัดการ primitive ของ JVM หากไม่ลงไปใช้ Java อาจรู้สึกติดขัด และในทางปฏิบัติก็มีการใช้ Java เป็นครั้งคราว
  • บางส่วนของระบบ polymorphism ยังไม่เพียงพอ แต่สามารถใช้ไลบรารีหลีกเลี่ยงได้ และข้อความผิดพลาดก็ยังไม่ดีนัก
  • Jepsen เคยทำ prototype ด้วยหลายภาษา ก่อนตัดสินใจเลือก Clojure และแม้ผ่านไป 10 ปีแล้ว ก็ยังถือเป็นการประนีประนอมที่ค่อนข้างดี

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

 
GN⁺ 2023-12-07
ความคิดเห็นบน Hacker News
  • ในฐานะคนที่ดำเนินงาน SaaS ด้วย Clojure/ClojureScript มาราว 10 ปี เห็นด้วยกับบทความของ Kyle อย่างเต็มที่
    สิ่งที่มีคุณค่าเพิ่มเติมคือการวางโค้ดโดเมนส่วนใหญ่ไว้ใน ไฟล์ cljc ทำให้คอมไพล์ไปได้ทั้งฝั่งเซิร์ฟเวอร์และไคลเอนต์, transducer และ pipeline ของ transducer ถูกประเมินค่าต่ำไปในแง่ประสิทธิภาพ ความสามารถในการประกอบ และการนำกลับมาใช้ซ้ำ และความที่เป็นภาษาที่ Rich Hickey ออกแบบมา จึงมีเสถียรภาพและความเข้ากันได้ระยะยาวยอดเยี่ยม
    ความเข้ากันได้ย้อนหลังสำคัญมาก ทำให้เราโฟกัสกับแอปพลิเคชันได้ แทนที่จะถูกเครื่องมือที่เปลี่ยนไปเรื่อย ๆ ลากไปมา และผมคิดว่าไม่ใช่เรื่องบังเอิญที่โปรแกรมเมอร์ Clojure โดยเฉลี่ยมีประสบการณ์มากกว่า 12 ปีและได้รับค่าตอบแทนอยู่ในควอร์ไทล์บน

    • อยู่ในสถานการณ์คล้ายกัน SaaS ของผมก็รันด้วย Clojure และเมื่อเทียบกับภาษาอื่นแล้ว การบำรุงรักษา ง่ายเหมือนฝัน
      แทบไม่พัง และอัปเกรดก็ง่าย HMR, REPL, ไฟล์ cljc ทำให้ประสบการณ์นักพัฒนายอดเยี่ยม และโค้ด Clojure ก็เขียนสนุก
    • จากประโยชน์ทั้งหมด คิดว่าส่วนที่มาจาก JVM กับส่วนที่มาจากตัวภาษา Clojure เองมีสัดส่วนประมาณเท่าไร?
    • Clojure มี เว็บเฟรมเวิร์ก ที่ใช้งานได้ดีไหม?
    • ถ้าความเข้ากันได้ย้อนหลังสำคัญขนาดนั้น ผมสงสัยว่าทำไมพอเป็น C กับ C++ ถึงถูกมองเหมือนเป็นข้อยกเว้น
      ในเมื่อบอกว่าโอเคที่จะบิดภาษาและระบบให้ฝืนไปข้างหลังเพื่อไม่ให้สิ่งที่ใช้งานได้อยู่แล้วพัง แต่กลับคาดหวังให้สองภาษาที่รองรับซอฟต์แวร์ที่รันจริงจำนวนมหาศาลตัดขาดจากอดีตและปัจจุบันอันรุ่งโรจน์ ผมไม่เข้าใจว่าทำไม
  • ปัญหาใหญ่ที่สุดของ Clojure คือ ระบบนิเวศ อย่างชัดเจน
    ถ้าดูการกระจายของเครื่องมือที่เข้าถึงได้และใช้งานได้ จะพบว่าไม่ก็อยู่ปลายซ้ายสุด เป็นเครื่องมือที่แย่มากแต่เข้าถึงง่าย หรือไม่ก็อยู่ปลายขวาสุด แบบ README มีคำคมจากลอร์ดออฟเดอะริงส์ ทุกอย่างเป็นข้อมูลไปถึงลำดับที่ n และมีแต่มังกรที่เขียนปลั๊กอิน Emacs ได้ขณะถูกปิดตาแขวนกลับหัวเท่านั้นที่เข้าถึงได้
    ตัวภาษานั้นยอดเยี่ยม และการทำงานร่วมกับ Java ก็ดีกว่าที่ Aphyr พูดไว้มาก แต่ถ้า Clojure มีอะไรแบบ Rails หรือ Django หรือยิ่งดีคือ Phoenix ก็คงโน้มน้าวคนได้ง่ายกว่านี้มากและถูกใช้แพร่หลายกว่านี้
    โดยเฉพาะเวลาจะโน้มน้าวทีมให้ย้ายจากภาษา imperative ตระกูล Algol มาใช้ Lisp สิ่งที่ได้ต้องคุ้มกว่าความลำบาก แต่ตอนนี้นอกจากองค์ประกอบพื้นฐานอย่าง HTTP routing แล้ว แทบทุกโปรเจกต์ต้องประดิษฐ์ล้อขึ้นมาใหม่
    ถึงอย่างนั้น การที่ใช้แพ็กเกจ Maven ใด ๆ ก็ได้และคอมไพล์เป็น jar ได้ จึงทำให้ที่ไหนที่ jar รันได้ Clojure ก็รันได้ ถือเป็นข้อดีมหาศาล

    • ต้องลองดู Calva ปลั๊กอินยอดเยี่ยมสำหรับ VSCode ไม่ได้มีแค่ REPL แต่ยังมีฟีเจอร์อย่างเอกสารแบบเรียลไทม์ ทำให้ใช้ Clojure ได้ง่าย และผมใช้ในงานทุกวัน
      https://calva.io
    • ดูเหมือนไม่เคยเขียน Clojure เป็นงานหลัก ระบบนิเวศและชุมชนของ Clojure ได้รับการดูแลอย่างดี
      Clojure มีหลายรูปแบบ โดยหลัก ๆ ใช้ Clojure และ ClojureScript และยังมี Babashka, Scittle เป็นต้น แต่ทั้งหมดก็แตกแขนงมาจาก clj หรือ cljs
      เครื่องมือพัฒนาขึ้นอยู่กับแพลตฟอร์มและความชอบด้าน IDE เครื่องมือจึงต่างกันไปใน Emacs, Neovim, VSCode, IntelliJ และระบบ build ก็ขึ้นอยู่กับความต้องการ
      ใน clj ตอนนี้ deps.edn ถูกใช้มากที่สุด ตามด้วย leiningen ส่วน cljs นอกจาก shadow-cljs ก็ยังมีตัวเลือกอื่น ๆ
      สำหรับคนที่เพิ่งเริ่มอาจรู้สึกท่วมท้น แต่ชุมชนดีและพร้อมช่วยเสมอ ผมเขียนโปรแกรมเป็นงานหลักมาหลายภาษาแล้ว แต่ Clojure เป็นภาษาที่ชอบที่สุดอย่างไม่ต้องสงสัย
    • อยากรู้ตัวอย่างของเครื่องมือที่ “แย่มากแต่เข้าถึงง่าย”
      ผมใช้ Clojure มาตั้งแต่ราวปี 2013 แต่นึกเครื่องมือแบบนั้นไม่ออก ไลบรารียอดนิยมส่วนใหญ่ยอดเยี่ยม และในแง่เสถียรภาพ ความเข้ากันได้ย้อนหลัง และความเรียบง่าย นำหน้าระบบนิเวศส่วนใหญ่ที่ผมรู้จักไปมาก
    • อันนี้ดูเหมือนไม่ได้เกี่ยวกับ Jepsen หรือเนื้อหาบทความเท่าไร เป็นแค่คอมเมนต์ Clojure แบบสุ่มมากกว่า
    • ขอเสริมสำหรับคนที่ไม่คุ้นกับ Clojure อย่างที่ /u/jwr พูดไว้ในเธรดนี้ Clojure รันได้ในที่ที่มีเบราว์เซอร์ด้วย เพราะมี ClojureScript
      ด้วยไฟล์ซอร์ส .cljc ที่แชร์กันได้ทั้ง Clojure และ ClojureScript จึงรันโค้ด Clojure เดียวกันได้ทั้งฟรอนต์เอนด์และแบ็กเอนด์
      อย่างที่ Rich Hickey พูด ไม่ใช่แค่ JVM ที่ “เข้าถึง” ได้ แต่ JavaScript ก็เข้าถึงได้ด้วย
      ผมใช้ Emacs มานาน และท้ายที่สุดก็ปรับแต่งได้ตามต้องการหรือสร้างโค้ด elisp ที่จำเป็นได้ แต่คงพูดไม่ได้เลยว่าเก่ง elisp
      ยอมรับว่าคนที่ไม่เคยเรียน Lisp dialect ใด ๆ มาก่อน การเรียน Emacs, elisp และ Clojure พร้อมกันนั้นยาก และโน้มน้าวให้ทำได้ยากมาก
      ตอนนี้มี Clojure LSP server แล้ว และทำงานได้ไม่เฉพาะใน Emacs แต่รวมถึง IDE อื่น ๆ ด้วย ดังนั้นแม้นักพัฒนา Clojure จำนวนมากจะใช้ Emacs แต่ Emacs ก็ไม่ใช่สิ่งจำเป็นสำหรับการพัฒนา Clojure
  • ผมใช้แต่ Clojure มา 7 ปี และกำลังดูแล โค้ดเบส Clojure + ClojureScript มากกว่า 500,000 บรรทัดอย่างจริงจัง สิ่งที่ไม่พอใจที่สุดคือไม่มีระบบ type ที่แข็งแกร่ง
    ผมเห็นด้วยว่า Clojure มีพลังในการสื่อความหมายสูง เดินหน้าได้เร็ว และไม่ขวางทาง แต่ก็เปิดช่องให้เกิด runtime error เลอะเทอะที่ทำซ้ำและดีบักได้ยาก
    ถ้ามีระบบ static type ที่ได้รับการยอมรับกว้างขวางและประสบความสำเร็จ Clojure คงยอดเยี่ยมมาก ตอนนี้ผมมองว่ามันค่อนข้างดีถ้าคุณชอบ Ruby หรือ Python แต่ต้องการอะไรที่แข็งแรงกว่า และตอนนี้ก็เริ่มสงสัยว่า Go อาจเป็นทางที่ถูกหรือไม่

    • ส่วนที่วัดได้ว่า static type ช่วยได้ สามารถผสาน ภาษา JVM อื่นอย่าง Kotlin เข้าไปในโปรเจกต์ Clojure ได้
  • เห็นด้วยอย่างยิ่งว่า Clojure(Script) แทบจะเป็นพรจากสวรรค์ และเป็นตัวเลือกที่ยอดเยี่ยมสำหรับหลายโปรเจกต์ ไม่ว่าจะเล็กหรือใหญ่
    หลังจากเคยใช้ C, Python, PowerShell, Java, Bash, SQL มาบ้างเล็กน้อยในงานมหาวิทยาลัย งานดูแลระบบ การวิเคราะห์ทราฟฟิกดัมป์ ฯลฯ ภาษาแรกที่ใช้เขียนโปรแกรมแบบมืออาชีพจริง ๆ คือ Clojure
    กำลังสร้าง OrgPad ด้วย Clojure+ClojureScript และแม้โค้ดจะเกิน 100,000 บรรทัดแล้ว ก็ยังคิดว่าเป็นการตัดสินใจที่ดี
    เข้าถึงง่าย และเมื่อเขียนโค้ดไปนิดหน่อย ก็มีความมั่นใจพอสมควรว่ามันจะทำงานตามที่จินตนาการไว้ ใน Python, PowerShell, Bash ไม่ได้รู้สึกถึงระดับนี้ และรู้สึกว่าเป็นคนละชั้นกันเลย
    เวิร์กโฟลว์แบบ REPL ก็ดีมากจริง ๆ และเพื่อนร่วมงานทำวิดีโอเกี่ยวกับเรื่องนี้ไว้: https://www.youtube.com/watch?v=4igO7Qbyj9o
    ทุกวันนี้ ฟังก์ชัน งานสั้น ๆ หรือโปรเจกต์เล็ก ๆ ที่เคยทำให้ลังเลว่าจะย้ายจาก Bash ไป Python ดีไหม ก็จัดการได้ด้วย Babashka/nbb

  • ก่อนหน้านี้ตอนพยายามเขียน Clojure กับ ClojureScript สักไม่กี่พันบรรทัด ปัญหาใหญ่ที่สุดคือเครื่องมือส่วนใหญ่มีสถานะ error ที่ค่อนข้างรก
    Python ก็มีด้านคล้าย ๆ กัน ดังนั้นถ้ากด Ctrl+C หยุดโปรแกรม Python ส่วนใหญ่ ก็มักจะมี stack trace ที่ปนอะไรไม่รู้เต็มไปหมด แต่สำหรับคนเพิ่งเริ่ม มันทำให้เดินหน้าต่อยาก
    ผมคิดว่าภาษาและ ecosystem นี้มีไอเดียที่ปฏิวัติวงการและน่าสนใจอยู่มาก อย่างน้อยก็คุ้มที่จะอ่านบทความประวัติศาสตร์ของ Clojure และซึมซับบทเรียนส่วนใหญ่ไว้
    อาจฟังดูนอกรีตสำหรับทุกคน แต่ผมคิดว่ายังมีพื้นที่เล็ก ๆ ใน ecosystem สำหรับ ภาษาสคริปต์ ที่จริงจังกับ performance และ ergonomics ในการเขียนโค้ดพอ ๆ กับ Clojure แต่ไม่มีวงเล็บ
    ถ้าไม่มีแนวปฏิบัติที่ปฏิบัติกับ nil เป็นกรณีพิเศษก็คงดี แต่ตรงนั้นอย่างน้อยก็พอมีพื้นฐานอยู่บ้าง
    ผมเข้าใจว่า (f x y) ดีกว่า f(x, y) แต่ปัญหาของผมใกล้กับกรณีที่ฟอร์ม let ทำให้ต้องเยื้องมากกว่า ผมไม่คิดว่าการตั้งชื่อให้ค่าหนึ่งควรต้องจ่ายทั้งต้นทุนของการเยื้องและวงเล็บพร้อมกัน
    ถ้ามาจากภาษาอย่าง Python ที่ใช้การเยื้องซึ่งยังไงก็ต้องใส่ในโค้ดอยู่แล้วให้เป็นข้อมูล สิ่งเหล่านี้บางครั้งก็รู้สึกเหมือนเป็น noise เฉย ๆ

    • การที่ ฟอร์ม let ทำให้เกิดการเยื้อง เป็นสัญญาณเสียมากกว่าว่ากำลังใช้ let มากเกินไป
      ในสไตล์ functional มักไม่จำเป็นต้องตั้งชื่อให้ argument กลาง ๆ ที่ส่งต่อระหว่างฟังก์ชันมากนัก
      โดยทั่วไปจะใช้ threading macro อย่าง ->, ->> เพื่อส่ง argument ไปยังฟังก์ชันถัดไปโดยปริยาย หรือกำหนดตัวการแปลงเองเป็น pure function แล้ววางไว้ระดับบนสุด
      อย่างไรก็ตาม เข้าใจได้ว่าในโค้ด interoperability บางส่วนต้องใช้ let เยอะ โดยเฉพาะไลบรารี Java JWT ที่เปลี่ยน argument ใน procedural chain
    • เมื่อใช้ เวิร์กโฟลว์แบบ REPL ใน Clojure หรือ Python ก็มีสิ่งที่ได้เรียนรู้จากความผิดพลาด
      เช่น ดีบักอยู่นานแล้วเพิ่งรู้ว่าไม่ได้โหลดใหม่หรือ reinitialize
      รู้สึกว่าส่วนใหญ่แล้วเราจะเพิ่มเรื่องนี้เข้าไปใน checklist เมื่อตกอยู่ในสถานการณ์แบบ “เป็นไปไม่ได้” เช่น “ใส่ debug output เพื่อยืนยันว่าการเปลี่ยนโค้ดของเราถูกเรียกจริงหรือไม่”
      แน่นอนว่านี่เป็นแค่ตาข่ายนิรภัย และโดยหลักแล้วจะพยายามหลีกเลี่ยงสถานการณ์แบบนั้นด้วยนิสัยการทำงานกับ REPL แบบอื่น
    • มันทำให้ในหัวทรมาน เพราะเหมือนควรอ่านว่า (+ clojure clojurescript)
  • Clojure ทำหลายอย่างได้ถูกต้อง และเพราะอย่างนั้นจึงชอบมาก
    สิ่งหนึ่งที่ทำให้ทีมจริงที่ทำงานเว็บจริงด้วย Clojure ช้าลง คือความต้องการแบบแทบจะเป็นลัทธิที่จะเอาไลบรารีจำนวนมากที่ต่างคนต่างมีวิธีของตัวเองมาประกอบและผูกทุกอย่างเข้าด้วยกัน
    ถ้า community มี เว็บเฟรมเวิร์ก ที่ดูแลต่อเนื่อง มีแบตเตอรี่ให้พร้อม และโดยทั่วไปใช้งานได้จริง นอกเหนือจากแนวทางปัจจุบัน ผมคิดว่า Clojure จะได้รับความนิยมมากขึ้นและน่าใช้ขึ้นมาก สงสัยว่า Biff จะเป็นสิ่งนั้นหรือเปล่า
    อยากให้มีเส้นทางทางเลือกสำหรับคนที่ชอบภาษา แต่ไม่ชอบวิธีประกอบสัตว์ประหลาดเอง
    ส่วนหนึ่งก็เพราะถูก Ruby on Rails ทำให้เคยตัวด้วย

    • สำหรับหลายคน เสน่ห์ของ Clojure อยู่ที่การไม่มัดสิ่งต่าง ๆ เข้าด้วยกันโดยไม่จำเป็น
      เป็นแนวทางแบบในทอล์กดังของ Rich Hickey คืออย่า complect แต่ให้ compose: (https://github.com/matthiasn/talk-transcripts/blob/master/Hi...)
    • Biff ใกล้เคียงกับแบบ batteries-included มาก แต่ค่า default บางอย่างต่างจากสายหลักไปเล็กน้อย เพราะใช้ XTDB แทน SQL และใช้ HTMX/Hyperscript คนที่เพิ่งเข้ามาจึงยังอาจลำบากอยู่
      การเรียน Clojure กับ graph database และบางกรณีก็รวมถึง HTMX ด้วย ถือว่าเยอะพอสมควร ถึงอย่างนั้นก็มีการตั้งค่าหลายอย่างทำไว้ให้แล้ว authentication ก็ใส่ใจและง่าย ส่วนคอมเมนต์ในไฟล์ตั้งค่าเซิร์ฟเวอร์ก็ดี
      มีสคริปต์ deploy สำหรับตั้งค่าเซิร์ฟเวอร์ Linux และ SSH เข้า production REPL ด้วย ถ้าอยากใช้ XTDB วิธีตั้งค่า document validation ของ Biff ดีมากจริง ๆ
      โดยส่วนตัวผมชอบทางนี้มากกว่าแอปที่รันด้วย ClojureScript มี wrapper ของ ClojureScript สำหรับ React เยอะจนแทบกลายเป็นมีม แต่ในฐานะนักพัฒนา React ผมไม่รู้สึกว่าอันไหนง่ายกว่า React เลย
      กลับรู้สึกซับซ้อนและไม่ค่อยเข้ามือ ในทางกลับกัน HTMX/Hyperscript เข้ากับ Clojure ได้ดีมาก เพราะไวยากรณ์ HTML เป็นเพียง array และ object ที่จัดการได้ง่าย
      คติที่แฟน Clojure พูดซ้ำ ๆ ว่า “โค้ดคือข้อมูล” รู้สึกเป็นจริงขึ้นมาเป็นครั้งแรก
    • อย่างที่เขียนไว้ข้างบน ลองดู Luminus หรือ Kit ก็น่าจะดี
    • ในบรรดาที่เคยลองมา Biff ถูกใจที่สุด
  • เมื่อก่อนผมเคยลองใช้ OCaml ทีละนิดอยู่หลายครั้ง แต่ไม่ชอบ ระบบชนิดข้อมูล ที่เข้มงวดเกินไป
    เวลาที่ใช้ทำให้คอมไพเลอร์พอใจมีมากกว่าเวลาที่ใช้เขียนโค้ดเสียอีก ใน Clojure, Common Lisp และ C ผมมีอิสระมากกว่าที่จะบิดคอมไพเลอร์หรือระบบชนิดข้อมูลไปในทางที่ต้องการ
    แน่นอนว่ามีทั้งข้อดีข้อเสีย แต่เวลาผมเขียนโค้ด ผมไม่อยากถูกขัดจังหวะ อาจเป็นสไตล์ของผมเองก็ได้ แต่ผมเจอคนที่คิดเหมือนกันเยอะมาก
    ผมเชื่อว่าระบบชนิดข้อมูลแบบสแตติกเป็นเรื่องของรสนิยม ส่วนฝ่ายตรงข้ามคิดต่างออกไป ถึงอย่างนั้นการมีค่ายที่เห็นต่างกันก็ดี เพราะต่างฝ่ายต่างเรียนรู้จากกันได้มาก
    Rich Hickey เคยพูดหลายครั้งว่า Clojure เป็นภาษาโฮสต์ ดังนั้นเมื่อจำเป็นจะลงไปใช้ Java หรือ JavaScript ก็ได้
    โดยส่วนตัว ผมมองว่านี่เป็นหนึ่งในฟีเจอร์ที่ทรงพลังที่สุดของอีโคซิสเต็ม Clojure เพราะมันใช้งานได้จริงกว่ามาก
    ผมเห็นความพยายามมากมายที่จะนำสิ่งเดิม ๆ มาเขียนใหม่ซ้ำ ๆ ในภาษาที่ตัวเองชอบ เพียงเพราะไม่อยากแตะ “ไลบรารีที่เขียนด้วยภาษาอื่นสกปรก ๆ นั่น” เหตุผลก็หลากหลาย เช่น ช้า ไม่ปลอดภัย ไม่ยืดหยุ่น เป็นต้น
    เรื่องแบบนี้เกิดขึ้นบ่อยทั้งใน Common Lisp และในชุมชน Rust และยังเกิดอยู่จนถึงตอนนี้

    • การตรวจสอบชนิดข้อมูลเป็นเรื่องของรสนิยมจริง ๆ โดยส่วนตัวแล้วผมค่อนข้างชอบที่ภาษาช่วยกันความผิดพลาดเล็ก ๆ น้อย ๆ ให้ จึงใส่ การประกาศชนิดข้อมูล ไว้ในโค้ด Common Lisp เยอะมาก
      SBCL ช่วยรับประกันตามการประกาศเหล่านั้นให้มากที่สุด และน่าจะช่วยประหยัดอาการปวดหัวไปได้โปรเจกต์ละหลายนาที
      และ CL ก็ใช้งานได้จริงมาก เช่น กรณีที่ woo มีพื้นฐานจากไลบรารี C ก็ไม่มีใครแปลกใจหรือสนใจเป็นพิเศษ
    • ตอนที่นำ ทีมความน่าเชื่อถือสูง ใน Big Tech ผมอยากใส่สแตติกไทป์ที่เข้มงวดให้ทุกที่ตั้งแต่เมื่อวานแล้ว
      ปัญหาการปฏิบัติการทั้งหมดล้วนเกี่ยวข้องกับประเด็นเล็ก ๆ และละเอียดอ่อน เช่น การอัปเกรดรันไทม์ทำให้ลำดับคีย์ JSON เปลี่ยน จนไคลเอนต์เก่าที่แกะ JSON เองพัง หรือไลบรารีที่อยู่ลึกในสแต็กเริ่มคืนค่า HTTP code เป็นจำนวนเต็มแทนที่จะเป็นสตริง ทำให้การแยกวิเคราะห์ข้อผิดพลาดพัง
      ด้วยขนาดการปฏิบัติการ แม้ลูกค้าเพียงส่วนน้อยได้รับผลกระทบ ก็จะมีรายงานปัญหาเข้ามาหลายร้อยรายการ ดังนั้นทุกเหตุขัดข้องจึงเป็นเรื่องใหญ่
      ตอนนี้ผมทำงานในสตาร์ทอัพเล็ก ๆ และมันต่างกันโดยสิ้นเชิง เราเลือกภาษาแบบสแตติกเพราะเป็นสิ่งที่ดึงดูดความสนใจและบุคลากรได้มากกว่า แต่ผมก็คิดถึงช่วงที่ทำงานกับภาษาไดนามิก
      เพราะต้องปล่อยของเร็ว คุณภาพโค้ดจึงแย่ลงจริง ๆ ด้วยข้อจำกัดด้านเวลา แทนที่จะสู้กับระบบชนิดข้อมูลและรีแฟกเตอร์ให้สะอาด เรากลับคัดลอกโครงสร้างออบเจกต์เดียวกันที่แตกต่างกันเล็กน้อยไว้หลายชุดและใช้ตามที่ต่าง ๆ
      เพราะรูปทรงของชนิดข้อมูลทำให้การทำให้เป็นทั่วไปยุ่งยาก เราจึงคัดลอก/วางลอจิกเดิมไป 10 ที่ แทนที่จะแยกฟีเจอร์ออกมาให้หลายจุดอ้างอิง
      ผมคิดว่าวิธีแก้ที่เหมาะสมขึ้นอยู่กับโดเมนของปัญหา หากคุณถูกเรียกกลางดึกเพราะบั๊กละเอียดอ่อน สแตติกไทป์ที่เข้มงวดก็น่าจะเป็นคำตอบที่ถูก
      หากคุณต้องวนรอบพัฒนาอย่างรวดเร็ว และปัญหาสามารถแก้ได้ด้วยอีเมลหรือข้อความ Slack เพียงฉบับเดียว ไดนามิกไทป์อาจดีกว่า
      เคล็ดลับคืออย่าสะสมหนี้ในพาราไดม์ไดนามิกมากเกินไป เผื่อวันที่เติบโตแล้วต้องย้ายไปสู่พาราไดม์สแตติก
      น่าเสียดายที่ภาษาที่มีแฟนพันธุ์แท้จำนวนมากดูเหมือนจะไหลไปสู่ท่าทีว่า “ไม่อยากใช้ไลบรารีของภาษาอื่น” ได้ง่าย
  • Clojure เป็นภาษาที่ผมชอบที่สุดอย่างชัดเจน และให้ความรู้สึกเป็นธรรมชาติ
    แต่มีสองอย่างจากภาษาอื่นที่ผมคิดถึงจริง ๆ คือ ข้อความแสดงข้อผิดพลาด ที่เข้าใจได้ และ type hint
    ที่บริษัท ผมต้องรีแฟกเตอร์โค้ดขนาดใหญ่ และมันเจ็บปวดมาก เป็นเรื่องยากที่จะรู้ว่าฟังก์ชันไหนจะโยนข้อยกเว้นหรือแค่คืนค่า nil และยังยากที่จะรู้ว่าฟังก์ชันหลักจะคืนค่าเป็นเวกเตอร์ เป็นซีเควนซ์ หรือเป็นคอลเลกชันแบบอื่น
    มีโปรเจกต์อย่าง spec, malli, typed clojure ที่พยายามแก้ปัญหานี้ แต่ผมไม่รู้สึกว่ามันเป็นทางเลือกแทนที่ใกล้เคียงกับชนิดข้อมูลของ Python หรือ TypeScript

    • อาจเป็นเพราะผมคุ้นเคยกับภาษาสมัยใหม่ที่มีฟีเจอร์แบบนี้ หรืออาจเป็นเพราะภาษาที่ไม่มีฟีเจอร์นี้กำลังค่อย ๆ แปะเพิ่มทีหลังเหมือน Python/TypeScript แต่ผมสงสัยจริง ๆ ว่าคนทนกับมันได้อย่างไร
      ภาษาที่บอกไม่ได้ว่าอะไรเข้าและอะไรออกจากฟังก์ชัน แทบจะดูไม่มีคุณค่าในโค้ดเบสที่เกินไม่กี่ไฟล์
      การพยายามอนุมานชนิดข้อมูลจากสิ่งที่โค้ดปัจจุบันดูเหมือนทำกับออบเจกต์ได้ คือการหาเรื่องเจ็บปวดให้ตัวเอง
  • หากเพิ่งเริ่มรู้จัก Clojure ลองดู บทเรียนแบบอินเทอร์แอคทีฟ นี้ได้: https://tryclojure.org

    • https://4clojure.oxal.org/
      เป็นชุดการเรียนรู้แบบอินเทอร์แอคทีฟที่ดีกว่า ไล่ตั้งแต่ระดับง่าย ไปจนถึงระดับกลางและยาก
  • Clojure สนุก

    • เรื่องนี้ถูกประเมินค่าต่ำเกินไป อาจฟังดูไม่เป็นมืออาชีพ แต่ ความสนุก ก็เป็นเหตุผลที่ Basecamp และ Ruby on Rails ถูกสร้างด้วย Ruby เช่นกัน
      Rails ครองการพัฒนาเว็บในยุค 2010 และมีสตาร์ทอัพที่ประสบความสำเร็จอย่างมหาศาลจำนวนมากสร้างอยู่บนมัน
      มีคนจำนวนมากล้อเลียนวิศวกรว่า “เล่นของเล่น” แต่สิ่งดี ๆ จำนวนไม่น้อยที่เรามีในตอนนี้ ครั้งหนึ่งก็เคยเป็นของเล่นมาก่อน Linux ก็เป็นตัวอย่างที่ดี
    • เป็นคำอธิบายที่จับความรู้สึกนั้นได้อย่างสมบูรณ์ ผมเคยเขียนถึงอารมณ์นั้นไว้ด้วย [1]
      สิ่งที่ tricky ของภาษาที่ “สนุก” มาก ๆ คือมันทำให้เราสมมติว่าแก้ทุกอย่างด้วยภาษานั้นได้
      สุดท้ายก็เขียนโค้ดไปเยอะ แต่เมื่อมองย้อนกลับไป การไม่เขียนโค้ดอาจเป็นทางออกที่ดีพอแล้วก็ได้
      [1] https://franz.hamburg/writing/clojure-makes-happy.html