4 คะแนน โดย GN⁺ 2023-10-07 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • คีย์โน้ต Strange Loop ของ Julia Evans ว่าด้วยเหตุผลที่เทคโนโลยีซึ่งดูเหมือน “พื้นฐาน” อย่าง DNS, Bash, HTTP และ SQL กลับใช้เวลาเรียนรู้นาน และ วิธีลดกำแพงการเรียนรู้
  • ความยากของ Bash อยู่ที่มี ข้อยกเว้นเล็ก ๆ และกับดัก มากมาย เช่น set -e จะถูกปิดการทำงานเมื่อเรียกฟังก์ชันภายในเงื่อนไข || และหลายคนก็ใช้ Bash เพียงเป็นครั้งคราว จึงจำรายละเอียดให้แม่นได้ยาก
  • HTTP และ SQL มี ความซับซ้อนที่ซ่อนอยู่หลังพื้นผิวที่ดูเรียบง่าย เช่น implementation ของเบราว์เซอร์ที่มีโค้ดระดับ 20 ล้านบรรทัด, header และ flag จำนวนมาก, และความต่างระหว่างลำดับการเขียน SQL กับลำดับการทำงานจริง ทำให้ภาระในการเรียนรู้สูงขึ้น
  • DNS ทำงานผ่านไลบรารี, แคช และการสื่อสารกับ authoritative nameserver ซึ่งผู้ใช้มองไม่ค่อยเห็น และ output ของ dig ก็ซับซ้อน จึงทำให้ เครื่องมือและเดโมที่เผยให้เห็นการทำงานที่ซ่อนอยู่ มีความสำคัญ
  • การช่วยให้เรียนรู้ได้ดีควรมีทั้งการแชร์เครื่องมือและ reference, การย่อรายการใหญ่ให้เหลือรายการเล็กที่ใช้จริง, การอธิบายสิ่งที่คอมพิวเตอร์ทำตามลำดับเวลา, และการแบ่งปันทั้งเรื่องล้มเหลวและบันทึกบั๊ก

ทำไมเทคโนโลยีที่ดู “พื้นฐาน” ถึงใช้เวลาเรียนนาน

  • คีย์โน้ต Strange Loop Making Hard Things Easy พูดถึงวิธีทำให้เทคโนโลยีที่เรียนยากเข้าใจได้ง่ายขึ้น
  • จุดเริ่มต้นคือ DNS
    • การหา IP address ของโดเมนดูเหมือนง่าย แต่ผู้บรรยายบอกว่าหลังจากเริ่มเรียน DNS ไปแล้ว 7 ปี ก็ยังเจอปัญหาระหว่างตั้งค่าเว็บไซต์ และโดยรวมแล้วใช้เวลาราว 10 ปี
    • เพื่อนของเธอก็เจอปัญหาเดิมซ้ำ ๆ และหลายคนมักรับมันเป็นปัญหาส่วนตัวราวกับว่า “ควรจะเข้าใจได้แล้ว”
  • ผู้บรรยายจึงเริ่มสำนักพิมพ์เล็ก ๆ ชื่อ Wizard Zines เพื่อเขียนอธิบายหัวข้อเหล่านี้ให้เข้าใจง่ายขึ้น โดยใช้ Bash, HTTP, SQL และ DNS เป็นกรณีศึกษา

Bash: ข้อยกเว้นที่จำยากควรให้เครื่องมือช่วยจำ

  • Bash เป็นภาษาโปรแกรม แต่ก็เป็นหนึ่งในภาษาที่ผู้บรรยายใช้แล้วรู้สึกว่ามี พฤติกรรมประหลาด มากที่สุด
  • ในสคริปต์ตัวอย่าง แม้ mv ./*.txt /tmmpp จะล้มเหลว Bash ก็จะไม่หยุดโดยอัตโนมัติ และยังรัน echo "success!" ต่อ
    • ถ้าใช้ set -e ก็สามารถทำให้หยุดเมื่อเกิดความล้มเหลวได้
    • แต่ถ้าเรียกฟังก์ชันในเงื่อนไขอย่าง f || echo "failed!" ค่า set -e ภายในฟังก์ชันจะถูกปิดการทำงานทั่วทั้งฟังก์ชัน ทำให้สุดท้ายยังพิมพ์ success ออกมาอีก
    • พฤติกรรมนี้ไม่ใช่บั๊กของ Bash แต่เป็นพฤติกรรมที่มีการระบุไว้ในเอกสาร
  • เหตุผลหนึ่งที่ Bash ยากคือหลายคนเขียนสคริปต์ Bash แค่ ทุก 6 เดือนครั้ง แล้วก็ไม่ได้กลับมาดูอีก
    • ถ้าระบบที่ใช้นาน ๆ ครั้งเต็มไปด้วยความรู้จุกจิกและกับดัก ก็จะใช้อย่างถูกต้องได้ยาก
  • คำพูดแนว ๆ ว่า “ไม่มีใครใช้ Bash เป็น” ไม่ตรงกับความจริง
    • มีคนจำนวนมากใช้ Bash อยู่ และถึงจะไม่สมบูรณ์แบบก็ยังใช้แก้งานได้บ่อย
    • เป้าหมายคือพาคนที่ยืนงงอยู่หน้ากองกับดักมหาศาล ไปสู่จุดที่ “ใช้งานได้ค่อนข้างถูกต้องเป็นส่วนใหญ่”
  • ShellCheck เป็นเครื่องมือที่ช่วยจำกับดักของ Bash ที่คนจำเองได้ยาก และเตือนแทนมนุษย์
    • shellcheck -o all bad-again.sh จะแสดงคำเตือน SC2310 ว่า set -e ถูกปิดการทำงานเมื่อฟังก์ชันถูกเรียกในเงื่อนไข ||
    • การตรวจนี้จะปรากฏก็ต่อเมื่อรันด้วย -o all
    • เครื่องมือแบบนี้ช่วยย้ายภาระของความรู้จุกจิกไปให้คอมพิวเตอร์ ลดภาระทางความคิดของคน

เรื่องเล่าความล้มเหลวช่วยตัดสินใจได้มากกว่า “best practices”

  • ถึงจะไม่ได้สร้างเครื่องมือเอง การบอกเพื่อนหรือเพื่อนร่วมงานถึงเครื่องมือที่มีประโยชน์และใช้อยู่แล้วก็สำคัญ
    • ผู้บรรยายบอกว่าตัวเองก็เพิ่งมารู้จัก ShellCheck ช้าไปมาก และโกรธที่ก่อนหน้านั้นไม่รู้ว่าจริง ๆ แล้วไม่จำเป็นต้องจำทุกอย่างไว้ในหัว
  • การแชร์กับดักและเรื่องเล่าความล้มเหลวใกล้เคียงกับ การทำประโยชน์ให้ชุมชน
    • กรณี set -e ถูกปิดใน Bash เป็นสิ่งที่เธอเพิ่งเรียนรู้จากเพื่อนชื่อ Jesse ไม่กี่สัปดาห์ก่อน
    • ถ้าเรารู้เรื่องที่คนอื่นเคยพลาด ก็หลีกเลี่ยงปัญหาเดียวกันได้โดยไม่ต้องเจอเอง
  • แทนที่จะมีความเห็นแรง ๆ อย่าง “ไม่มีใครควรใช้ Bash” เรื่องเล่าว่า Bash ทำให้เกิดปัญหาอะไรจริง ๆ จะมีประโยชน์มากกว่า
    • บางคนอาจฟังแล้วตัดสินใจใช้ ShellCheck และคงสคริปต์ Bash ง่าย ๆ ต่อไป
    • บางคนอาจตัดสินใจว่าไม่อยากใช้ Bash เลย
    • ต่อให้แต่ละคนตอบสนองต่อกรณีเดียวกันต่างกัน ก็ไม่เป็นไร

HTTP: ต้องเข้าใจโดยมีเบราว์เซอร์ 20 ล้านบรรทัดเป็นฉากหลัง

  • HTTP response อาจดูเหมือนมีโครงสร้างง่าย ๆ คือ status code, header และ body
  • แต่คำถามว่า “ทำไมต้องตั้ง header นี้” ก็นำไปสู่ พฤติกรรมของเบราว์เซอร์ ทันที
    • Firefox มีโค้ดประมาณ 20 ล้านบรรทัด
    • เบราว์เซอร์พัฒนามาตั้งแต่ยุค 1990s และ security model ก็เปลี่ยนไปเรื่อย ๆ ตามการโจมตีและการเปลี่ยนแปลงของเว็บ
  • ถ้าอยากเข้าใจว่าทำไมหัวข้อหนึ่งถึงยาก ต้องดูว่ามี codebase ขนาดมหาศาลอยู่เบื้องหลังหรือไม่
    • ไม่ใช่แค่ HTTP อย่างเดียว แต่รวมถึง CSS, JS ฯลฯ ด้วย ทว่าความซับซ้อนของเบราว์เซอร์สมัยใหม่ก็ช่วยอธิบายกำแพงการเรียนรู้ของ HTTP ได้ดี
  • รายการใหญ่ควรถูกย่อให้เป็น รายการเล็ก เพื่อให้เข้าใจง่ายขึ้น
    • รายการ HTTP request header มีมากกว่า 43 รายการ และยังมี header ที่ไม่เป็นทางการอีก
    • ผู้บรรยายพูดถึง 15 header ที่ตัวเองรู้จักและใช้จริงใน การ์ตูน HTTP request headers
    • “header ที่สำคัญที่สุด” ไม่ใช่รายการแบบวัตถุวิสัย แต่เป็นรายการเชิงอัตวิสัยตามสิ่งที่ตัวเองรู้และใช้
    • เช่น แค่รู้ว่าเมื่อตั้ง Accept-Encoding เป็น gzip ก็จะได้ response แบบบีบอัด สำหรับส่วนใหญ่ก็มักเพียงพอแล้ว
  • เครื่องมือ command line ก็อธิบายด้วยแนวทางเดียวกันได้
    • man page ของ grep มี flag มากมาย แต่ผู้บรรยายบอกว่าแม้จะใช้ grep มา 20 ปี ก็ยังไม่ได้รู้ทั้งหมด
    • ถ้าคนมีประสบการณ์บอกว่า “ฉันรู้แค่ 7 อย่างในระบบนี้ และมันคือสิ่งเหล่านี้” ก็ช่วยมือใหม่ได้มาก
    • และคนมีประสบการณ์อีกคนก็อาจรู้ “7 อย่าง” อีกชุดหนึ่ง

reference ควรถูกแชร์อย่างตรงไปตรงมาว่าใช้อะไรจริง

  • สำหรับข้อมูลที่ใส่ไว้ในหัวคนไม่ได้ จำเป็นต้องมี reference ที่ดี
  • ผู้บรรยายบอกว่าตัวเองเรียน CSS แบบเป็นช่วง ๆ มา 20 ปี แต่เพิ่งรู้จัก CSS-Tricks ในช่วงประมาณ 2 ปีล่าสุด และคิดว่าถ้ารู้จักเร็วกว่านี้ก็คงช่วยได้มาก
    • แม้ CSS-Tricks หลังการเข้าซื้อกิจการจะดูเหมือนหยุดลงบทความใหม่ตั้งแต่เดือนเมษายน แต่บทความเก่าก็ยังมีประโยชน์อยู่มาก
  • สำหรับ HTTP เธอใช้ Mozilla Developer Network บ่อยมาก
  • ส่วน reference ทางการของ HTTP คือ RFC 9110, 9111, 9112, 9113, 9114) ที่เขียนในปี 2022
    • ใช้ค้นหารายละเอียดอย่างพฤติกรรมที่แน่นอนของ header Connection ได้
    • ปกติ reference หลักของผู้บรรยายมักเป็น MDN แต่ก็ชื่นชมว่า RFC ทางการจัดระเบียบไว้ดีมาก
  • เวลาจะแชร์ reference ควรแยกให้ออกระหว่างสิ่งที่แชร์เพราะมันดูเท่ กับสิ่งที่ใช้งานจริงในงานประจำ
    • ต่อให้ในชีวิตจริงใช้ reference ที่ “ดูไม่เท่” อย่าง w3schools ก็สำคัญที่จะพูดตรง ๆ ว่าใช้อยู่จริงหรือไม่

SQL: อธิบายสิ่งที่คอมพิวเตอร์ทำตามลำดับเวลา

  • SQL อาจทำให้ผู้เริ่มต้นสับสน เพราะลำดับที่เขียน query ไม่ตรงกับลำดับการทำงานเชิงแนวคิดจริง
  • mental model สำหรับ SQL ที่ผู้บรรยายใช้มีลำดับดังนี้
    • FROM
    • WHERE
    • GROUP BY
    • HAVING
    • SELECT
    • ORDER BY
    • LIMIT
  • ฐานข้อมูลจริงมีการ optimize จึงซับซ้อนกว่านี้ แต่ โมเดลตามลำดับเวลา นี้ก็ยังมีประโยชน์ในสถานการณ์ส่วนใหญ่
    • มันเกือบเหมือนกับลำดับที่เขียนใน query ต่างกันตรงที่ SELECT มาเป็นลำดับที่ห้า
  • วิธีตั้งคำถามว่า “คอมพิวเตอร์ทำอะไรก่อนจริง ๆ” ยังใช้กับหัวข้ออื่นได้ด้วย
    • ใน CORS สามารถเขียนการสื่อสารทั้งหมดระหว่างเบราว์เซอร์กับเซิร์ฟเวอร์ตามลำดับเวลาเพื่อทำความเข้าใจได้
    • ผู้บรรยายยก การ์ตูน CORS เป็นตัวอย่างของวิธีนี้
  • การอธิบายตามลำดับเวลาดูเหมือนง่าย แต่จริง ๆ ทำได้ยาก จึงมีประโยชน์มากต่อการทำงานร่วมกัน
    • Behind Hello World on Linux อธิบายว่าเกิดอะไรขึ้นบ้างเมื่อรัน “hello world” บน Linux
    • ผู้บรรยายเคยเขียน บทความคล้ายกัน เมื่อ 10 ปีก่อน แต่บทความปี 2023 ยาวกว่าประมาณ 6 เท่า
    • ไม่ใช่เพราะ Linux ซับซ้อนขึ้น แต่เพราะในปี 2013 เธอยังรู้ไม่มากพอว่ามีอะไรเกิดขึ้นตามลำดับเวลาบ้าง
  • ในทีมเองก็ทำแบบนี้ได้ เช่น ถ้าคำขอเข้ามาที่ API endpoint หนึ่ง แล้วร่วมกันวาด timeline ตามลำดับเวลา ก็จะช่วยเชื่อมความรู้ที่แต่ละคนมีอยู่เข้าด้วยกัน

DNS: ต้องเผยให้เห็นระบบที่ซ่อนอยู่จึงจะเกิดสัญชาตญาณ

  • DNS เป็นระบบที่เบราว์เซอร์, ฟังก์ชันไลบรารีที่ส่ง DNS request, แคช และ authoritative nameserver ทำงานร่วมกัน
  • ปัญหาคือหลายส่วนในนี้ ถูกซ่อนจากผู้ใช้
    • ไม่ง่ายที่จะรู้ว่าโค้ดไลบรารีส่วนไหนเป็นคนส่ง DNS request
    • แคชเก็บข้อมูลภายในไว้และตรวจสอบได้ยาก อีกทั้งผู้ใช้ก็ไม่ได้ควบคุมมัน
    • การสื่อสารระหว่างแคชกับ authoritative nameserver ก็ไม่ปรากฏให้เห็น
  • ผู้บรรยายสร้าง DNS server ขนาดเล็กชื่อ Mess With DNS ร่วมกับเพื่อนชื่อ Marie
    • ผู้ใช้สามารถสร้าง DNS record ให้โดเมนได้
    • ทุกครั้งที่มี request เข้ามาจาก resolver ระบบจะแสดงให้เห็นว่ามีข้อความอะไรเข้ามา
    • ในเดโมของ Strange Loop เธอสร้าง CNAME record ให้ชื่อ strangeloop ชี้ไปที่ orange.jvns.ca และเห็นว่า DNS resolver ในแคนาดาที่เบราว์เซอร์ใช้ส่งคำขอ A และ AAAA record มา
  • อีกตัวอย่างของการเผยให้เห็นสิ่งที่ซ่อนอยู่คือ float.exposed
    • สามารถปรับ significand และ exponent ของเลข floating point 32-bit แล้วดูเลข floating point ถัดไปและการเปลี่ยนแปลงของช่วงห่างได้
  • อีกเหตุผลที่ DNS ยากคือมันเป็น distributed system ขนาดมหึมา
    • ผู้บรรยายพูดในทำนองว่า “อาจมีคอมพิวเตอร์มากกว่า 5 ล้านเครื่องเกี่ยวข้อง” ซึ่งผู้ใช้ควบคุมแทบไม่ได้ และบางส่วนก็อาจทำงานไม่ตรงกับที่คาด

เมื่อเครื่องมือเองกลายเป็นกำแพงการเรียนรู้ เช่น output ของ dig

  • output ของเครื่องมือ DNS เองก็เพิ่มความสับสนได้
  • dig มี flag +norecurse
    • ใช้ขอให้ resolver ส่งกลับเฉพาะผลลัพธ์ที่มีอยู่ในแคชแล้ว
    • dig +norecurse jvns.ca ใช้ตรวจได้ประมาณว่า resolver นั้นได้แคชโดเมนนั้นไว้ในช่วง 5 นาทีที่ผ่านมาหรือไม่
  • output ของ dig อาจทำให้ผู้เริ่มต้นรู้สึกว่า DNS ซับซ้อนกว่าที่เป็นจริง
    • ผู้บรรยายมองว่านี่ใกล้เคียงกับการที่รูปแบบ output ซึ่งค่อนข้างตามอำเภอใจและถูกกำหนดตั้งแต่ยุค 1990s ยังคงถูกใช้มาจนถึงทุกวันนี้
  • “eraser eyes” คือวิธีมองข้าม output ที่ซับซ้อนโดยเหมือนลบทุกอย่างทิ้ง เหลือไว้เฉพาะส่วนที่ต้องดูจริง
    • ในตัวอย่างจะสนใจเฉพาะ response code SERVFAIL
    • ตามความเข้าใจของผู้บรรยาย SERVFAIL ในบริบทนี้มีความหมายใกล้เคียงกับ “ไม่มีอยู่ในแคช”
  • เวลาสาธิตเครื่องมือ ถ้าบอกด้วยว่าควรดู output หรือ UI ส่วนไหน และควรไม่สนใจส่วนไหน ก็จะช่วยให้เรียนรู้ได้มาก
    • dig แม้ output จะหยาบ แต่ก็มีฟังก์ชันเยอะ รองรับ +norecurse มีอยู่แทบทุกที่ และมีข้อดีตรงความเสถียรเพราะแทบไม่เปลี่ยนมานาน

บทบาทต่าง ๆ ในการช่วยกันทำให้เรื่องยากง่ายขึ้น

  • การทำให้เทคโนโลยีเข้าใจง่ายขึ้นเป็นสิ่งที่แบ่งปันกับคนรอบตัวได้ แม้จะไม่มีบล็อกส่วนตัว
  • วิธีที่ผู้บรรยายสรุปไว้มีดังนี้
    • แชร์ เครื่องมือ ที่มีประโยชน์
    • แชร์ reference ที่ใช้งานจริง
    • อธิบายสิ่งที่เกิดขึ้นในคอมพิวเตอร์ตามลำดับเวลา
    • ย่อรายการใหญ่ให้เป็นรายการเล็กที่ตัวเองใช้จริง
    • แสดงให้เห็นพฤติกรรมที่ซ่อนอยู่
    • สาธิตเครื่องมือที่ชวนสับสน พร้อมบอกว่าควรดูตรงไหน
  • คนที่ช่วยได้ก็มีหลายแบบ
    • “ผู้ใช้เก๋า ๆ ที่ชอบบ่น” ช่วยเล่าว่าเมื่อก่อนอะไรเคยผิดพลาดบ้าง จึงช่วยลดความลำบากให้คนอื่น
    • “มือใหม่เสียงดัง” ช่วยถามว่า “สิ่งนี้ทำงานอย่างไร?” ทำให้คนอื่นรู้สึกโล่งใจว่าไม่ได้งงอยู่คนเดียว
    • ถ้า senior developer ถามสิ่งที่ตัวเองไม่รู้ต่อหน้าคนอื่น ก็ช่วยให้คนที่กังวลว่าจะถูกมองว่าไม่รู้ กล้าเรียนรู้ไปด้วยกัน
    • “ผู้บันทึกบั๊ก” ช่วยจดว่าเกิดอะไรขึ้น เพื่อไม่ให้บั๊กเดิมกลับมาอีก
    • “ผู้สร้างเครื่องมือ” ใช้โค้ดทำให้ปัญหาง่ายลงอย่างถาวร แทนการต้องอธิบายซ้ำ ๆ
    • “ผู้แชร์สิ่งที่เพิ่งเรียนวันนี้” ช่วยแบ่งปันเครื่องมือใหม่ บั๊กที่เจอ หรือฟีเจอร์ใหม่ของไลบรารีที่เพิ่งรู้
    • “คนที่เปิดแท็บไว้ 700 แท็บ” อาจรู้แล้วว่าควรไปหาข้อมูลจากที่ไหน
    • ยังต้องมีทั้ง “คนที่ตอบคำถาม” และ “คนที่เขียนเก็บไว้ให้ค้นเจอทีหลัง”
  • การรู้สึกว่าสิ่งที่ดูพื้นฐานนั้นยาก ไม่ใช่ปัญหาของใครคนเดียว
    • คนจำนวนมากติดอยู่ที่จุดเดียวกันด้วยเหตุผลแบบเดียวกัน
    • ถ้าเข้าใจเหตุผลที่ทำให้มันยาก เราก็จะแก้ปัญหาได้ดีขึ้น เหมือนกับการแก้บั๊กของโปรแกรมคอมพิวเตอร์
  • ปัจจัยที่ทำให้มันยากมีทั้งความรู้จุกจิกมหาศาลและกับดัก, โค้ดระดับ 20 ล้านบรรทัด, ระบบที่ซ่อนอยู่, และ output ของเครื่องมือที่สับสนและไม่ได้รับการปรับปรุง
  • ผู้บรรยายบอกว่ายังไม่เข้าใจดีนักว่าทำไม Git ถึงยาก แต่ก็ยังเป็นหัวข้อที่อยากคิดต่อและพยายามทำความเข้าใจต่อไป

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

 
GN⁺ 2023-10-07
ความคิดเห็นบน Hacker News
  • ส่วนที่โดนใจที่สุดคือคำว่า จงแสดงสิ่งที่ปกติถูกซ่อนไว้
    เครื่องมือแบบนี้แทบจะทำให้สถานการณ์ชัดเจนขึ้นได้ทันที ลองนึกถึง developer tools ของเว็บเบราว์เซอร์ดู ใน “ยุคมืด” ที่ยังไม่มีของแบบนั้น มันแย่มากเพราะเรามองไม่เห็นว่าเกิดอะไรขึ้นและต้องเดาเอาเอง
    เครื่องมืออย่าง Wireshark ที่แสดง byte ของแพ็กเก็ตเครือข่ายที่เข้าถึงได้ และยัง parse โครงสร้างให้ด้วย ไม่ได้มีประโยชน์มากแค่กับการ debug เครือข่ายเท่านั้น แต่ยังมีประโยชน์มากในการสอนแนวคิดเครือข่ายด้วย เพราะมันไม่ซ่อนอะไรเลย
    ผมชอบซอฟต์แวร์โอเพนซอร์สด้วยเหตุผลนี้เช่นกัน เพราะสามารถดูซอร์สเพื่อเข้าใจสาเหตุของบั๊ก เติมช่องว่างความรู้ที่เอกสารทิ้งไว้ หรือเรียนรู้แนวคิดการเขียนโปรแกรมเพิ่มเติมได้ จึงไม่มีอะไรถูกซ่อนไว้

    • ในสายพัฒนาเกม เครื่องมือที่เข้าข่ายนี้คือ renderDoc ตอนที่รู้ครั้งแรกว่ามันมีอยู่ ผมทึ่งมากจริง ๆ
    • Wireshark ยอดเยี่ยมก็จริง แต่ไม่ได้แสดงทุก byte ที่เครือข่ายขนส่งมา
      ตัวอย่างเช่น มันไม่เคยแสดง Ethernet preamble เลย, แสดง Ethernet frame checksum แค่บางครั้ง และไม่เคยแสดง inter-frame gap ซึ่งเป็นองค์ประกอบจำเป็นของโปรโตคอล Ethernet
      ถึงจะใกล้เคียงมากแล้ว แต่ก็แสดงให้เห็นว่าไม่ว่าที่ไหนก็ยังมีรายละเอียดซ่อนอยู่อีกเสมอ
    • ความฝันคือการทำให้ทุกอย่าง มองเห็นเป็นภาพได้ ตอน runtime ถ้าทำได้แบบนั้น ผมคิดว่าการประมวลผลทั้งหมดจะเรียบง่ายมากและซับซ้อนน้อยลงมาก
      ในหัวเราก็ visualize อยู่แล้ว และคำอธิบายใด ๆ เกี่ยวกับ computing สุดท้ายก็ถูกแสดงเป็น diagram ได้ แต่ตอนเขียนโค้ดกลับไม่มี diagram เลย
      ก็แค่ instrument โค้ดทั้งหมดแบบ dynamic แล้วส่งข้อความไปที่ GUI ก็พอ
    • ตรงกันข้ามกับคำว่า “จงแสดงสิ่งที่ปกติถูกซ่อนไว้” และ “เครื่องมือแบบนั้นทำให้สถานการณ์ชัดเจนขึ้นแทบจะทันที” เครื่องมือ DevOps สมัยนี้กลับดูเหมือนซ่อนสิ่งต่าง ๆ มากขึ้นเรื่อย ๆ
      ผู้เชี่ยวชาญที่เคยมีความรู้นั้นและสอนได้ ตอนนี้ก็ไม่ได้อยู่ในองค์กรแล้ว แต่ไปรวมตัวกันอยู่ที่บริษัททำเครื่องมือเหล่านั้น
    • สิ่งที่ผมชอบใน Magit สำหรับ Emacs ก็คือแบบนี้ UI ฉลาดและลื่นไหลมาก จนอาจเป็น Git frontend ที่ดีที่สุดในบรรดาที่เคยใช้ แต่รูปแบบการโต้ตอบกับ UI คือการ toggle flag และ option ที่ map ไปยัง argument ของ Git command line จริง ๆ ข้างใน
      ดังนั้นเมื่อย้ายไปใช้ command line ตามธรรมชาติ ก็จะคุ้นเคยและใช้งานเองได้ทันที
  • Julia น่าจะเป็นหนึ่งในคนที่น่าชื่นชอบที่สุดในวงการเทคโนโลยี
    ทุกครั้งที่อ่านงานเขียนของเธอ ความตื่นเต้นแบบตอนเด็ก ๆ ที่เพิ่งเริ่มไขความลับของโลกจริงผ่านการทดลองเล็ก ๆ ก็กลับมาอีก น่ารักจริง ๆ

    • คนที่มีทั้งความรู้เชิงเทคนิคลึกมากและ ความสามารถด้านการสอน·การสื่อสาร ที่ยอดเยี่ยมพร้อมกันนั้นหาได้ยาก อีกคนที่นึกถึงคือ Andrej Karpathy
      โชคดีที่ช่วงหลังเริ่มพบคนที่เข้าข่ายแบบนี้มากขึ้น
    • แวบหนึ่งนึกว่ากำลังพูดถึงภาษา Julia :)
    • เห็นด้วยมาก ปกติผมไม่ค่อยชอบบล็อกโพสต์หรือ tutorial ที่ตื่นเต้นเกินเหตุแบบ “omg awesomesauce” เท่าไร และชอบงานเขียนสไตล์ Landau&Lifschitz ที่แห้ง กระชับ สวยงาม และมี signal-to-noise ratio สูงกว่ามาก
      แต่งานเขียนของ Julia ทุกชิ้นทำให้ผมรู้สึกถึงความตื่นเต้นแบบที่พูดถึงข้างต้นได้ทั้งหมด
    • เจอตัวจริงก็ น่ารักมาก ผมให้เธอเซ็นหนังสือ How DNS Works ของผมด้วย
  • ผมคิดว่าคำว่า “เมื่อมือใหม่บอกว่า ‘อันนี้ยาก’ คนมีประสบการณ์ก็บอกว่า ‘ใช่ bash ใช้ไม่ได้หรอก ไม่มีใครรู้จริง ๆ’” ไม่ควรตีความตามตัวอักษร
    ความหมายใกล้เคียงกว่าคือ “เราไม่ได้เข้าใจโค้ด bash ที่เราเขียนไว้อย่างมั่นใจนัก และก็ไม่ได้มั่นใจว่ามันจะทำงานตามคาดในสถานการณ์ที่ไม่ได้ทดสอบ”
    หมายความว่าเมื่อมีอะไรที่ไม่ธรรมดาแม้แต่นิดเดียวเกิดขึ้น ก็พอจะคาดได้ว่าบางอย่างจะล้มเหลว และข้อเท็จจริงใหม่ที่ได้เรียนรู้เกี่ยวกับ bash อาจทำให้ขนลุก หรือถึงขั้นฟาดของใกล้มือแรงจนเสียหาย
    Bash เป็นภาษาที่ซับซ้อน และสำหรับโปรแกรมเมอร์ส่วนใหญ่ มันต่างจากภาษาอื่น ๆ ที่ใช้เป็นประจำโดยสิ้นเชิง บริษัทส่วนใหญ่มักมี bash อยู่บ้างใน production ที่ไหนสักแห่ง แต่บ่อยครั้งไม่มีใครใช้มันมากพอจนรู้ดีจริง ๆ
    ผมไม่คิดว่าเป็นเรื่องบังเอิญที่ build tools, CI tools และเครื่องมือ cloud orchestration วิวัฒน์ไปในทิศทางที่ลดความจำเป็นของ shell scripting

    • ผมคิดว่าความซับซ้อนของเครื่องมืออย่าง bash มาจาก การขาดวิวัฒนาการ
      ลองคิดเป็น thought experiment ว่าเราเพิ่ม assignment statement ที่ดีกว่าให้ bash ไม่ได้หรือ เช่นในโหมด set --goodass ถ้าเขียนแบบ a = string1 + '.' + string2 ได้ ก็จะตัดปัญหา shell quoting ออกไปได้มาก
      เครื่องมืออย่าง make ก็จะได้ประโยชน์ด้วย ถ้าใช้เวลา 6 เดือนทำให้ make มีตัวแปรที่ใช้งานได้ วิธีจัดการ path และ filename ที่ชัดเจน และ target ที่ใช้ได้ดีกว่าเดิม อาจดีกว่าการใช้เวลา 6 เดือนสร้าง Makefile ที่ซับซ้อน
    • ปัญหาคือมือใหม่จะเข้าใจนัยโดยนัยนั้นหรือไม่ หรือจะรับตามตัวอักษรมากกว่าที่ตั้งใจไว้
      โดยเฉพาะความรู้สึกที่ว่า “สำหรับโปรแกรมเมอร์ส่วนใหญ่ bash ต่างจากทุกภาษาที่ใช้เป็นประจำ” ไม่ใช่สิ่งที่มือใหม่จะอนุมานได้เสมอไป เพราะต้องมีประสบการณ์พอจะแยกความต่างระหว่าง “ไม่ค่อยพบบ่อย” กับ “เข้าใจยากสุด ๆ”
  • เกี่ยวกับเรื่องนี้ ซอฟต์แวร์ส่วนใหญ่ถูก ออกแบบเกินความจำเป็น
    ผมคิดว่าส่วนหนึ่งเป็นเพราะการรวมศูนย์ของอุตสาหกรรมด้วย คนกลุ่มเล็ก ๆ ที่ควบคุมเครื่องมือจำนวนน้อยได้ประโยชน์จากการผลักทุกคนไปใช้เครื่องมือเหล่านั้น และผลก็คือเครื่องมือจำนวนมากกลายเป็น “เครื่องมือสำหรับทุกอย่าง” ครอบคลุมมากกว่ากรณีใช้งานที่ต้องจัดการจริง ๆ มาก
    บริษัทต่าง ๆ อยากให้นักพัฒนาทุกคนรู้จักเครื่องมือเดียวกัน เพราะทำให้ทดแทนกันได้ง่ายระหว่างโปรเจกต์และบริษัท และทำให้อำนาจต่อรองในอุตสาหกรรมอ่อนลง
    ดังนั้นซอฟต์แวร์จึงเหลือเพียงสายหลักเดียว ส่วนแนวทางทางเลือกถูกกีดกันออกไปโดยไม่มีงานรองรับ ทั้งที่โดยธรรมชาติแล้วอุตสาหกรรมอยากกระจายตัว แต่กลับทำไม่ได้
    มองในแง่บวก สักวันหนึ่งแนวทางนอกกระแสที่เหนือกว่ามาก ๆ จะปรากฏขึ้นและกัดเซาะแนวทางกระแสหลัก เทคโนโลยีไม่ใช่คณิตศาสตร์ และก็แตกต่างจากวิทยาศาสตร์ มันสามารถรองรับหลายแขนงที่แก้ปัญหาเดียวกันได้หลายวิธีอย่างเพียงพอ

    • เห็นด้วย ในบางแง่ web development เหมือนถอยหลังจากยุค ASP.NET หรือ Rails ช่วงแรก ๆ ด้วยซ้ำ
      ตอนนั้น browser war ทำให้เรายุ่งก็จริง แต่ตอนนี้แม้ browser ส่วนใหญ่จะเข้ากันได้แล้ว เรากลับสร้างความซับซ้อนฝั่ง frontend สำหรับ web app ที่ส่วนใหญ่ไม่จำเป็นขึ้นมาเต็มไปหมด
      สิ่งอย่าง DNS, IP, HTTPS เป็นเทคโนโลยีพื้นฐานที่มีความเข้ากันได้ย้อนหลังและปัจจัยทางการเมืองพันกันอยู่ จึงช่วยไม่ได้
      ถึงอย่างนั้น ผมรู้สึกว่าการเรียนรู้สิ่งเหล่านั้นให้ดีเป็นการลงทุนที่ดีกว่าการเรียน framework มาก ถ้าพูดต่อคงไปถึงเรื่อง innovation tokens แน่ ๆ
  • หากต้องการทำให้สิ่งที่ยากกลายเป็นเรื่องง่าย ต้องหา abstraction ที่เหมาะสมให้เจอ คือเก็บไว้ในหัวแค่บางส่วนของเนื้อหาที่ยากและรายละเอียดที่ใช้บ่อย ส่วนที่เหลือค่อยไปค้นเมื่อจำเป็น
    ปัญหาคือผู้คนมักไม่ยอมสร้างการบีบอัดเชิงปริชานสำหรับหัวข้อใหญ่ ๆ จนกว่าจะจำเป็นจริง ๆ เพราะพวกเขาแบกรับภาระทางปริชานขนาดใหญ่อื่นอยู่แล้ว จึงต่อต้านการเพิ่มภาระใหม่
    ถ้าสามารถพึ่งพาคนอื่นที่รู้เรื่องหัวข้อ X ดีได้ ก็อาจทำแบบนั้นไปเลย และไม่ต้องพยายามเรียนรู้ X ให้เพียงพอ วิธีที่ดีที่สุดสำหรับคนที่รู้ X ดีในการลดคำขอความช่วยเหลือ คือช่วยให้คนอื่นเข้าใจขั้นต่ำสุดของ X
    set -e นั้นเสียอยู่ ความจำเป็นที่ต้องครอบทุกอย่างด้วยเครื่องหมายคำพูดก็เสียอยู่เช่นกัน และ globbing ควรเป็นฟีเจอร์ที่ต้องขอใช้อย่างชัดเจน ใน command line อาจน่ารำคาญ แต่ในสคริปต์เป็นคนละเรื่อง และตอนนี้ถ้าปิด globbing แบบ global ก็จะทำ globbing ในจุดที่ต้องการได้ยาก
    ค่าเริ่มต้นที่แย่แบบนี้ไม่ได้มีแค่ใน Bash แต่มีอยู่ทั่วทั้งเชลล์สาย Ksh และ Bourne shell
    SQL ก็มีหลายคนที่อยากสลับลำดับ clause ไม่มีเหตุผลที่ทำไม่ได้ และดูเหมือนจะเป็นการเปลี่ยนแปลงค่อนข้างเล็กเพื่อให้ parser SQL ที่มีอยู่ยอมรับ clause ในลำดับอื่น
    อย่างไรก็ตาม โดยส่วนตัวไม่มีปัญหาเชิงปริชานนี้ อาจเพราะรู้อยู่แล้วว่าต้องดูแหล่งที่มาของตารางก่อน

    • กับดักสามอย่างคือ set -e เสียอยู่, ต้องครอบทุกอย่างด้วยเครื่องหมายคำพูด, และ globbing ควรเป็นแบบชัดเจน — OSH แก้ให้ได้โดยยังรันสคริปต์เชลล์เดิมได้
      ถ้าเพิ่ม shopt --set ysh:upgrade ไว้บนสุดของสคริปต์ ปัญหาทั้งสามอย่างนั้นจะหายไป
      ถ้าอยากช่วยโปรเจกต์นี้ ก็ดาวน์โหลด tarball ไปตรวจสอบข้ออ้างเหล่านี้ แล้วเขียนบล็อกโพสต์ให้จะดีมาก
      รายละเอียดอยู่ที่ https://www.oilshell.org/release/latest/doc/error-handling.h... และ https://www.oilshell.org/release/latest/doc/simple-word-eval...
      เอกสารครอบคลุมมาก แต่คนส่วนใหญ่ไม่ได้ต้องการรายละเอียดระดับนั้น ดังนั้นถ้ามีใครช่วยทดสอบแล้วเขียนสรุปสั้น ๆ ก็จะเป็นประโยชน์
      เหตุผลที่ช่วงหนึ่งไม่ได้ผลักดัน Oils อย่างจริงจังคือมันมี dependency กับ Python แต่ตอนนี้เป็น C++ ล้วนแล้ว และ ณ สัปดาห์นี้ชนะ bash ใน benchmark บางตัวที่เน้นการคำนวณ
      สคริปต์ที่เน้น I/O นั้นเร็วเท่าเดิมมาตลอด เช่นเดียวกับสคริปต์เชลล์ส่วนใหญ่ ในเอกสารยังต้องเปลี่ยนชื่อ Oil เป็น YSH อยู่ จึงอาจมีความสับสนไปอีกพักหนึ่ง: https://www.oilshell.org/blog/2023/03/rename.html
    • ปัญหาคือยังใช้ เชลล์โบราณ แบบนี้ต่อไป ทั้งที่มีเชลล์ที่ดีกว่าแล้ว ผู้ใช้ไม่ควรต้องเสียเวลาท่องความรู้ลับอย่าง set -e ถึงอย่างนั้นตอนนี้ก็ยังมีเสิร์ชเอนจิน
    • วิธีที่ค่อนข้างสุดโต่งในการแก้ลำดับ clause ของ SQL อาจเป็นการเพิ่ม project ที่ทำงานเหมือน select แต่สามารถวางไว้ในตำแหน่งที่ถูกต้องได้
    • ถ้ามีรายละเอียดที่ไม่จำเป็นอยู่ในคำอธิบาย จะทำให้สับสนมาก เหมือนปืนของเชคอฟที่พยายามยัดมันเข้าไปในโครงเรื่องตลอดเวลา แต่เข้ากันไม่ได้
      พลังพิเศษของผมคือความจำที่แย่มาก ดังนั้นถ้าจะจำอะไรได้ก็ต้องเข้าใจมันให้ได้ก่อน กล่าวคือต้องมีการบีบอัดเชิงปริชาน ผมเรียนแบบจำไปเฉย ๆ เหมือนคนทั่วไปไม่ได้
    • ต้องสามารถลอก SQL ออกแล้วเข้าถึง ชั้นล่าง ได้
  • สิ่งที่ได้เรียนรู้วันนี้: ในรายการ && หรือ || แม้จะมีคำสั่งที่ล้มเหลว เชลล์ก็จะไม่จบการทำงาน ยกเว้นคำสั่งที่อยู่หลัง && หรือ || ตัวสุดท้ายในบรรดาคำสั่งที่ถูกเรียกใช้
    อ้างอิง: https://www.gnu.org/software/bash/manual/bash.html#index-set

    • “ความล้มเหลว” เป็นแนวคิดในระดับที่สูงกว่าสิ่งที่เชลล์ใส่ใจมาก เงื่อนไขความล้มเหลวและการตอบสนองขึ้นอยู่กับดุลยพินิจของโปรแกรมเมอร์ทั้งหมด ไม่ได้ถูกฝังเป็นสมมติฐานไว้ในเชลล์
      สิ่งที่ /bin/false ทำก็แค่คืนค่า 1 เท่านั้น แบบนั้นคือความล้มเหลวหรือ? ไม่ใช่ มันถูกออกแบบมาให้ทำงานแบบนั้น และเป็นเครื่องมือที่มีวัตถุประสงค์ตรงตามนั้นตามตัวอักษร
      ผมเคยเขียนเชลล์สคริปต์มาหลายร้อยตัว และในนั้นมีหลายคำสั่งที่คืนค่าที่ไม่ใช่ 0 อย่างปกติมาก ๆ เพื่อทำงานของตัวเอง เช่น ตรวจสอบว่าสตริงมีแพตเทิร์นบางอย่างหรือไม่
      โปรแกรมสามารถคืนค่า exit code ใดก็ได้ตามต้องการในทุกสถานการณ์ และตามธรรมเนียมแล้วความสำเร็จคือ 0 ความล้มเหลวคือค่าที่ไม่ใช่ 0 แต่สิ่งเดียวที่ภาษาเชลล์ใส่ใจคือ 0 ถูกประเมินเป็น “จริง” และค่าที่ไม่ใช่ 0 ถูกประเมินเป็น “เท็จ”
      ถ้าเชลล์จบการทำงานทุกครั้งที่โปรแกรมใด ๆ คืนค่าที่ไม่ใช่ 0 คำสั่ง if และลูปก็จะเป็นไปไม่ได้ ทำให้ใช้งานลำบากมาก
      ถ้าเป็นสคริปต์ที่ให้ความสำคัญกับ return code ของโปรแกรมใดโปรแกรมหนึ่ง ก็ต้องตรวจสอบและจัดการอย่างชัดเจน อย่างที่ลิงก์ไว้ มีตัวเลือกที่ทำให้เชลล์จบการทำงานเมื่อคำสั่งภายในคืนค่าที่ไม่ใช่ 0 และผู้เขียนเชลล์สคริปต์ระดับต้นถึงกลางจำนวนมากก็ยืนยันแบบยึดหลักการว่าควรใช้ตัวเลือกเหล่านั้นในทุกสคริปต์
      แต่ในสคริปต์ที่ซับซ้อน ผมรู้สึกว่ามี edge case จำนวนมากที่ค่อนข้างแฮ็ก ๆ และรับมือยาก ถ้าต้องใช้ตัวเลือกพวกนั้นทุกครั้ง บางทีใช้ Makefile ไปเลยอาจดีกว่า
    • เพราะ && และ || ถูกใช้เหมือนเงื่อนไขบ่อยมาก
      [ -e README ] && cat README ช่วยหลีกเลี่ยงข้อผิดพลาดเมื่อไม่มีไฟล์ README และ [ -e README ] || echo "You should write a README!" ทำงานในทางกลับกัน
      ปัญหาที่แยบยลกว่าคือ แม้จะสมมติว่าใช้ set -e ใน pipeline เชลล์ก็จะไม่จบการทำงานถ้าคำสั่งสุดท้ายไม่ล้มเหลว
      grep foo README | sort จะไม่ล้มเหลวแม้ไม่มี README ตราบใดที่ไม่ได้ใช้ set -o pipefail ด้วย
    • ผมมองว่านี่เป็นหนึ่งในข้อบกพร่องที่ใหญ่ที่สุดของการออกแบบภาษาเชลล์ เพราะฟังก์ชันอาจนำไปสู่ผลลัพธ์ต่างกันได้ตามบริบทที่ถูกเรียก โดยไม่ขึ้นกับอาร์กิวเมนต์
      แม้จะตั้ง set -e อย่างชัดเจนภายในฟังก์ชัน ก็ยังถูกเขียนทับ
      เคยยกตัวอย่างไว้ก่อนหน้านี้: https://news.ycombinator.com/item?id=22213830
    • เชลล์ยังมีความรู้ลับ ๆ ที่ต้องเรียนรู้อีกมาก ถึงจุดหนึ่งก็ต้องยักไหล่และยอมรับว่า มันเป็นเครื่องมือที่พอใช้ได้สำหรับให้ได้ผลลัพธ์เร็ว ๆ แต่ไม่เหมาะกับการเขียน โปรแกรมที่แข็งแกร่ง
  • เป็นบทความที่อธิบายสิ่งต่าง ๆ ที่ดูเหมือนไม่ควรยาก แต่จริง ๆ แล้วมีความซับซ้อนมากได้ดี
    แต่ส่วน SQL ดูเหมือนจะยิ่งผลักดันความล้มเหลวเชิงแนวคิด มากกว่าจะช่วยไขความลึกลับ
    ตรรกะของคิวรีเป็นแบบ declarative และกำหนดผลลัพธ์ สิ่งที่มีลำดับการทำงานหรือลักษณะเชิงขั้นตอนคือ query plan ต่างหาก ควรเรียนสิ่งนี้ก่อน
    จากนั้นจึงค่อยเรียนพื้นที่ก้ำกึ่งอย่าง dependent subquery ได้ ถ้ามองเห็นว่า not exists กับ anti join เทียบเท่ากัน ก็จะเข้าใจและให้เหตุผลได้
    การเปรียบเปรยในทำนองให้เข้าใจคิวรีที่เขียนขึ้นแบบเชิงขั้นตอนเป็นเพียงการเลื่อนปัญหาออกไป และเมื่อไปติดกับสิ่งที่ซับซ้อนกว่า ก็จะไม่มีวิธีแกะ “คำโกหกด้วยเจตนาดี” นั้นออก

    • ส่วน SQL พูดถึง mental model ที่ช่วยทำความเข้าใจคิวรี และยังกล่าวด้วยว่าฐานข้อมูลจริง ๆ คงไม่ได้ประมวลผลแบบนั้น
    • ตอนที่เกี่ยวข้องล่าสุดเกี่ยวกับ Postgres แต่ในหลายกรณีก็สามารถขยายไปคิดกับฐานข้อมูลอื่นได้ด้วย: https://www.se-radio.net/2023/09/se-radio-583-lukas-fittl-on...
  • เป็นการนำเสนอที่ยอดเยี่ยม จริงอยู่ที่ Bash เต็มไปด้วย “กับดัก” และเกร็ดความรู้จิปาถะ และยากที่จะจำทั้งหมด แต่ผมคิดว่าเกร็ดบางอย่างก็ควรจำไว้เหมือนกัน
    เช่น ผมมักลืมลำดับอาร์กิวเมนต์ของคำสั่ง find อยู่บ่อย ๆ จนเสียเวลาในการนึก syntax ตอนอยู่หน้าเครื่องที่ต่ออินเทอร์เน็ตไม่ได้ทันที
    ดังนั้นผมจึงตัดสินใจเรียนและจำเครื่องมือบรรทัดคำสั่งที่ใช้บ่อยที่สุดกับ กับดัก บางส่วนของมัน โดยใช้ Anki และเทคนิคช่วยจำบางอย่าง ผมคิดว่าผลตอบแทนต่อการลงทุนคุ้มค่ามาก

    • Anki เป็น เส้นชีวิต ของผมในการทำความเข้าใจสิ่งยาก ๆ อย่าง DNS
      จริง ๆ แล้วผมอ่าน Networking for System Administrators ของ Michael W. Lucas หลังจากเห็นคำแนะนำหนังสือจาก jvns.ca และดึงความรู้ทางเทคนิคกับภูมิปัญญาของผู้ดูแลระบบไม่น้อยออกมาเป็นการ์ด Anki
      ตอนนี้เมื่อดีบักปัญหาใน transport layer ผมจำได้ทันทีว่าควรใช้เครื่องมืออย่าง netcat และ tcpdump อย่างไร ดังนั้นมันอาจเป็นหนึ่งในหนังสือที่ให้ผลตอบแทนต่อการลงทุนสูงที่สุดในบรรดาหนังสือที่ผมอ่านมา
    • ผมดูแลไฟล์ที่รวบรวมคำสั่งที่ไม่ได้ใช้บ่อยไว้ เช่น คำสั่งเพิ่มเสียงด้วย ffmpeg หรือคำสั่งเพิ่มขอบให้รูปภาพด้วย convert
      ยังทำคีย์ลัดสำหรับเพิ่มคำสั่งล่าสุดที่รันลงในไฟล์นี้ และคีย์ลัดสำหรับค้นหาในไฟล์นี้ไว้ด้วย
    • man page ใช้งานได้ทันที
      man page ของ bash ใหญ่และซับซ้อน แต่ครอบคลุมมาก ถ้าคุ้นเคยกับส่วนหลัก ๆ และรูปร่างทางสายตาของข้อความ ก็สามารถเลื่อนผ่านอย่างรวดเร็วเพื่อหาข้อมูลที่ถูกต้องที่ต้องการได้ ซึ่งค่อนข้างมีประโยชน์
      วิธีนี้หลายครั้งยังเร็วกว่าการใช้เสิร์ชเอนจินบนอินเทอร์เน็ตด้วย
    • หากไม่อยากพึ่งอินเทอร์เน็ต แต่ก็ไม่อยากต้องจำการออกแบบที่แย่ อาจดีกว่าที่จะลงทุนกับ เอกสาร·ชีตสรุปคำสั่ง ที่ทั่วไปกว่า
      เช่น แปลง man page เก่า ๆ ให้อยู่ในรูปแบบที่เป็นมิตรกับ text editor หรือใช้เครื่องมือที่ดีกว่าอย่าง tldr, Dash เพราะไม่ได้มีแค่ find เท่านั้นที่เป็นแบบนี้
    • ควรหยุดใช้ Bash แล้วใช้ TypeScript แทน Bash แย่มาก
  • ไม่รู้ทำไมเหมือนกัน แต่ตอนแรกอยากจะไม่ชอบบทความนี้ อาจเป็นเพราะเห็น jvns บน HN บ่อยเกินไป หรืออารมณ์ไม่ดีอยู่ก็ได้
    แต่จริง ๆ แล้วเป็นบทความที่ดีมาก และในฐานะคนที่มีประสบการณ์พัฒนา 20 ปี ผมคิดว่านี่ค่อนข้างใกล้ความจริงในบรรดาการถกเถียงระดับเมตาเกี่ยวกับการเขียนโปรแกรม
    เรื่อง การมองเห็นแบบเลือกได้ นั้นตรงกับทั้ง dig และหน้า man มาก ๆ ผมจำไม่ได้แล้วว่ากี่ครั้งที่เปิด man แล้วถูกตัวเลือกการตั้งค่าและแฟล็กบรรทัดคำสั่งที่ไม่มีที่สิ้นสุดถาโถมใส่จนงง
    ทิปที่ใช้กับ man คือใช้ฟังก์ชันค้นหาแบบ Vim ด้วย / เช่น ถ้าอยากหาวิธีให้ grep แสดงเลขบรรทัดของแต่ละ match แต่จำไม่ได้ ก็เปิด man grep แล้วพิมพ์ /line จากนั้นกด Enter เพื่อค้นหาคำว่า “line” ในหน้า man ส่วน match ถัดไปก็แค่กด /
    ข่าวที่ว่า Strange Loop จบลงแล้วก็ทำให้เศร้านิดหน่อย เพิ่งรู้จักเมื่อราวปีก่อน แต่หลาย ๆ ทอล์กดูมีคุณภาพสูงเป็นพิเศษ

    • น่าจะลองดูทอล์กของ Alex Miller ที่เพิ่งลงมาไม่นานนี้: https://www.youtube.com/watch?v=suv76aL0NrA
      ถึงจะเศร้าที่มันจบลง แต่ทอล์กนี้แสดงให้เห็นอย่างค่อนข้างน่าเชื่อว่า บางครั้งการที่บางสิ่งจบลงก็เป็นเรื่องดีได้ ถ้าดูทั้งทอล์กจะเข้าใจ
    • https://cheat.sh เป็นเหมือนเส้นชีวิตเลย
      และยังทำ https://github.com/kristopolous/mansnip ด้วย
    • match ถัดไปกด n ก็ได้
  • ผมไม่เห็นด้วยอย่างแรงกับมุมมองเรื่อง bash ทางออกที่ดีที่สุดไม่ใช่การวางเครื่องมือทับบน bash หรือท่องจำความแปลกเฉพาะของมัน แต่คือ ไม่ใช้ bash
    นั่นเป็นวิธีเดียวที่จะเลี่ยงกับดักได้

    • ผมยังไม่เจอสิ่งทดแทน bash ที่เหมาะจริง ๆ โดยเฉพาะสำหรับสคริปต์
      ทางเลือกที่พบบ่อยที่สุดคือ 1) ใช้เชลล์ใหม่อย่าง Oil shell [0] หรือ 2) ใช้ภาษาโปรแกรมอย่าง Python, JavaScript, PHP
      ปัญหาของเชลล์ใหม่คือ ต้องติดตั้งเชลล์นั้นในทุกที่ที่อยากรันสคริปต์ ในขณะที่ bash มีอยู่แทบทุกที่ ถ้าไม่ใช่สคริปต์ที่คุณดูแลคนเดียว ก็เท่ากับกำลังขอให้คนอื่นเรียนเชลล์นั้นเพื่อมาดูแลต่อด้วย
      ปัญหาของภาษาโปรแกรมอื่นคือ สิ่งที่ bash ทำได้ดีมากคือการต่อคำสั่งเข้าด้วยกัน และจัดการ input/output ของคำสั่งกับไฟล์ ซึ่งมี usability ที่ดีอย่างหาได้ยาก
      พอลองทำด้วยภาษาอื่น จู่ ๆ มันก็ซับซ้อนขึ้นมาก หรืออย่างน้อยก็ยืดยาวขึ้น
      ดังนั้นผมยังใช้ bash อยู่ แต่ยอมรับว่าจุดแข็งของมันอยู่ที่การรันคำสั่งอื่นและจัดการ I/O ถ้าเป็นลอจิกซับซ้อนที่ไม่เกี่ยวกับสิ่งเหล่านั้น ก็โยนไปให้ภาษาอื่น บางครั้งก็แค่เรียกสคริปต์ Python จาก bash ไม่ใช่หลีกเลี่ยง bash ทั้งหมด
      ถ้ามีแนวทางอื่นที่เหมาะกว่า อยากให้ช่วยแชร์ด้วย
      [0] https://www.oilshell.org
    • เป็นประเด็นที่สมเหตุสมผล bash เป็นเครื่องมือที่ซับซ้อนเกินไป และมันก็แปลกที่จะเขียนเครื่องมืออีกชั้นบน bash เพื่อทำให้ bash ซับซ้อนน้อยลง
      ทั้งที่เครื่องมือใหม่นั้นก็คงไม่ได้ผ่านการดีบักมาหลายสิบปีแบบ bash เอง ปัญหาอยู่ที่ตัว bash นั่นแหละ
      เรามีแนวโน้มประเมิน usability ต่ำเกินไป และประเมิน “ความฉลาดล้ำ” สูงเกินไป
      ตัวอย่างเด่นคือ Git เป็นเครื่องมือที่ฉลาดมาก แต่ usability แย่มาก ถึงอย่างนั้น Linus ก็เป็นคนสร้าง และ Linus ก็ฉลาด เราเลยรู้สึกเหมือนปัญหาอยู่ที่ตัวเราเอง
      สุดท้ายเราจะได้สิ่งที่เราให้คุณค่า เราควรให้คุณค่ากับ usability มากกว่านี้
    • ผมเป็นแฟนตัวยงของ shellcheck และเคยใช้ bash อย่างลึกจริง ๆ แต่ไม่มี linter หรือเครื่องมือใดบน bash ที่จะแก้เรื่องนี้ได้
      ทางออกที่ดีที่สุดคืออยู่ให้ห่าง มันต้องหยุดจริง ๆ อย่าพยายามทำตัว macho
      โมเดลทั้งหมดของภาษานี้พังโดยพื้นฐาน ทั้งไทป์ที่เน้นสตริงเป็นศูนย์กลาง, สวิตช์โหมดแบบ global, แฟล็กตัวอักษรเดียวใน operator เปรียบเทียบพื้นฐาน, พฤติกรรมที่โดยปริยายมักเมิน error ไปทั่ว และโดยเฉพาะ function ด้วย
      แค่ความแปลกอย่างใดอย่างหนึ่งก็พอจะตัดภาษานี้ทิ้งแล้ว แต่ bash มีทั้งหมดนั้นและมากกว่านั้นอีก
    • เหตุที่ bash แปลก เพราะมันไม่ใช่ภาษาทั่วไป สิ่งที่บทความพูดถึงก็มีเหตุผลของมันอยู่ เช่นกรณีที่ set -x อาจทำลายพฤติกรรมที่คาดหวังของ || และ &&
      มีภาษาอะไรบ้างที่ชนกันเพราะฟังก์ชันคืนค่า false ตั้งแต่แรก? มีภาษาที่ throw exception ก็จริง แต่ “false” เป็นค่าที่ถูกต้องที่คืนได้ไม่ใช่หรือ
      ใน Makefile ก็เห็นเรื่องเดียวกัน ผู้คนไม่เข้าใจว่าตัวเองกำลังทำอะไร และไม่เคยคิดลึก ๆ เกี่ยวกับ build system จึงคาดหวังว่ามันจะทำงานแบบใดแบบหนึ่ง
      ตัวอย่างเช่น recursive assignment ของ Make ทำให้แทบทุกคนสะดุด
      FLAGS=-b, COMPILE=compile $(FLAGS), $(info compile command=$(COMPILE)), FLAGS=-a, myfile:, echo $(COMPILE) $? -o $@ จะทำให้การพิมพ์ข้อมูลครั้งแรกออกมาเป็น compile -b แต่ตอนรันจริงจะเป็น compile -a -o myfile
      แต่ว่าถ้าทำให้การกำหนดค่าทั้งหมดประเมินผลทันทีเพื่อให้เข้ากับภาษาโปรแกรมอื่น ก็เท่ากับพรากเครื่องมือที่มีประโยชน์มากไป ยิ่งเข้าใจเครื่องมือแบบนี้มากเท่าไร ก็ยิ่งรู้ดีขึ้นว่าจะใช้ตรงไหนและควรทุ่มแรงแค่ไหน
    • พูดง่ายกว่าทำ และการกำจัด bash ให้หมดอาจไม่ได้คุ้มเวลาและแรงเสมอไป
      แต่โดยรวมเห็นด้วย ผมพยายามโยนทุกอย่างที่ซับซ้อนแม้แต่นิดเดียวไปให้สคริปต์ที่เขียนด้วยภาษาที่แปลกน้อยกว่า
      ในตอนนั้น เครื่องมือที่ช่วยหลีกเลี่ยงความผิดพลาดใน 5% สุดท้ายที่ยังเหลือเป็น bash มีประโยชน์มาก