การรีวิวโค้ดต้องอาศัยการอ่าน
(hauleth.dev)- การรีวิวโค้ดไม่ใช่ขั้นตอนเชิงพิธีการก่อนปล่อยขึ้นระบบ แต่เป็นกระบวนการย้ายความรับผิดชอบต่อเหตุขัดข้อง ปัญหาความปลอดภัย และการลบข้อมูล จากคนคนเดียวไปเป็น ความรับผิดชอบของทีม
- การมี evals, การทดสอบ, feature flags, guardrails และ observability ที่ดีขึ้น อาจเป็นคำตอบเพื่อลดความกังวลจากการปล่อยโค้ดที่ไม่ได้อ่าน แต่ก็ถูกวิจารณ์ว่าเป็นแนวทางที่พลาดเป้าหมายเรื่อง การกระจายความรับผิดชอบ ของการรีวิว
- การขอให้อนุมัติโดยไม่อ่าน ก็ไม่ต่างจากการให้คนกดปุ่มโดยไม่ต้องคิด และนำไปสู่การเสียดสีแบบ button roulette ที่สุ่มรวม PR ใดก็ได้ตราบใดที่ CI เป็นสีเขียวทั้งหมด
- การรีวิวโค้ดช่วยให้สมาชิกทีมได้เห็นหลายส่วนของโค้ดเบสขนาดใหญ่ ทำให้ bus factor ลดลง และยังทำหน้าที่เป็นกลไกการเรียนรู้สำหรับสมาชิกใหม่ให้คุ้นเคยกับโค้ดและวัฒนธรรมการเขียนโค้ด
- หากจะบังคับให้ปล่อยโค้ดที่ไม่ได้อ่าน ก็ต้องมีหนังสือยกเว้นความรับผิดชอบเป็นลายลักษณ์อักษรต่อบั๊ก ปัญหาความปลอดภัย และ downtime ซึ่งบทสรุปคือแทบเป็นไปไม่ได้ที่จะได้สิ่งนั้น
เป้าหมายของการรีวิวคือการกระจายความรับผิดชอบ ไม่ใช่แค่อนุมัติ
- จุดตั้งต้นคือคำถามในบทความของ Charity Majors “AI enthusiasts are in a race against time, AI skeptics are in a race against entropy” ที่ว่า “ต้องมีอะไรบ้างจึงจะรู้สึกสบายใจพอที่จะปล่อยโค้ดที่ไม่ได้อ่านขึ้นโปรดักชัน”
- คำตอบอย่าง evals ที่ดีขึ้น การทดสอบ feature flags guardrails observability การแยก dependencies การลด blast radius และการเริ่มจากการเปลี่ยนแปลงเล็ก ๆ ที่อยู่นอก critical path ถูกมองว่าเลี่ยงประเด็นสำคัญของการรีวิว
- จุดประสงค์ของการรีวิวคือไม่ปล่อยให้ภาระจากเหตุขัดข้อง ปัญหาความปลอดภัย หรือการลบข้อมูลโดยไม่ตั้งใจ ตกอยู่กับคนคนเดียว แต่แบ่งเป็น ความรับผิดชอบของทีม ระหว่างผู้เขียนและผู้รีวิวทั้งหมด
- หากจะให้ “อนุมัติโดยไม่อ่าน” เหตุผลที่จะให้คนมากดปุ่มด้วยมือตัวเองก็ยิ่งน้อยลง และจึงเกิดคำเสียดสีว่า
button rouletteซึ่งคือการสุ่มรวมหนึ่งใน PR ที่ถูกจัดสรรมาให้ถ้า CI เป็นสีเขียวทั้งหมด
สิ่งที่การรีวิวแบบไม่อ่านทำให้สูญเสียไป
- การรีวิวโค้ดบังคับให้สมาชิกทีมได้เห็นส่วนอื่น ๆ ของโค้ดเบส ช่วยชดเชยข้อจำกัดที่ว่าในระบบขนาดใหญ่มากนั้น ไม่มีใครรู้ทุกส่วนได้ตลอดเวลา
- กระบวนการรีวิวช่วยลด bus factor และช่วยให้สมาชิกหลายคนในทีมคุ้นเคยกับทั้งโค้ดเบสและวัฒนธรรมการเขียนโค้ดมากขึ้น
- หากทุกคนอนุมัติโดยไม่อ่าน ผลด้านการเรียนรู้นี้ก็จะหายไป และไม่เพียงทำให้ bus factor กลับขึ้นไปเป็น 1 แต่ยังก่อปัญหาการโยนออกไปให้บุคคลที่สาม
- ข้อสรุปคือ หากจะยอมรับคำสั่งให้ปล่อยโค้ดที่ไม่ได้อ่านขึ้นโปรดักชัน คนที่ออกคำสั่งนั้นต้องออกหนังสือยกเว้นความรับผิดชอบเป็นลายลักษณ์อักษรต่อบั๊ก ปัญหาความปลอดภัย และ downtime ให้ด้วย
1 ความคิดเห็น
ความคิดเห็นจาก Lobste.rs
รู้สึกต่อต้านอย่างมากกับข้ออ้างที่ว่าจุดประสงค์ของการรีวิวคือการกระจายความรับผิดชอบ
ถ้า โค้ดที่ merge เข้า main ทำให้โปรดักชันพัง นั่นเป็นความรับผิดชอบของผู้เขียน ไม่ใช่ของฉันหรือของทั้งทีม
ในฐานะวิชาชีพ นี่คืองานที่มีลายเซ็นของตัวเองกำกับอยู่ และถ้าแบบสะพานที่ประทับตราด้วยใบอนุญาต P.E. ทางวิศวกรรมโยธาทำให้คนตาย นั่นก็เป็นผลงานและความรับผิดชอบของเจ้าตัวเช่นกัน
ความรับผิดชอบของทีมคือ ในฐานะนักพัฒนาและผู้ดูแลโค้ดเบส ต้องทำให้ ไม่ว่าโค้ดของใครก็ทำให้โปรดักชันพังไม่ได้
การ merge เข้า main หมายความว่ามีคนรีวิว ตรวจสอบการเปลี่ยนแปลง ถกเรื่องดีไซน์ แก้ไขหลายรอบ แล้วจึงอนุมัติ
ไม่มีใครสร้างหอไอเฟลคนเดียว และการโทษบุคคลในที่ทำงานมีแต่จะก่อให้เกิดความคับแค้นใจและ วัฒนธรรมที่เป็นพิษ
ถ้าเป็นพฤติกรรมที่เกิดซ้ำเป็นรูปแบบ นั่นเป็นเรื่องที่ HR ควรจัดการ
ถ้าความรับผิดชอบเป็นศูนย์ ผู้รีวิวก็ไม่มีประโยชน์ และไม่มีเหตุผลอะไรที่ต้องรีวิว
การกระจายความรับผิดชอบเป็นผลลัพธ์มากกว่า ส่วนเป้าหมายหลักคือ การจับข้อผิดพลาด ที่คนเดียวพลาดได้ง่าย แต่พอมีมากกว่าหนึ่งคนแล้วพลาดได้ยาก
อย่างไรก็ตาม ผมมองว่าในซอฟต์แวร์มีการใช้รีวิวมากเกินไป และรีวิวไม่สามารถเป็น สิ่งทดแทนงานวิศวกรรม ได้
ผมไม่คิดว่าการมอง “อนุมัติโดยไม่อ่านโค้ด” ว่าเท่ากับ “อนุมัติแบบไม่คิด” จะถูกต้องนัก
ลองนึกภาพว่ามี บทพิสูจน์ความถูกต้อง แนบมากับโปรแกรม ใน PR สามารถอ่านนิยามและทฤษฎีบทได้ CI ใช้เครื่องมือแบบกำหนดผลได้แน่นอนเพื่อตรวจว่าโปรแกรมกับบทพิสูจน์สอดคล้องกัน และยังตรวจข้อกำหนดที่ไม่ใช่เชิงฟังก์ชันอย่างอัตราคอนทราสต์ benchmark ประสิทธิภาพ และ tail latency ด้วย ส่วนการเปลี่ยน UI ก็มี prototype ให้ลองเล่นได้ง่าย แบบนั้นจะเป็นอย่างไร
ต่อให้เป็นโลกแบบนั้น ก็ยังน่าสงสัยว่าเราจำเป็นต้องยึดติดกับการอ่านโค้ดทีละบรรทัดมากเท่าตอนนี้หรือไม่
แม้แต่ทุกวันนี้ คนส่วนใหญ่ก็เขียน SQL โดยไม่ได้ตรวจสอบทีละจุดว่า query plan ตรงกับสิ่งที่ต้องการแบบเป๊ะ ๆ หรือไม่
บทความต้นทางอ่านแล้วให้ความรู้สึกใกล้เคียงกับการบอกว่า “ลองนิยามโลกในอุดมคติที่เรารู้สึกว่าสามารถ deploy ได้โดยไม่ต้องอ่านโค้ดตามตัวอักษรดู” แล้วค่อยถามต่อว่า “เราจะค่อย ๆ เคลื่อนจากปัจจุบันไปสู่โลกนั้นได้อย่างไร”
จะเถียงกันได้ว่าอุตสาหกรรมโดยรวม หรือบริษัทและโค้ดเบสใดโค้ดเบสหนึ่ง ยังอยู่ห่างจากจุดนั้นแค่ไหน แต่ถ้าจินตนาการโลกในอุดมคตินั้นอย่างจริงจัง คนส่วนใหญ่ก็น่าจะนึกเกณฑ์บางอย่างออกได้
ผมเข้าใจว่าด้วยกระแสในอุตสาหกรรมตอนนี้ หลายคนอาจรับความหมายเป็น “แบบไม่คิด” แต่ผมไม่คิดว่าสิ่งที่ Charity เขียนต้องการสื่อแบบนั้น
ซึ่งสิ่งนี้จะเกิดขึ้นไม่ได้ถ้าไม่อ่านโค้ด ต่อให้มีเทสต์ดีแค่ไหนก็ตาม
ถ้า Alice เพิ่มโค้ดเข้าไป Bob เป็นคนรีวิว แล้วหลังจากนั้น Alice ลาพักร้อน Bob ก็ควรจะรู้ส่วนนี้ดีพอและมีความรับผิดชอบพอที่จะเข้าไปแก้หรือเพิ่มฟีเจอร์ใหม่ได้
ถ้า Bob แค่ประทับตรารับรองบทพิสูจน์ความถูกต้อง เขาก็ยังไม่พร้อมที่จะดูแลโค้ดเบสนั้นต่อไป
ถึงจะมีส่วนร่วมในขั้นตอน commit แต่ถ้าความรู้หรือ ความเป็นเจ้าของ ไม่เพิ่มขึ้น ก็แทบไม่ต่างจากไม่ได้มีส่วนร่วมจริง ๆ
แต่ compiler เป็นสิ่งที่กำหนดผลได้แน่นอน ในขณะที่ LLM เป็นเครื่องมือไม่กำหนดผลแน่นอนซึ่งอาจสร้างเทสต์ที่น่าสงสัยได้
เรามีโปรแกรมที่เปลี่ยนคำสั่งหรือโค้ดที่มนุษย์เขียนให้เป็นโค้ดหรือ intermediate representation ที่เครื่องอ่านได้อยู่แล้ว และเพราะมันรับประกันได้ว่าผลลัพธ์ที่สร้างขึ้นมีความสัมพันธ์แบบใดกับอินพุต เราจึงเชื่อถือผลลัพธ์ได้โดยไม่จำเป็นต้องตรวจมันทุกครั้ง
บางครั้งเราอ่านผลลัพธ์จาก compiler ผ่านเครื่องมืออย่าง Godbolt เพื่อดูการ optimize แต่โดยทั่วไปนอกจากนั้นก็ไม่จำเป็น
การพยายามทำสิ่งนี้อีกครั้งในระดับนามธรรมอื่นที่ไม่กำหนดผลแน่นอนอาจดูสมเหตุสมผล แต่สุดท้ายก็เป็นแค่การเลียนแบบหลักประกันความถูกต้องที่ compiler ให้ได้ และท้ายที่สุดปัญหาก็จะเกิดขึ้น
ในระดับที่ลึกกว่านั้น ผมมองว่าข้อถกเถียงเรื่อง LLM เป็นอาการของปัญหาที่ว่าภาษาโปรแกรมแบบกำหนดผลได้แน่นอนที่มีอยู่เดิมยังแสดงออกได้ไม่พอ และเครื่องมือก็ยังมีประสิทธิภาพไม่พอ
LLM อาจทำให้รู้สึกเหมือนแก้ปัญหานั้นได้ แต่จริง ๆ แล้วไม่ใช่วิธีแก้ และเป็นเพียงการซ้อนชั้นของการอ้อมอีกชั้นพร้อมต้นทุนด้านประสิทธิภาพบนรากฐานที่จำกัดเกินไป
มันใกล้เคียงกับ pseudo-compiler ราคาแพงและเต็มไปด้วยบั๊ก ที่ทำงานอยู่บน interpreter และบนภาษาเครื่องที่ถูก compile มาอีกทอดหนึ่ง
เพราะแบบนั้นผมจึงคิดว่ามันเป็นทางตันทางเทคนิค
สำหรับบริษัท มันอาจเป็นเส้นทางสู่กำไรระยะสั้น แต่ผมไม่เชื่อว่ามันจะทำให้ซอฟต์แวร์ หรือความสัมพันธ์ระหว่างมนุษย์กับการใช้และการสร้างซอฟต์แวร์ ดีขึ้น
ซอฟต์แวร์เป็นมากกว่าแค่เทคโนโลยีเพื่อปล่อยผลิตภัณฑ์ออกสู่ตลาด
การแยกคิดตามกรณีใช้งานน่าจะช่วยได้
ถ้าเป็นแค่การขึ้น JavaScript ใหม่สำหรับ UI ของแอปภายใน ผมคิดว่าไม่จำเป็นต้องไล่ดูไปถึง CSS เสมอไปก็ได้