-
Hyrum's Law และ Golang
- ระหว่างที่สำรวจ Gocodebase เมื่อไม่นานมานี้ ผู้เขียนพบคอมเมนต์ที่น่าสนใจ
- ตัวอย่างโค้ดที่มีคอมเมนต์ว่า "ไม่สามารถเปลี่ยนข้อความนี้ได้เพราะ Hyrum's Law"
- เมธอด
Error() ของโครงสร้าง MaxBytesError จะคืนค่าข้อความผิดพลาดว่า "http: request body too large"
-
Hyrum's Law
- เป็นหลักการที่ตั้งชื่อตาม Hyrum Wright วิศวกรซอฟต์แวร์ของ Google
- กล่าวไว้ว่าเมื่อมีผู้ใช้จำนวนมากใช้งาน API พฤติกรรมทุกอย่างของระบบที่สังเกตได้จะต้องมีใครสักคนพึ่งพามัน
- พฤติกรรมทุกอย่างที่สังเกตได้ในโค้ด ไม่ว่าจะตั้งใจหรือเกิดขึ้นโดยบังเอิญ สุดท้ายจะมีใครบางคนพึ่งพามัน
- อธิบายว่าทำไมการเปลี่ยนข้อความผิดพลาดจึงอาจทำให้โค้ดเดิมพังได้
-
กรณีใน Golang
- พบคอมเมนต์ที่กล่าวถึง Hyrum's Law ในแพ็กเกจ
crypto/rsa และ internal/weak ด้วย
- ตัวอย่างคอมเมนต์ใน
crypto/rsa/rsa.go และ crypto/rsa/pss.go
- ตัวอย่างคอมเมนต์ในแพ็กเกจ
internal/weak
-
ข้อสังเกต
- ไม่ได้จำกัดอยู่แค่ Golang เท่านั้น
- สามารถสังเกตเห็นปรากฏการณ์คล้ายกันได้จากกระบวนการวิวัฒนาการของ JavaScript
- ปรากฏการณ์นี้ถูกเรียกว่า Hyrum's Law
-
ความคิดส่งท้าย
- เป็นการเตือนให้ระมัดระวังเมื่อเปลี่ยนโค้ดที่ผู้อื่นอาจพึ่งพาอยู่
- การออกแบบระบบให้พฤติกรรมที่ไม่ได้ตั้งใจไม่ถูกนำไปพึ่งพาเป็นสิ่งสำคัญ
- ควรจำไว้ว่าการเปลี่ยนแปลงเล็กน้อยอาจส่งผลกระทบใหญ่ได้
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
Hyrum's Law เป็นข้อสังเกตที่มีประโยชน์ แต่ต้องระวังไม่ให้สรุปผิด เวลาในการทำงานทั้งหมดของฟังก์ชันก็เป็นคุณสมบัติที่สังเกตได้เช่นกัน ดังนั้นการปรับแต่งฟังก์ชันให้เร็วขึ้นอาจเป็นเรื่องที่ดีสำหรับผู้ใช้ 99.99999999% แต่ก็อาจกลายเป็นการเปลี่ยนแปลงที่ทำให้ระบบพังได้ จึงควรเข้าใจว่า "การเปลี่ยนแปลงที่ทำให้พัง" เป็นสัญญาทางสังคม ไม่ใช่สัญญาทางเทคนิค ผู้เขียนไลบรารีควรบันทึกเอกสารว่าส่วนใดของ API จะไม่เปลี่ยนแปลง และควรเห็นอกเห็นใจผู้ใช้ ส่วนผู้ใช้ไลบรารีก็ควรเข้าใจว่าการใช้อินเทอร์เฟซที่ไม่ได้บันทึกไว้ในเอกสารอาจมีความเสี่ยง และควรเห็นอกเห็นใจผู้เขียน
ในภาษา Go ให้ความสำคัญกับ Hyrum's Law และความเข้ากันได้ย้อนหลังอย่างมาก ตัวอย่างเช่น ใช้ MaybeReadByte ในฟังก์ชัน GenerateKey เพื่อไม่ให้อัลกอริทึมถูกตรึงตายตัว กำลังพยายามแก้ปัญหาของคีย์ ECDSA ลำดับการวนซ้ำของแมปถูกทำให้เป็นแบบสุ่มเพื่อไม่ให้เปิดเผยรายละเอียดภายใน เอาต์พุตของ rand.Rand ก็ถือเป็นส่วนหนึ่งของคำมั่นสัญญาด้านความเข้ากันได้ จึงทุ่มเทความพยายามอย่างมากเพื่อปรับปรุงมัน มีการถกเถียงกันเสมอว่าในเอกสารควรให้คำมั่นสัญญาอะไร และควรปฏิเสธพฤติกรรมใด
สำหรับทางแก้ของปัญหาบางประเภท มีการแนะนำให้ใช้ sentinel error แทนข้อผิดพลาดแบบอิงสตริง ควรใช้ค่า ชนิด หรือค่าคงที่ของข้อผิดพลาดที่กำหนดไว้ล่วงหน้า เพื่อไม่ให้ผู้ใช้ API ต้องพึ่งพาสตริงที่ไม่ใช่สาระทางเทคนิค Hyrum's Law มีอยู่จริง แต่สามารถบรรเทาผลกระทบได้
วิธีหนึ่งในการรับมือกับ Hyrum's Law คือการเพิ่มความสุ่มเข้าไป โปรโตคอล QUIC ตั้งค่าฟิลด์ที่ไม่ได้ใช้เป็นค่าสุ่ม เพื่อไม่ให้เราเตอร์พึ่งพาฟิลด์เหล่านั้นในการระบุแพ็กเก็ต แนวทางนี้เรียกว่า "greasing" เพื่อป้องกัน "ossification"
ผู้ออกแบบ Golang ไม่ต้องการ exceptions แต่ข้อผิดพลาดแบบไม่เป็นทางการก็มีปัญหา จำเป็นต้องมีการถกเถียงกันว่าจะจัดการข้อผิดพลาดที่มีการจัดรูปแบบอย่างไรโดยไม่มี pattern matching
มีประสบการณ์จากที่ทำงานแห่งหนึ่งที่พบและแก้คำสะกดผิดในข้อความแสดงข้อผิดพลาด แต่กลับมีการพึ่งพาคำสะกดผิดนั้นลึกมากจนแก้ไขไม่ได้ สุดท้ายต้องย้อนกลับไปเป็นแบบเดิม
ข้อผิดพลาดของ Go อาจออกแบบให้เป็นชนิด enum ได้ แต่กลับใช้สตริงเป็นชนิด ทำให้ไม่อาจรู้ได้ว่าผู้ใช้จะพึ่งพามันอย่างไร นี่เป็นการตัดสินใจเชิงออกแบบแบบเก่าที่ยังคงอยู่ทั้งที่มีทางเลือกที่ดีกว่า
Hyrum's Law ตรงข้ามกับ Robustness Principle/Postel's Law โดยสิ้นเชิง หากเปิดกว้างในสิ่งที่ยอมรับได้ ก็ต้องเข้าใจวิธีนั้นและบันทึกไว้ในเอกสาร จึงพยายามออกแบบ API ไม่ให้เปิดกว้างเกินไปในสิ่งที่ยอมรับได้
Hyrum's Law มักปรากฏในงานทดสอบ สมมติฐานเกี่ยวกับพฤติกรรมที่ไม่ได้รับการรับประกันทำให้การทดสอบหลายประเภทพังได้ เช่น การเปลี่ยนลำดับขององค์ประกอบใน Hashmap การเปลี่ยนข้อความข้อผิดพลาด หรือการเปลี่ยนวิธีจัดการปีอธิกสุรทิน
ผู้เขียนแพ็กเกจบางรายอาจยอมรับ Hyrum's Law มากกว่า ในคอมเมนต์ของแพ็กเกจ
jsonมีการกล่าวว่าแม้จะเป็นรายละเอียดภายใน แต่ก็พบว่ามีแพ็กเกจที่ถูกใช้อย่างแพร่หลายเข้าถึงมันผ่าน linkname