- ช่วงหลังมานี้ นักพัฒนาต้องใช้เวลามากขึ้นในการแก้ไขและปรับปรุง โค้ดที่สร้างโดย LLM (Large Language Model)
- เช่นเดียวกับโค้ดเลกาซีเดิม หากต้องการแก้โค้ดอย่างปลอดภัย ก็ต้องเข้าใจก่อนว่า ทำอะไรไว้ และทำไมจึงออกแบบแบบนั้น แต่โค้ดจาก LLM ทำให้กระบวนการนี้ยากขึ้น
- บางทีมช้าลงเพราะรีวิวและทำโค้ดใหม่อย่างเพียงพอ แต่หลายทีมกลับนำ โค้ดที่แทบไม่มีใครอ่านและทดสอบแบบลวกๆ เข้าไปไว้ในรีโพซิทอรีโดยตรง
- สิ่งนี้ก่อให้เกิด “หนี้ความเข้าใจ (Comprehension Debt)” และสุดท้ายเมื่อจำเป็นต้องแก้ไขโค้ด ก็จะย้อนกลับมาเป็นต้นทุนด้านเวลาที่สูงกว่าเดิม
- โดยทั่วไป LLM ช่วยแก้ปัญหาได้ในระดับประมาณ 70% แต่ไม่อาจหลีกเลี่ยง “Doom Loop” ที่ล้มเหลวซ้ำๆ ได้ และท้ายที่สุดย่อมต้องเกิดสถานการณ์ที่มนุษย์ต้องมาเข้าใจและแก้โค้ดด้วยตนเอง
โค้ดที่สร้างโดย LLM และปัญหาหนี้ความเข้าใจ
- ในช่วงหลัง วงการพัฒนาซอฟต์แวร์มีแนวโน้มใช้งานเครื่องมือสร้างโค้ดอัตโนมัติบนพื้นฐาน LLM เช่น ChatGPT, Copilot มากขึ้น
- เครื่องมือเหล่านี้สามารถ สร้างโค้ดที่ซับซ้อนได้อย่างรวดเร็ว แม้นักพัฒนาจะยังไม่มีความรู้หรือความเข้าใจโดยตรง
- แต่ในกระบวนการนี้ มักไม่สามารถมองเห็น เจตนา ข้อจำกัด และหลักการทำงาน ของโค้ดได้อย่างชัดเจน จึงเกิดการสะสมของ 'หนี้ความเข้าใจ'
หนี้ความเข้าใจ (Comprehension Debt) คืออะไร
- หนี้ความเข้าใจหมายถึงสภาวะที่สมาชิกในทีม ยังไม่เข้าใจคุณภาพ โครงสร้าง และเจตนาของโค้ดได้อย่างเพียงพอ
- ในระยะสั้นอาจช่วยเพิ่มความเร็วในการพัฒนา แต่ในระยะยาวมีความเสี่ยงที่จะนำไปสู่ผลกระทบหลายด้าน เช่น ต้นทุนการบำรุงรักษาที่เพิ่มขึ้น การเกิดบั๊ก และข้อจำกัดในการขยายฟีเจอร์
ความเสี่ยงเพิ่มเติมของโค้ดที่สร้างโดย LLM
- โค้ดที่ LLM สร้างมักให้ผลลัพธ์ออกมาอย่างรวดเร็ว โดยไม่มีคอมเมนต์หรือบริบทที่ชัดเจน
- มีโอกาสสูงที่จะเผยให้เห็นปัญหาเรื่อง การแบ่งปันความรู้ที่ไม่เพียงพอ ภายในทีม และ ความเข้ากันได้ที่ไม่ดี กับระบบเดิม
- หากพึ่งพาโค้ดจาก LLM ซ้ำๆ อาจทำให้ ความน่าเชื่อถือของโค้ดทั้งโปรเจกต์ลดลง
เปรียบเทียบกับหนี้ทางเทคนิค
- หนี้ทางเทคนิคแบบเดิมเป็นผลจาก การประนีประนอมอย่างมีสติของนักพัฒนา แต่หนี้ความเข้าใจจาก LLM อาจ สะสมโดยไม่รู้ตัว จึงยิ่งอันตราย
- เป็นปัญหาที่รับรู้ได้ยาก และการตามหาสาเหตุรวมถึงการแก้ไขก็ ซับซ้อนยิ่งกว่าเดิม
- ระหว่างแก้ปัญหา มักพบกับ “Doom Loop” (วงจรล้มเหลวที่ต่อให้เรียกใช้ LLM ซ้ำๆ ก็ยังไม่สำเร็จ) อยู่บ่อยครั้ง
บทสรุปและข้อคิด
- ท้ายที่สุดแล้ว มนุษย์ยังต้องเป็นฝ่ายอ่านและแก้โค้ดด้วยตนเอง
- เมื่อนำ LLM มาใช้ สิ่งสำคัญคือ การทำเอกสารและการแบ่งปัน เพื่อให้สมาชิกทั้งทีมเข้าใจ บริบทและเจตนา ของโค้ดร่วมกัน
- จำเป็นต้องมีมาตรการในระดับองค์กร เช่น การเข้มงวดด้าน code review การเสริมคอมเมนต์และเอกสาร และเซสชันแบ่งปันความรู้
- หากไม่บริหารจัดการหนี้ความเข้าใจ ข้อดีของเครื่องมืออัตโนมัติ ก็อาจกลับกลายเป็นความเสี่ยงระยะยาวได้
- ทั้งอุตสาหกรรมกำลังนั่งอยู่บน ภูเขาของหนี้ความเข้าใจที่พอกพูนขึ้นอย่างรวดเร็ว
8 ความคิดเห็น
ผมก็เช่นกัน เพราะ AI ไม่สามารถตัดสินใจได้ทั้งหมดเสมอไป จึงเป็นผมที่ตัดสินใจเองกับโค้ดทุกบรรทัด และตรวจสอบด้วยตัวเองด้วยว่ามันออกมาดีหรือไม่
สำหรับผมก็คงใช้แค่ทำสnippetสั้น ๆ ไม่เกิน 10 บรรทัดเท่านั้น (เช่น parsing JSON, เขียนการ sort) ต่อให้ใช้แค่นี้ก็ดูเหมือนว่าจะช่วยประหยัดเวลาได้อย่างมาก
การใช้ AI ช่วยทำโครงร่างเบื้องต้นนั้นโอเคอยู่ แต่การเก็บรายละเอียดให้ดีจนถึงขั้นสุดท้ายดูเหมือนจะยากมากจริงๆ
ส่วนตัวผมเองก็เคยรู้สึกถึงผลข้างเคียงอยู่บ่อยครั้งตอนให้ LLM เขียนโค้ดตั้งแต่ 0 ไปถึง 90 ดังนั้นช่วงนี้ผมเลยพยายามทำเองตั้งแต่ 0 ถึง 90 ให้มากที่สุด แล้วค่อยนำมันมาใช้เป็นหลักในช่วงเปลี่ยนจาก 90 ไป 100 ซึ่งก็รู้สึกพอใจมากครับ
ความคิดเห็นจาก Hacker News
เมื่อการพึ่งพา LLM หนักขึ้น ก็ได้เห็นว่าปัญหาที่มีอยู่เดิมยิ่งเลวร้ายลง
มีการยกแนวคิด "การสร้างทฤษฎี" ของ Naur ขึ้นมาอธิบาย และชี้ว่าถ้าทีมพัฒนาโปรแกรมสลายตัวลง โปรแกรมนั้นก็แทบจะถือว่าตายไปแล้ว
มีการอ้างเหตุผลของ Lamport ที่ว่า 'programming ≠ coding' เพื่อเน้นว่าหัวใจของการเขียนโปรแกรมคือการสร้างทฤษฎีเกี่ยวกับ 'จะทำอะไร และทำอย่างไร'
คิดว่ายิ่งเป็นโปรแกรมเมอร์ที่ไม่ได้สร้างโมเดลหรือทฤษฎีที่จำเป็น ก็ยิ่งมีแนวโน้มจะรู้สึกว่า LLM ช่วยตัวเองได้อย่างรวดเร็ว
เคยมีประสบการณ์ว่าตอนที่ถอยห่างจากคอมพิวเตอร์และเทคโนโลยีโดยสิ้นเชิง กลับสร้างคุณค่าให้โครงการซอฟต์แวร์ได้มากกว่า
เมื่อรู้แน่ชัดว่าต้องการอะไร ความเร็วในการพัฒนาจะเพิ่มขึ้นอย่างก้าวกระโดด และในจังหวะนั้น LLM ก็มีประโยชน์มาก
ถ้ามีเป้าหมายชัดเจน ก็จะแยกแยะ hallucination ของ LLM ได้ทันที
ไม่คิดว่าวิธีเริ่มต้นแบบจ้องผืนผ้าใบเปล่า ๆ โดยไม่มีทิศทางจะมีประสิทธิภาพ
LLM อาจช่วยให้ออกตัวได้ แต่ถ้าพลาดก็มักพาออกนอกทางได้ง่าย
ปัญหาที่ยากที่สุดกลับเคยแก้ได้ตอนกำลังทำอาหารอยู่ในครัวแล้วครุ่นคิดไปด้วย
เหตุผลหนึ่งที่ใช้ AI coding ได้สำเร็จกว่าเพื่อนร่วมงาน คือก่อนมี LLM ก็ทำงานแบบสร้าง prototype อย่างรวดเร็ว แล้วคอยปรับโครงสร้างใหม่ทั้งหมดหรือทิ้งแล้วเริ่มใหม่ซ้ำ ๆ อยู่แล้ว
แนวทางแบบนี้ (rapid prototyping, การ refactor อย่างต่อเนื่อง ฯลฯ) ค่อนข้างเป็นที่รู้จัก แต่วิศวกรจำนวนมากมักพยายามออกแบบให้สมบูรณ์แบบตั้งแต่แรก หรือไม่ก็เอาแต่ปะ patch ต่อจาก prototype โดยไม่ปรับปรุงโครงสร้าง
เมื่อมี AI ก็สามารถทำ implementation หลายแบบคู่ขนานได้ในต้นทุนต่ำ จึงทดลองและเปรียบเทียบหลายเวอร์ชันได้ และสุดท้ายสร้างทฤษฎีของโปรแกรมหรือการออกแบบที่แข็งแรงกว่าได้อย่างรวดเร็วและมีประสิทธิภาพ
AI ช่วยย่นลูปนี้ลง และทำให้โฟกัสกับการรีวิวผลลัพธ์ได้มากขึ้น จึงทำให้กระบวนการพัฒนามีประสิทธิภาพขึ้นมาก
น่าประทับใจที่แนวคิด "การสร้างทฤษฎี" เชื่อมโยงกับ "หนี้ความเข้าใจ" ของโค้ดจาก LLM
คิดว่านี่เกี่ยวข้องลึกซึ้งไม่ใช่แค่กับการเขียนโปรแกรม แต่รวมถึงกระบวนการคิดและความเข้าใจของมนุษย์ด้วย
โค้ด ข้อความ หรือภาพที่ LLM สร้างขึ้นเป็นเพียงผลลัพธ์ผิวหน้าเท่านั้น และหากไม่ได้สร้างหรือผ่านประสบการณ์ของทฤษฎีเบื้องหลังด้วยตนเอง ก็ย่อมจบลงที่ความเข้าใจระดับผิวเผิน
แม้วันหนึ่ง LLM จะสามารถทำการสร้างทฤษฎีได้เอง แต่ก็ยังรู้สึกว่าความเข้าใจแบบประดิษฐ์ที่มนุษย์ไม่ได้เข้าไปมีส่วนร่วมโดยตรงนั้นมีความหมายไม่มากพอ
ยิ่งเครื่องจักรคิดแทนได้สะดวกเท่าไร ก็ยิ่งกังวลว่าความสามารถในการ <เข้าใจ> ของมนุษย์จะค่อย ๆ เสื่อมถอยลง
เห็นด้วยกับข้อโต้แย้งของ Lamport และในขณะเดียวกันก็คิดว่า AI อาจช่วยได้บางส่วนในกระบวนการ "การสร้างทฤษฎี" ด้วยเช่นกัน—ทั้งในแง่ความเข้าใจ codebase, algorithm และภาพรวมของระบบ ไม่ว่าจะกับทีมเดิมหรือทีมที่รับช่วงต่อ
ถึงจะยากที่จะทดแทนความรู้ทั้งหมดได้ แต่ก็คาดหวังว่า AI จะช่วยอุดช่องว่างได้บางส่วน
เคยมีกรณีที่ทีมใหม่ต้องรับช่วงโปรเจกต์หลังจากนักพัฒนาเดิมหายไปหมด แล้วความรู้ทั้งหมดของทีมก่อนหน้าก็เหมือนระเหยหาย ทำให้ลำบากมาก
พยายามทำความเข้าใจการออกแบบเดิมจนสร้างบั๊กเพิ่มเป็นจำนวนมาก และสุดท้ายก็ต้องลำบากกับการเขียนใหม่และขยายโค้ดเกือบทั้งหมด
แต่ท่ามกลางความยากลำบากนั้น กลับได้เดินซ้ำตามปัญหาการออกแบบหลายอย่างด้วยตัวเองเช่นกัน
LLM มักสร้างโซลูชันที่ใช้งานได้ แต่บ่อยครั้งก็ให้โค้ดที่ซับซ้อนเกินจำเป็นมาก
ตอนเขียนครั้งแรก ผู้เขียนมักเข้าใจปัญหาดีที่สุด จึงลบความซับซ้อนได้ง่าย แต่เมื่อเวลาผ่านไป โค้ดซับซ้อนนั้นอาจถูกเข้าใจผิดว่าจำเป็นจริง ๆ จนยิ่งยากที่จะลดทอนให้เรียบง่ายลงอย่างมาก
ผู้ดูแลโค้ดมักขาดบริบทหรือความรู้พื้นหลัง จึงไม่ทันนึกว่าจริง ๆ แล้วอาจมีทางเลือกที่ง่ายกว่านี้
อย่างแรก ต้องเขียน prompt ให้ชัด เพื่อชี้นำไม่ให้ LLM สร้างผลลัพธ์ที่ซับซ้อนเกินความจำเป็น
อย่างที่สอง ต้องส่งต่อกฎ การสอน หรือบริบทที่ทำให้มันแก้ปัญหาอย่างเรียบง่ายที่สุดเสมอ
สุดท้าย หากได้โซลูชันที่ซับซ้อนมา ก็ใช้ prompt เพิ่มเติมเพื่อขอให้ลดความซับซ้อนได้
ปัญหาที่ LLM สร้างโค้ดจำนวนมหาศาลซึ่งดีบักยากนั้นมีอยู่จริง
แม้จะมีหลักการว่า 'ทีมที่ให้ความสำคัญกับคุณภาพต้องรีวิวและทำความเข้าใจให้เพียงพอ' แต่ความเร็วในการสร้างโค้ดนั้นสูงเกินไปจนการรีวิวตามไม่ทัน กลายเป็นคอขวดหรือไม่ก็จบลงที่การอนุมัติแบบพิธีการ
รอบตัวมีแต่การเพิ่มขั้นตอนรีวิวเข้าไปเรื่อย ๆ แต่แนวทางแบบนี้ได้ผลกับนักพัฒนารุ่นจูเนียร์เท่านั้น และ AI ก็ไม่ได้เรียนรู้ จึงทำให้ปัญหาเดิมเกิดซ้ำ
LLM ต้องการบริบทจำนวนมากมาก แต่คนส่วนใหญ่กลับแทบไม่ให้ข้อมูลอะไรเลย แล้วใช้แบบ "ช่วยเขียนฟังก์ชันแก้ปัญหานี้ให้หน่อย" เท่านั้น
สุดท้ายทุกคนกำลังกองภูเขาโค้ดที่ไม่มีใครเข้าใจ ซึ่งก็คือ tech debt
สิ่งที่ต้องการจริง ๆ ในระดับพื้นฐานคือ 'primitive' ที่ช่วยส่งบริบทได้อย่างมีประสิทธิภาพมากขึ้น ว่าทำไม LLM ถึงควรสร้างสิ่งนี้ โดยมีฉากหลัง เจตนา และกรณีก่อนหน้าแบบใดรองรับ
ถ้า code review กลายเป็นคอขวด ก็ยังคิดว่าการมีคอขวดเฉพาะที่ code review ยังดีกว่าต้องให้คนคนเดียวทำทั้ง coding และ review
เครื่องมือที่จะช่วยเสริมกระบวนการนี้ (lint, fuzzing, test ฯลฯ) ก็มีอยู่แล้ว
สำหรับคนที่ยังขาดทักษะในการทำ architecture ให้ทั้งโปรเจกต์ หรืออ่านและวิเคราะห์โค้ดได้อย่างรวดเร็ว ยุค LLM อาจจะยาก แต่ทักษะเหล่านี้พัฒนาได้ และเมื่อเวลาผ่านไปทุกคนก็น่าจะปรับตัวได้
ชอบงานสายนี้อยู่แล้ว จึงมองความท้าทายใหม่นี้ในทางบวก
เคยสร้างไฟล์ instruction .md หลายชุดเพื่ออัปเดตกฎการเขียนโค้ดที่เอเจนต์ต้องทำตาม กับดักที่ห้ามเจอเด็ดขาด และลิงก์ไปยังเอกสารมาตรฐานการเขียนโค้ด
โมเดลอย่าง Gemini และ Claude ค่อนข้างสะท้อนคำสั่งบนเอกสารลักษณะนี้ได้ดีในระดับหนึ่ง แต่บางครั้งก็ยังทำผิดซ้ำ ๆ (เช่น สั่งห้ามใช้
autoใน C++ แต่ก็ยังใช้)คาดหวังว่าเมื่อโมเดลดีขึ้น การจัดการ feedback แบบนี้ก็จะพัฒนาขึ้นด้วย
ท้ายที่สุด รู้สึกว่าการเลิก "vibe coding" แล้วให้คนดูแลโครงสร้างโค้ดและปฏิสัมพันธ์ระหว่างหน่วยต่าง ๆ เอง ส่วน AI รับหน้าที่เรื่อง syntax และการพิมพ์ จะเป็นจุดประนีประนอมที่เหมาะที่สุด ทั้งเพิ่ม productivity และทำให้นักพัฒนายังคุมทิศทางโดยรวมได้ต่อเนื่อง
หลังจากเปลี่ยนวิธีคิดในการจัด prompt และบริบท สัญชาตญาณในการใช้ LLM ก็ดีขึ้นมาก
เริ่มมองผ่านมุมที่ว่า prompt และบริบทช่วยบีบพื้นที่ความน่าจะเป็นของผลลัพธ์ให้แคบลง
กระบวนการนี้มีประสิทธิภาพมากในการอัดฉีดทฤษฎีของโค้ดให้กลับมาใช้ซ้ำได้
แต่อย่างไรก็ดี การเตรียมบริบทเช่นนี้ต้องใช้แรงและการคิดมาก และก็ยังไม่ง่ายที่จะหาจุดแบ่งว่าเมื่อไรควรลงมือเขียนเอง และเมื่อไรควรมอบหมายให้ LLM ทำ
เห็นด้วยกับคำชี้ว่า "primitive มันต่างกัน" และคิดว่าหน่วยที่สำคัญจริง ๆ คือ 'test'
เวลาที่ให้โมเดลเขียนโค้ด ก็ให้มันเขียน test มาด้วย และตรวจเสมอว่า test อ่านเข้าใจง่ายหรือไม่
ควร merge โค้ดก็ต่อเมื่อ test ทั้งหมดผ่านเท่านั้น
ต้องปรับปรุง test infrastructure อย่างต่อเนื่อง เพื่อไม่ให้ test ทั้งชุดช้าจนเกินไป
โค้ด legacy แบบเก่ามักมีลักษณะร่วมคือไม่มี test และสิ่งนี้ก็ยังใช้ได้เหมือนเดิมในยุค LLM
สำหรับประเด็นที่ว่า "มันกลายเป็นคอขวด" นั้น ต่อให้เป็นโค้ดจาก StackOverflow ก็ยังต้องอ่านและตรวจดูก่อนใช้อยู่ดี เพราะฉะนั้นสุดท้ายมนุษย์ก็เป็นคอขวดอยู่แล้ว
สรุปคือถ้าไม่ผ่านกระบวนการแบบนี้ ก็แทบเท่ากับว่าไม่สามารถใช้โค้ดนั้นได้เลย
เมื่อไม่นานมานี้ ในพอดแคสต์ของ Dwarkesh Patel มีแขกรับเชิญแนะนำให้อ่านนิยายเรื่อง <A Deepness In The Sky> และพอได้อ่านจริงก็ประทับใจที่ระบบคอมพิวเตอร์ในอีกหลายพันปีข้างหน้า รวมถึงความรู้ legacy จากอดีต มีบทบาทสำคัญมาก
เป็นนิยายยอดเยี่ยมที่เล่าเรื่องคุณค่าของ legacy code และความรู้ในองค์กรได้อย่างสนุก จึงน่าแนะนำ
พอดแคสต์: https://www.youtube.com/watch?v=3BBNG0TlVwM
ข้อมูลหนังสือ: https://amzn.to/42Fki8n
น่าเสียดายที่นักเขียน Vernor Vinge เสียชีวิตแล้ว และก็รู้สึกว่าไอเดียของเขายิ่งเวลาผ่านไปก็ยิ่งให้แรงบันดาลใจในโลกจริงมากขึ้น
ส่วนที่บรรยายถึงกระบวนการกลายเป็นโปรแกรมเมอร์ในอนาคตอันไกลนั้นน่าสนใจมาก
เพราะมีไลบรารีและแพ็กเกจจำนวนมหาศาล ความสามารถหลักจึงไม่ใช่การเขียนโค้ดใหม่ แต่เป็นการค้นหาและประกอบโมดูลที่มีอยู่แล้ว
การเข้าใจนัยรายละเอียดและการตีความของโค้ดเดิมอย่างทะลุปรุโปร่งถูกบรรยายว่าเป็นทักษะที่แท้จริง
ดูเหมือนว่า "A Deepness In The Sky" จะเป็นหนังสือเล่มที่สองของซีรีส์ เลยสงสัยว่าอ่านได้เลยไหมถ้ายังไม่ได้อ่านเล่มแรก
ถามว่าสามารถเริ่มจากเล่มนี้ได้หรือไม่
นักพัฒนาส่วนใหญ่ไม่ได้เข้าใจถึงระดับ assembly หรือ machine code
ภาษาระดับสูงกลายเป็นชั้นแกนกลางของการสื่อสารและการทำงานร่วมกันระหว่างมนุษย์
เมื่อ LLM เข้ามา ชั้นนั้นก็กำลังถูกดันไปสู่การพัฒนาด้วย natural language และสเปก
สุดท้ายแล้วคิดว่าภาษาระดับสูงที่วิวัฒน์มาหลายสิบปีนั้นเกือบจะเป็นรูปแบบที่เหมาะที่สุดในการสื่อสารข้อกำหนดการทำงานของโปรแกรมแล้ว
ถ้าพยายามทำ abstraction เพิ่มด้วยภาษาธรรมชาติ ก็จะเกิดการสูญเสียข้อมูล และถ้าลงไปยังภาษาระดับต่ำก็จะยืดยาวเกินไป
การกระโดดไปสู่ภาษาธรรมชาตินั้นไม่ใช่แค่การเปลี่ยนชั้น abstraction แต่เป็นวิธีแบบใหม่โดยสิ้นเชิง
เครื่องมือเดิม ๆ (assembler, compiler, framework ฯลฯ) ล้วนอยู่บนตรรกะที่ hardcode ไว้และตรวจสอบเชิงคณิตศาสตร์ได้ แต่หลังยุค LLM เหมือนเรากำลังกระโดดเข้าสู่โลกที่เต็มไปด้วยความไม่แน่นอน การเดา และแม้แต่ hallucination
นักพัฒนา JavaScript จำนวนมากยังไม่เข้าใจแม้แต่แนวคิดระดับสูงอย่างโครงสร้างข้อมูลที่เหมาะสม, DOM, Node API ฯลฯ อย่างลึกซึ้ง
จึงเกิดการพึ่งพาชั้น abstraction มากเกินไป และไปถึงจุดที่ไม่เข้าใจกลไกการทำงานภายใน
คนนอกจึงหลีกไม่พ้นที่จะตั้งคำถามว่า "ที่นี่จริง ๆ แล้วกำลังทำอะไรกันอยู่?"
ปรากฏการณ์แบบนี้ถูกยอมรับเป็นเรื่องปกติไปแล้วในชีวิตประจำวัน
จึงเป็นการเปรียบเปรยว่าถึงไม่มีใครรู้ภายในโค้ดอย่างแท้จริงอยู่แล้ว การที่ LLM มาเขียนโค้ดก็ไม่ได้ต่างกันในเชิงสาระมากนัก
แม้ภาษาธรรมชาติจะมีบทบาทได้จริง แต่ก็คิดว่าจำเป็นต้องมีชั้นกลางที่มีความหมายเชิง semantics ที่เข้มงวด
ยกตัวอย่างการใช้ Rust ร่วมกับ LLM ซึ่งระบบ type ที่แข็งแรงจะช่วยปิดสถานะที่ไม่ถูกต้องออกไป และแม้ compile จะใช้เวลานาน แต่สุดท้ายผลลัพธ์ที่ต้องการมักออกมาถูกต้อง
ในชุมชน Rust มีวัฒนธรรมประมาณว่า "ถ้ามัน compile ได้ มันก็มักจะทำงานได้" แม้จะยังมี logical bug ได้อยู่ แต่พื้นที่ของความผิดพลาดที่แท้จริงจะแคบลง
ในอุดมคติแล้ว อยากให้มีภาษาการเขียนโปรแกรมที่เข้มงวดซึ่งนิยามความหมายเชิงตรรกะได้อย่างแม่นยำ พร้อมสเปกอย่าง precondition และ postcondition สะสมอยู่ด้านบน แล้วให้ LLM ทำหน้าที่แปลงภาษาธรรมชาติเป็น formal specification
ภาษาธรรมชาตินั้นโดยพื้นฐานแล้วไม่ชัดเจน และมีความกำกวมอยู่ในตัว
ถ้าเกิดความกำกวมในการ parse ภาษาการเขียนโปรแกรม เราจะมองว่าเป็นบั๊กร้ายแรง แต่ในภาษาธรรมชาติ ความกำกวมกลับเป็นกลไกสำคัญของการสื่อสาร เช่น บทกวี นัยยะ และการสื่อความหมายแฝง
คุณสมบัติแบบกำหนดแน่นอนของภาษาระดับสูง (import) ไม่ใช่ความต่างเพียงอย่างเดียว
ในการเขียนโปรแกรม ความเป็น deterministic ไม่ใช่ทั้งหมด และโค้ดที่ไม่ชัดเจนในเชิงความหมายต่อมนุษย์ก็ยังอาจ deterministic ได้เต็มที่
กล่าวคือ แกนเรื่อง 'abstraction สูง/ต่ำ' กับ 'deterministic/ความน่าจะเป็น' เป็นคนละประเด็นกันโดยสิ้นเชิง
สำหรับผมและทีม นี่ดูเหมือนคลื่นงานระลอกใหญ่ที่จะถาโถมเข้ามาในอนาคต
ตลอดเกือบ 8 ปีที่ผ่านมา เราเลี้ยงธุรกิจด้วยการกู้ชีพโค้ด legacy แต่ช่วงหลังความต้องการลดลง เพราะบริษัทต่าง ๆ หันไปพึ่ง LLM ในการเขียนโค้ด
แต่คาดว่าอีกเพียงราว 18 เดือน ถ้าประคองไปได้ ก็จะมีคำขอจำนวนมากให้ช่วยแก้ tech debt แบบ LLM ที่กองสะสมอย่างรวดเร็วในช่วงสั้น ๆ ซึ่งจะกลายเป็นโอกาสครั้งใหญ่
ความเสียหายจากหนี้ที่ Claude กองไว้พร้อมคำว่า "ตอนนี้โค้ดอยู่ในระดับ production แล้ว" กำลังจะเริ่มปรากฏให้เห็นในไม่ช้า
ได้ยินเรื่องเล่าจากคนรู้จักตอนรีวิว PR ที่ LLM สร้างขึ้น
PR นั้นดูภายนอกเหมือนฟังก์ชันทำงานสมบูรณ์แบบ แต่พอเปิดดูข้างในกลับพบว่าแท้จริงแล้วมันไม่ได้อัปเดต backend เลย แค่เล่นกับ cache ให้ดูเหมือนทำงานได้เท่านั้น
ต้องใช้ความพยายามมากในการโน้มน้าวผู้จัดการว่าโค้ดนี้ไม่ควรถูก merge
สุดท้ายจึงเริ่มสงสัยว่าน่าจะมีซอฟต์แวร์แบบ 'vibe coded' ที่ดูเหมือนใช้ได้แค่ผิวหน้าอยู่มากพอสมควรในโลกนี้
ในกรณีแบบนี้ คิดว่า merge ไปเลยแล้วปล่อยให้เจอแรงสะท้อนด้วยตัวเองอาจจะดีกว่า
คนเรามักได้บทเรียนก็ต่อเมื่อได้เผชิญผลของการตัดสินใจที่ผิดด้วยตัวเอง
ถ้าไม่มี feedback ก็ไม่มีการเรียนรู้ และผู้จัดการแบบนั้นก็จะยิ่งขาด sense of reality แล้วไปเพิ่มความคาดหวังและแรงกดดันที่เกินจริงให้ทีมพัฒนา จนเกิดวงจรที่พนักงานหมดแรงและถูกแทนที่ซ้ำ ๆ
สงสัยว่าผู้จัดการฝ่ายวิศวกรรมที่ไม่เชี่ยวชาญเทคนิคแบบนี้อยู่รอดในวงการมาได้นานอย่างไร
ตลอด 15 ปีที่ผ่านมาแทบไม่เคยเห็นผู้จัดการที่ไม่ใช่สายเทคนิคจริง ๆ เลย
ถ้าผู้จัดการแบบนี้ก่อปัญหา ก็ควรรายงานให้ CTO, CEO, เจ้าของ หรือผู้ลงทุนรับรู้
ไม่ใช่แค่โค้ดจาก LLM เท่านั้น ถ้าเป็นโค้ดที่คนอื่นเขียนไว้ ใครก็ตามก็ต้องจ่าย 'หนี้ความเข้าใจ' ทั้งนั้น
แม้แต่ในบริษัทใหญ่อย่าง Google วิศวกรใหม่ก็ยังต้องใช้เวลาหลายเดือนเพื่อทำความเข้าใจก่อนจะเปลี่ยนอัลกอริทึมครั้งใหญ่ได้อย่างรวดเร็ว
แต่โค้ดที่มนุษย์ออกแบบมาดีนั้น เข้าใจได้ง่ายกว่า output จาก LLM อย่างชัดเจน
สามารถถามคำอธิบายจากคนโดยตรงได้ ขณะที่ LLM ก็ให้คำตอบที่ดูน่าเชื่อได้เช่นกัน แต่ยังมีความต่างของบริบทจริงอยู่
ผมเองก็เคยทำ 'vibe coding' เยอะเหมือนกัน แต่สุดท้ายเพราะไม่ได้สะสม mental model ของโค้ดไว้ ถึงจะประหยัดเวลาในตอนแรก แต่ตอนดีบักจริงกลับเสียเวลามากกว่าเดิม
แน่นอนว่าในโลกจริงก็เป็นไปไม่ได้ที่จะวางการออกแบบทุกอย่างให้สมบูรณ์ตั้งแต่ต้น
และก็คิดว่าเกณฑ์ที่ใช้ 'จำนวนบรรทัดโค้ดที่ได้รับการยอมรับ' มาเป็นหลักฐานของ productivity หรือการประหยัดเวลานั้นเชื่อถือได้ยาก
การใช้โค้ดที่พึ่ง LLM อย่างได้ผลจริงต้องรีวิวอย่างระมัดระวังและค่อย ๆ ขัดเกลาให้เป็นรูปร่างที่ถูกต้อง
กระบวนการแบบนี้จริง ๆ แล้วใกล้เคียงกับ 'pair programming' มากกว่า
จึงเน้นว่าแนวทางใช้ output จาก LLM ตรง ๆ โดยไม่ตรวจอะไรเลย ("vibe coding") จะไม่มีทางมีประสิทธิภาพจริงได้
มีการยกกฎของ Kernighan (Kernighan's Law) มาพูดว่า "การดีบักยากกว่าการเขียนโค้ดสองเท่า"
ดังนั้นถ้า LLM เป็นคนสร้างโค้ด ก็อาจต้องใช้ LLM ที่ฉลาดกว่าสองเท่าเพื่อมาดีบักมัน
แต่ประสบการณ์ของผมไม่ถึงกับเป็นแบบนั้นเสมอไป และยังไงผมก็ต้องอยู่หลังพวงมาลัยเองตลอด
ใช้ Claude Code เป็นหลัก และทุกครั้งที่มันพลาดก็ต้องชี้ให้ชัดว่าผิดตรงไหน หรือไม่ก็ระบุจุดปัญหาให้เฉพาะเจาะจง
LLM ไม่รู้ด้วยตัวเองว่ามันพลาดอะไร จึงให้ความรู้สึกเหมือนกำลังทำงานกับนักพัฒนาจูเนียร์
สรุปคือการดีบักไม่จำเป็นต้องใช้สติปัญญาคนละระดับเสมอไป แต่ LLM ไม่สามารถรับรู้ปัญหาของตัวเองได้
สำหรับคำพูดที่ว่า "การดีบักต้องใช้คนที่ฉลาดกว่าสองเท่า" คิดว่าอาจเกี่ยวข้องกับความต่างของโหมด 'ความลึกในการคิด' ของ LLM ด้วย
ถ้าเป็นฟังก์ชันที่ซับซ้อน ก็จะให้ LLM เขียนคอมเมนต์โค้ดแนบอธิบายเจตนาและแนวทางให้ชัดเจนก่อนเสมอ
มีความเห็นหนึ่งบอกว่า แม้แต่กรณีที่เอาสิ่งที่นักพัฒนาคนอื่นเขียนมาใช้ก็ยังต้องรีวิวอยู่ดี ดังนั้นจึงไม่ต่างจากกรณีของ LLM แต่ผมไม่คิดแบบนั้นครับ ในกรณีของมนุษย์ มีกลไกอย่างชื่อเสียง ความน่าเชื่อถือ รางวัล และบทลงโทษทำงานอยู่ ถ้าทำงานแบบ LLM ในตอนนี้ คงถูกไล่ออกทันทีแน่ ๆ
ผมคิดมาตลอดว่า "AI ไม่ได้มารับผิดชอบแทนเรา"
ผมมองว่าวันที่การใช้ AI เขียนโค้ดจะถูกห้ามคงอยู่อีกไม่ไกลแล้วครับ ฟังดูอาจไม่น่าเป็นไปได้ แต่ผมคิดว่ามันจะกลายเป็นความจริงครับ