อัปเดต
Python / Tools
sqlite-utils 4.2.1 มาพร้อมบทเรียนราคาแพง: อย่าลืมประกาศ dependency ที่แกใช้จริง
บั๊กที่ทำ CLI พังต่อหน้าต่อตา เพราะ typing-extensions ไม่ได้ถูกระบุเป็น dependency โดยตรง — แล้วไอเดียการเทสต์แบบ "แยกกาก" ของ Simon ก็เจ๋งพอจะขโมยไปใช้
ทีมข่าว เอไอไทย.com
⏱ อ่าน 3 นาที
หนึ่งในเรื่องน่าปวดหัวที่สุดของคนเขียนไลบรารี Python คือการที่โค้ดตัวเองรันได้ปกติเป๊ะทุกอย่างบนเครื่องตัวเอง พอคนอื่นเอาไปใช้ถึงพังสนั่น — และนี่คือสิ่งที่เกิดขึ้นกับ sqlite-utils เวอร์ชัน 4.2 ที่เพิ่งปล่อยออกมาไม่ทันไรก็ต้องรีบแกะกล่องใหม่เป็น 4.2.1 ทิ้งทันที
เรื่องมันเริ่มจาก Simon Willison เจ้าของโปรเจกต์ไปใช้ typing_extensions.Self ในโค้ด ซึ่งเป็นอะไรที่ดู harmless มากๆ แต่ปัญหาคือเจ้าแพ็กเกจนี้มันไม่ได้ถูกระบุไว้ใน dependencies ของตัว sqlite-utils เอง มันแอบโผล่มาเพราะ dev dependencies ตัวอื่นดึงมาอีกทีหนึ่ง พอตอนที่เขารันบนเครื่องตัวเองซึ่งมีของเต็มไปหมดก็ไม่มีปัญหาอะไร แต่พอมีคนใช้ uvx sqlite-utils ซึ่งมันจะสร้าง environment ใหม่สะอาดๆ โดยไม่ดึง dev dependencies พวกนั้นมาด้วย — บูม! crash ทันที
คำถามคือทำไมมันถึงไม่ถูกจับได้ตั้งแต่ตอนเทสต์? เพราะว่าเทสต์ส่วนใหญ่รันใน environment ที่ "เปื้อน" ไปแล้ว — มีแพ็กเกจเกินความจำเป็นนอนกองเต็มไปหมด มันเลยไม่เคยเจอสถานการณ์ "ของขาด" ที่แท้จริง ซึ่งเป็นปัญหาเรื้อรังของนักพัฒนา Python หลายคน (รวมถึงผมด้วยแหละ) ที่ไม่ค่อยได้ทดสอบกับ environment ที่สะอาดจริงๆ สักเท่าไหร่
สิ่งที่เจ๋งกว่าตัวบั๊กคือวิธีแก้ของ Simon เขาคิดค้นคำสั่งเทสต์แบบ "smoke test" ที่รันจากตัวโปรเจกต์โดยตรงแบบไม่ต้องพึ่ง dev dependencies เลย:
uv run --isolated --no-default-groups sqlite-utils --help
เจ้า --no-default-groups มันจะไม่ติดตั้ง dev dependencies ตามค่าเริ่มต้น ส่วน --isolated ก็คือแม้จะมี .venv/ ที่มีของเต็มไปหมดอยู่แล้ว มันก็จะเมินหน้าตาเฉย — บังคับให้รันใน environment ที่แทบจะเปลือยเปล่าจริงๆ นี่แหละคือวิธีที่จะทำให้เห็นปัญหาพวกนี้ได้ตั้งแต่ก่อนปล่อย ไม่ใช่ไปเจอเอาตอนผู้ใช้ร้องเรียน
ผมว่าประเด็นนี้มันสะท้อนอะไรได้เยอะนะ โดยเฉพาะยุคที่คนเริ่มใช้ uvx / pipx กันมากขึ้น ซึ่งมันจะสร้าง environment ที่สะอาดๆ ให้อัตโนมัติ ทำให้ปัญหา dependency แฝงแบบนี้จะโผล่บ่อยขึ้นเรื่อยๆ ถ้าใครยังเขียน code โดยไม่คิดถึง "มุมมองคนใช้" ว่าของที่แกใช้ตอน dev มันไม่จำเป็นต้องอยู่ฝั่งผู้ใช้ก็ได้ — ของบางอย่างมันก็ควรประกาศไว้ตรงๆ ให้ชัดเจน อย่ามัวแต่พึ่ง "ความบังเอิญ" ว่ามีแพ็กเกจอื่นดึงมาให้
อีกอย่างที่ผมชอบคือวิธีคิดเรื่องการเทสต์ของ Simon — แทนที่จะเพิ่ม dependency เข้าไปให้วุ่นวาย เขากลับหาวิธีรันเทสต์ในสภาพที่ "แย่ที่สุด" คือไม่มีอะไรเลย แล้วค่อยดูว่ามันรอดหรือเปล่า ซึ่งมันบังคับให้โค้ดของคุณแข็งแรงตั้งแต่แกนจริงๆ ไม่ใช่พึ่งไม้ค้ำยันที่มองไม่เห็น
เรื่องนี้เป็นบทเรียนคลาสสิกที่ทุกคนควรจำ: dependency ที่แกใช้ในโค้ดจริง ต้องประกาศให้ครบ ไม่มีข้อยกเว้น และการเทสต์ใน environment ที่สะอาดที่สุดเท่าที่จะทำได้ ไม่ใช่เรื่องฟุ่มเฟือย แต่คือเกราะป้องกันความอับอายที่จำเป็น — ปล่อยของพังออกไปทีหนึ่ง เสียชื่อไปอีกนาน
ที่มา: Simon Willison's Weblog — อ่านต้นฉบับ
ความคิดเห็น 3
กำลังโหลดความคิดเห็น...