Language Maturity by Library

ช่วงนึงเคยนั่งดูภาษาใหม่ๆ เผื่อจะเลือกมาเขียน

อย่างนึงที่พบคือภาษาเองไม่ได้สำคัญเท่ากับ library ที่ภาษานั้นมี เช่น คนเขียน Ruby กลุ่มใหญ่ๆ ก็ไปเพราะ Ruby on Rails, ถ้าจะเขียน data science ถ้าไม่ใช้ Python แล้วก็ทำงานลำบากมาก

ตอนที่หัด Rust แรกๆ นานมาแล้ว ตอนนั้นก็พบว่า library ของภาษาค่อนข้างมี maturity ต่ำมาก คือบางอันก็มีแต่ใช้งานไม่ได้ บางอันก็ไม่มี เลยคิดว่าทำ checklist ขึ้นมาว่าภาษาควรจะมี library อะไรบ้างถึงจะใช้งานทั่วไปได้บ้าง เวลา evaluate ภาษาจะได้ดูได้ง่ายขึ้นว่ามันพร้อมใช้งานแล้วหรือยัง

Language fundamentals

คิดว่าภาษาสมัยใหม่น่าจะมีพวกนี้อยู่แล้ว อาจจะเป็น first class เลยด้วยซ้ำคือรองรับในภาษาเลย ถ้าเป็นภาษาเก่าแบบ C อาจจะไม่มี

  • Unicode string และ function ที่จัดการกับตัวอักษร เช่น to uppercase, lowercase
  • Byte array (uint8 array) ในบางภาษามีแต่ string ก็มี ไม่สามารถเก็บ raw bytes ได้
  • Data structure ต่างๆ ที่สำคัญคือ ArrayList (Array ที่ไม่ระบุจำนวนสมาชิกล่วงหน้า) และ Map (Key-value store)
  • Threading ซึ่งถ้าเป็นภาษาเฉพาะทางหน่อยอาจจะไม่มี เช่น PHP หรือ JavaScript จะไม่อยู่ในแกนของภาษา
    • Synchronization primitives เช่น Mutex, RWLock, Barrier, Atomic operations
  • Timers ต่างๆ เช่น get time, sleep, monotonic clock (นาฬิกาที่เดินไปข้างหน้าอย่างเดียวถึงแม้ user จะปรับเวลาเครื่อง)
  • Date/Time calculation (with timezone) ซึ่งความยากคือ timezone เป็นข้อมูลที่ dynamic ประเทศต่างๆ อาจจะปรับเวลา daylight saving เมื่อไรก็ได้ บางภาษาเช่น Java ก็รวมฐานข้อมูลเข้ามาใน runtime บางภาษาเช่น Python ก็มีการเก็บ timezone แต่ไม่มีข้อมูลโลกจริงต้องไปใช้ library ภายนอก (pytz)
  • String templating พื้นฐาน ก็คือแบบ sprintf
  • Regular Expression
  • Pseudorandom และ Secure random
  • Path mutation function เช่น basename, dirname, join path
  • OS signal handler (ทำอย่างไรเมื่อโดน SIGINT?)

อีกส่วนที่จะช่วยได้เยอะ คือภาษาสามารถโหลด dynamic library ภาษา C เข้ามาได้และเรียกฟังค์ชั่นจากภาษา C ได้ซึ่งจะทำให้การต่อยอดขั้นถัดไปได้เยอะ

Interop

โปรแกรมที่ยากกว่า Programming มัธยมมักจะเริ่มต้องเชื่อมต่อกับระบบอื่นๆ บ้าง ซึ่งที่คิดว่าจำเป็นจะต้องมีคือ

  • Base64
  • JSON serializer/deserializer ซึ่งถ้าให้ดีควรจะใช้งานกับ data structure ใดๆ ของภาษาก็ได้ (POJO)
  • TCP/UDP socket
  • TLS socket ซึ่งง่ายที่สุดก็คือใช้ C FFI คุยกับ OpenSSL แต่บางภาษาก็อาจจะ implement ใน runtime แล้วไม่มี API ให้
  • Data encryption, hashing ซึ่งส่วนมากที่เห็นก็จะใช้ OpenSSL ทำเหมือนกัน
  • Byte stream encoder/decoder
  • Gzip
  • HTTP ซึ่งต้องใช้ฟีเจอร์หลายๆ ข้อด้านบน

Advanced language fundamentals

  • Unit testing library
    • Report เป็นแบบ Junit XML (ซึ่งก็น่าจะต้องมี XML encoder)
  • Documentation generator บางภาษาอาจจะไม่มีที่เขียนในภาษาตัวเอง แต่ไปแก้ tool ภาษาอื่นเช่น Sphinx, Doxygen ให้เข้าใจไฟล์ของมันได้แทน
  • Command line argument parser ผมค่อนข้าง prefer แบบ UNIX แต่บางภาษา (เช่น Go) ก็ทำแบบของตัวเองก็มี
  • Async IO บางภาษาก็ built in ไปเลย เช่น Go หรือหลายๆ ภาษาก็มี await keyword แล้วแต่ยังต้องแยก function ระหว่างประเภทที่เป็น sync กับ async ซึ่งผมคิดว่าไม่ดีเท่าไร (What color is your function?) จุดที่น่าสังเกตในภาษานั้นๆ คือใครจัดการ event loop เช่นใน Go, JavaScript นั้น runtime จัดการให้ ส่วนใน Python ถึงจะมี async แต่เราต้อง start event loop เองทำให้ทำงานลำบาก เรียกว่ามีเป็น library ยังไงก็ไม่ดีเท่า support ภายในภาษาเอง
  • Templating ขั้นสูง
    • Handlebars คิดว่าเป็นมาตรฐานต่ำสุด คือมี if, loop เท่านั้น
    • ขั้นสูงไปกว่านั้นควรจะมี variable filters (หรือ arbitrary function call), auto HTML escape, template inheritance ซึ่งถ้ามีหมดนี่ เท่าที่เห็นมักจะเป็นสไตล์ Django/Jinja (Smarty/Twig, Twigy, Pongo2)
  • Data validation ซึ่งจริงๆ เขียนเป็น if/else ก็ได้ แต่จะทำให้โค้ดรกและซ้ำซ้อน
  • Big number หรือจำนวนที่ใหญ่กว่าขนาด max int ปกติ
  • Decimal คือจำนวนทศนิยมที่แม่นยำ มักใช้ในการเงิน
  • Logging ซึ่งควรจะมีฟีเจอร์ดังนี้
    • Leveled logging คือกำหนดระดับของ log ได้ เช่น trace, debug, info, warning, error, fatal และปิดระดับที่ไม่ต้องการได้
    • Logging facility คือ config log level/output แยกตาม module ได้
    • JSON format / Human format ท่าที่น่าสนใจคือ library บางตัวเช่น bunyan ออกเป็น JSON เสมอ แล้วค่อย pipe ใส่ tool ให้จัดรูปใหม่บน client side แทน
    • Structured logging คือระบุ key-value ประกอบ log ได้โดยไม่ต้องนั่งเขียน message
  • Curses หรือ terminal GUI

Advanced interop

Standard ใหม่ๆ ที่ใช้หลายอันเริ่มมีความซับซ้อนสูงจนหลายๆ ภาษาอาจจะมีไม่ครบ ซึ่งที่คิดว่าควรจะมีคือ

  • YAML ซึ่งเป็น superset ของ JSON มี edge case มากมาย แต่ก็นิยมใช้เป็น config file จึงควรจะต้องรองรับไว้
  • Protobuf 3 ข้อนี้ผมคิดว่าค่อนข้าง opinionated เพราะ Thrift ก็มีคนใช้พอสมควรเหมือนกัน แต่คิดว่าควรจะมี binary encoding สักรูปแบบที่ portable ข้ามภาษาได้
  • HTTP/2 ผมยังไม่ค่อยเห็นคน implement API HTTP/2 ออกมาตรงๆ จะเป็นลักษณะว่าทำให้ HTTP client ใช้ HTTP/2 ได้แบบ transparent มากกว่า
  • SQL Database Access ซึ่งหลายๆ ภาษามักจะมี API กลาง (PDO, JDBC, database/sql) และ database driver แยกส่วนกันชัดเจน

Use case specific

ในขั้น use case ที่ใช้งานได้จริง ภาษาควรจะมี library พวกนี้ตามแต่ use case

  • gRPC client ถ้ามี 2 ข้อด้านบนแล้วจึงจะสามารถ implement ได้ เช่นเดียวกันผมคิดว่าข้อนี้ค่อนข้าง opinionated มากๆ มันเป็น standard ที่ซับซ้อนมากๆ และยังพอจะ design หลบไปใช้ HTTP ได้อยู่
  • gRPC server คิดว่าควรจะแยกข้อกันกับ client ด้วย ผมคิดว่า server สำคัญกว่า client แต่มักจะ implement ยากกว่า ท่าที่ gRPC เคยทำในหลายๆ ภาษา (Python, JavaScript) คือเรียกไปที่ C FFI เลย
  • Desktop GUI library ซึ่งแม้แต่ใน Go ผมก็ยังเห็นว่ามันยังไม่ค่อย mature เท่าไร
  • Graphics drawing library
  • Image processing เช่น เปิดไฟล์ภาพ ย่อขยาย ปรับสี, สว่าง มืด, blur
  • Generate QR code อาจจะเป็น terminal หรือ image
  • WebSocket client/server
  • Monitoring support เช่น Remote exception catcher, tracing, metrics
  • Unix function ต่างๆ เช่น syslog, shared memory