1 คะแนน โดย GN⁺ 3 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • การประเมิน เอเจนต์เขียนโค้ด แบบอัตโนมัติโดยมากมักดูอัตราความสำเร็จของงานบน codebase ที่กำหนดไว้ตายตัว แต่งานวิจัยนี้แยกวัดว่า ความสะอาด ของตัวโค้ดเปลี่ยนต้นทุนการสำรวจและการแก้ไขหรือไม่
  • สร้าง repository แบบคู่ขั้นต่ำ 6 คู่ที่มีสถาปัตยกรรม dependency และพฤติกรรมภายนอกเหมือนกัน แต่ต่างกันเฉพาะการละเมิดกฎ SonarQube และ cognitive complexity พร้อมงานอิง hidden tests 33 งาน
  • รันแต่ละงานด้วย Claude Code และ Claude Sonnet 4.6 ฝั่งละ 10 ครั้งในแต่ละคู่ repository รวมเป็น การทดลอง 660 ครั้ง โดยเอเจนต์ไม่รู้ว่ากำลังทำงานกับโค้ดฝั่งใด
  • ความสะอาดของโค้ดไม่ได้เปลี่ยน อัตราผ่าน แต่ในโค้ดที่สะอาดกว่า ตัวชี้วัดเทียบเท่า token ลดลง 7~8% และการกลับมาเปิดไฟล์ซ้ำลดลง 34%
  • ไม่ใช่แค่โมเดลหรือ prompt เท่านั้น แต่ สภาพของ codebase ยังเป็นตัวแปรเชิงปฏิบัติที่กำหนดต้นทุนการคำนวณและประสิทธิภาพการสำรวจของเอเจนต์

คำถามวิจัยและการตั้งปัญหา

  • เอเจนต์เขียนโค้ดแบบอัตโนมัติกำลังแพร่หลายอย่างรวดเร็ว
    • จากการสำรวจโปรเจกต์ GitHub 128,018 โปรเจกต์ในปี 2026 พบสัญญาณกิจกรรมของเอเจนต์ใน 22~29% ของโปรเจกต์ ณ ช่วงเวลาที่ยังไม่ถึง 1 ปีหลังการเปิดตัวเอเจนต์ที่ใช้งานได้จริงตัวแรก
  • ต้นทุนการรันเอเจนต์ก็ไม่น้อย
    • บน SWE-bench Verified งานเดี่ยวใช้โดยเฉลี่ยประมาณ 4 ล้าน token เมื่ออิง frontier LLM
    • ในปริมาณการใช้งานทั้งหมด input token เป็นสัดส่วนส่วนใหญ่
  • การประเมินเดิมมุ่งเน้นว่า แก้งานได้หรือไม่ บน benchmark อย่าง SWE-bench และงานวิจัยล่าสุดเริ่มวัดการใช้ทรัพยากรร่วมกับอัตราผ่าน
  • การเปรียบเทียบทั่วไปคือการตรึง codebase ไว้ แล้วเปลี่ยนเอเจนต์หรือ scaffolding
  • งานวิจัยนี้ทำกลับกัน คือคงเอเจนต์และงานไว้ แล้วเปลี่ยนเฉพาะ ความสะอาดของ codebase เพื่อเปรียบเทียบ

ความสะอาดของโค้ดและการสร้างคู่ขั้นต่ำ

  • ความสะอาดของโค้ดถูกมองเป็นชุดคุณลักษณะที่เชื่อมโยงกับโค้ดที่บำรุงรักษาได้
    • อ่านง่าย
    • cognitive complexity ต่ำ
    • helper แยกเป็นสัดส่วนดี
    • ตั้งชื่อชัดเจน
    • มี dead code, logic ซ้ำ และ accidental coupling น้อย
  • งานวิจัยไม่ได้กำหนดความสะอาดของโค้ดเป็นนิยามเชิงรูปแบบที่เข้มงวด แต่ใช้จำนวนการละเมิดกฎของ static analysis จาก SonarQube เป็นตัวชี้วัดแทนแบบหลวม ๆ
    • เครื่องมือที่ใช้คือ SonarQube Cloud Enterprise Edition
    • ชุดกฎคือ “default quality gate”
  • repository แบบคู่ขั้นต่ำถูกสร้างให้ต่างกันเฉพาะความสะอาดภายใน และให้เงื่อนไขต่อไปนี้ตรงกัน
    • ภาษาและ framework เดียวกัน
    • dependency เดียวกัน
    • test เดียวกันหรือ test coverage เทียบเท่า
    • พฤติกรรมภายนอกเหมือนกัน
  • ความเท่าเทียมของพฤติกรรมหมายถึงเมื่อให้ input เดียวกัน ผลลัพธ์และการเปลี่ยนสถานะที่สังเกตได้จากภายนอกต้องเหมือนกัน
    • การตรวจสอบจริงทำโดยให้ผ่าน test suite เดียวกันด้วย coverage เดียวกัน หรือผ่านคู่ test ที่ปรับชดเชยการเปลี่ยนแปลงที่สังเกตไม่ได้ เช่น refactoring

pipeline สร้างคู่ขั้นต่ำ: Slopify และ Vibeclean

  • คู่ขั้นต่ำถูกสร้างแบบสองทิศทาง
    • Slopify ทำให้ repository ที่สะอาดสกปรกขึ้น
    • Vibeclean จัดระเบียบ repository ที่สกปรก
  • Slopify

    • เปลี่ยน codebase ที่สะอาดให้เป็นเวอร์ชันเหมือนเติบโตมาโดยไม่มี code review หรือ linting
    • เป้าหมายไม่ใช่โค้ดที่จงใจทำให้พัง แต่เป็นเวอร์ชันประวัติศาสตร์ทางเลือกในกรณีที่ไม่มี static analysis
    • แต่ละขั้นตอนดำเนินการโดยเอเจนต์ตัวใหม่
      • Build: build repository และทำให้ test ผ่าน จากนั้นตรึงคำสั่งไว้ใน build instructions.md
      • Explore: สำรวจ repository และเขียน summary.md สำหรับแต่ละ directory ที่เป็นเป้าหมายการจัดระเบียบ
      • Transform: ใส่การละเมิดกฎ SonarQube ใน directory ที่กำหนด และรัน test ใหม่หลังแต่ละ pass เพื่อปฏิเสธการเปลี่ยนแปลงที่ทำให้พัง
    • เพิ่ม cognitive complexity ด้วยการ inline helper, ทำ logic ซ้ำตาม path, เพิ่ม dead code, รวมบาง module เป็นไฟล์เดียว เป็นต้น
  • Vibeclean

    • จัดระเบียบ codebase ที่มีการละเมิดกฎจำนวนมากตามธรรมชาติ โดยคงพฤติกรรมภายนอกไว้
    • รายการงานของเอเจนต์คือรายการ issue ที่ analyzer ตรวจพบ และแต่ละ issue เชื่อมกับช่วงของโค้ด
    • ขอบเขตการแก้ไขจำกัดอยู่ที่ปัญหาที่ analyzer ระบุ และไม่ได้มุ่ง redesign ทั้งระบบ
    • ทำงานสองขั้นตอน
      • Build: ตรวจสอบคำสั่ง build และ test แล้วตรึงไว้ใน build instructions.md
      • Clean: จัดระเบียบการละเมิดกฎ analyzer แบบเชิงกลไกทีละ module และตรวจสอบความเท่าเทียมของพฤติกรรมด้วย test หลังจัดการแต่ละ module
    • ดำเนินการเช่นลบ literal string ซ้ำ, ลบโค้ดที่ถูก comment out, แทนที่ idiom ของ collection แบบ legacy, ลบ branch ที่เป็น dead code
    • เมื่อ analyzer ชี้ไปที่โครงสร้างขนาดใหญ่มากจริง ๆ ก็เปลี่ยน dispatch switch กว่า 200 บรรทัดเป็น helper ที่มีชื่อ หรือแยก persistence helper ออกจาก class ขนาด 2,800 บรรทัด
    • อย่างไรก็ตาม การแยกออกมาอาจไม่ได้กำจัด complexity แต่กระจายไปยัง method จำนวนมากขึ้น และโครงสร้างขนาดใหญ่มากที่สุดบางส่วนยังคงเป็น wontfix

repository benchmark และการออกแบบงาน

  • benchmark สร้างบน Harbor framework v0.4.0
  • ใช้ repository แบบคู่ขั้นต่ำทั้งหมด 6 คู่
    • เน้น Java 3 คู่ และเน้น Python 3 คู่
    • บาง repository มีโค้ดภาษาอื่นเล็กน้อย
    • ประกอบด้วย repository open source สาธารณะ 3 คู่ และ codebase ภายในของ SonarSource ที่ไม่เปิดเผย 3 คู่
    • คู่ที่ไม่เปิดเผยทำหน้าที่เป็น การป้องกันการท่องจำ เผื่อ LLM ที่ประเมินอาจเคยฝึกด้วย repository สาธารณะ
  • ตัวเลขสำคัญของฝั่งสะอาดและฝั่งสกปรกในแต่ละ repository มีดังนี้
    • sonar-sca*: issue 94 / 2,825, issue density 0.73 / 20.66, cognitive complexity density 30.6 / 56.5
    • sonar-caas-poc*: issue 16 / 855, issue density 0.61 / 27.16, cognitive complexity density 179.8 / 218.9
    • sonarcloud-codedatalake*: issue 199 / 1,319, issue density 4.36 / 34.39, cognitive complexity density 34.0 / 216.5
    • commons-bcel: issue 694 / 2,711, issue density 12.60 / 49.46, cognitive complexity density 102.8 / 108.3
    • genie: issue 152 / 1,262, issue density 1.28 / 10.81, cognitive complexity density 22.2 / 23.5
    • ckan: issue 1,006 / 3,632, issue density 7.54 / 27.50, cognitive complexity density 69.3 / 76.5
  • การออกแบบงานปฏิบัติตามกฎสามข้อ
    • ผ่าน hotspot: วางงานให้ผ่านบริเวณโค้ดที่มีความต่างด้าน issue density และ cognitive complexity สูงในทั้งสองฝั่งของคู่
    • คำอธิบายที่สังเกตได้จากภายนอก: ให้เฉพาะ input, output และ scenario ตัวอย่าง ไม่ให้ชื่อไฟล์ ชื่อ function หรือชื่อโครงสร้างภายใน
    • test ผ่าน public surface: รัน hidden tests ผ่าน interface ที่แอปพลิเคชันมอบให้ผู้เรียก เช่น CLI, HTTP route, library/API
  • การสร้างงานแบ่งกันระหว่างเอเจนต์กับมนุษย์
    • เอเจนต์เปรียบเทียบ variant ที่สะอาดกับ variant ที่สกปรกเพื่อทำแผนที่ความต่าง
    • เอเจนต์อีกตัวเขียนโครงร่างงานและความเป็นไปได้ในการทดสอบ
    • มนุษย์เลือก แก้ไข และคัดสรรโครงร่างที่ดูสมเหตุสมผลและน่าสนใจ
    • เอเจนต์ตัวที่สามสร้างคำสั่งจริง, hidden public-surface tests และ reference implementation สำหรับใช้ภายใน
    • reference implementation ต้องผ่าน hidden tests ใน repository ทั้งสองฝั่ง
    • repository ก่อนแก้ไขต้องไม่ผ่าน hidden tests
    • งานที่ยังไม่เข้าเงื่อนไขหลังวนซ้ำสองรอบ จะถูกมนุษย์เขียนใหม่หรือนำออก
  • จำนวนงานสุดท้ายคือ 33 งาน แบ่งเป็นสาม track
    • งาน cognitive hotspot 13 งาน: ผ่านบริเวณ complexity หนาแน่นสูงของ method เดียวหรือ class เดียว
    • งาน multi-module 14 งาน: ต้องแก้ไขข้าม module ตั้งแต่สอง module ขึ้นไป
    • งาน calibration 6 งาน: ให้ทั้งสองฝั่งทำงานเรียบง่ายในบริเวณเดียวกัน เพื่อตรวจสอบว่ามีความเปลี่ยนแปลงที่ไม่เกี่ยวกับความสะอาดหรือไม่

การตั้งค่าการทดลองและตัวชี้วัด

  • การทดลองทั้งหมดดำเนินการด้วย Claude Code โดยใช้ชุดเครื่องมือพื้นฐาน
  • ตัวเลขที่รายงานมาจากการรัน Claude Sonnet 4.6
    • Claude Haiku 4.5 ก็ถูกลองคร่าว ๆ กับชุดงานเดียวกัน แต่ถูกตัดออกจากผลหลักเพราะอัตราผ่านต่ำเกินไปจนอ่านความต่างของ footprint ได้ไม่ชัด
  • เอเจนต์อ่านเฉพาะคำอธิบายงาน
    • ไม่ได้รับ priming เพิ่มเติมเกี่ยวกับความสะอาดของโค้ด
    • ไม่รู้ว่าตัวเองกำลังทำงานกับฝั่งใดของคู่ขั้นต่ำ
  • แต่ละงานรันฝั่งละ 10 ครั้งในแต่ละคู่
    • จำนวนการทดลองรวมคือ 33 × 2 × 10 = 660 ครั้ง
  • แต่ละการรันทำใน sandbox แบบ containerized
    • จำกัด CPU, memory, storage และ wall-clock time
    • เข้าถึง public package registry ได้
    • base image รวม toolchain, build cache และ service ตามแต่ละ repository
    • ภายในคู่ มีเพียง source tree ที่ mount ที่ /app เท่านั้นที่ต่างกัน
  • บันทึกตัวชี้วัด 10 รายการ
    • อัตราผ่าน: สัดส่วนที่ hidden tests ผ่านในสถานะสุดท้าย
    • input token: จำนวน token ที่โมเดลอ่านทุก turn โดยส่วนใหญ่เป็นเนื้อหาไฟล์และการส่งบทสนทนาก่อนหน้าซ้ำ
    • output token: ผลลัพธ์ทั้งหมดที่โมเดลและ sub-agent สร้าง รวม prose, code, ร่องรอย reasoning และ tool call
    • จำนวนอักขระ reasoning: เนื่องจาก Anthropic API ไม่เปิดเผย reasoning token แยกต่างหาก จึงนับจำนวนอักขระข้อความธรรมดาใน reasoning content block
    • จำนวน turn ของบทสนทนา: จำนวนการแลกเปลี่ยน agent-tool ทั้งหมด
    • จำนวน turn ก่อนการแก้ไขครั้งแรก: จำนวน turn ที่ใช้ก่อนการแก้ไฟล์ครั้งแรก
    • จำนวนอักขระก่อนการแก้ไขครั้งแรก: จำนวนอักขระของบทสนทนาในช่วงเดียวกัน
    • จำนวนไฟล์ที่อ่าน: จำนวนไฟล์ไม่ซ้ำที่เปิดดูระหว่างการรัน
    • การกลับมาเปิดไฟล์ซ้ำ: จำนวนครั้งที่กลับไปอ่านไฟล์ที่เคยอ่านและแก้ไขแล้ว
    • จำนวนบรรทัดที่แก้ไข: จำนวนบรรทัด source ที่ patch สุดท้ายเปลี่ยนแปลง
  • การกลับมาเปิดไฟล์ซ้ำปรากฏใน flow เช่น อ่าน → แก้ไข → อาจทำอย่างอื่น → กลับมาอ่านอีกครั้ง
    • งานวิจัยตีความว่าเป็นสัญญาณของ ความไม่แน่ใจ ต่อการแก้ไขก่อนหน้า มากกว่าการสำรวจอย่างกว้าง
  • ตัวชี้วัด footprint ของเอเจนต์อาจแปรผันมากแม้รันงานเดียวกันซ้ำที่ temperature คงที่ จึงใช้การกรอง outlier
    • ภายในแต่ละชุด (งาน, ฝั่ง) การรันที่เบี่ยงจาก median ของการทำซ้ำ 10 ครั้งเกิน 50% จะถูกนำออกก่อนคำนวณค่าเฉลี่ย
    • ในทางปฏิบัติ ถูกนำออก 9.7% ของการรันทั้งหมด
  • ตัวเลขระดับ dataset เป็น micro average จากงาน 33 งาน
    • สำหรับแต่ละตัวชี้วัด รวมค่าเฉลี่ยฝั่งสะอาดและฝั่งสกปรกของแต่ละงาน แล้วคำนวณความต่างเป็นอัตราส่วน
    • อัตราผ่านเป็นข้อยกเว้น โดยรายงานเป็นความต่างแบบจุดเปอร์เซ็นต์สัมบูรณ์ระหว่างฝั่งสะอาดกับฝั่งสกปรก

ผลลัพธ์: ส่งผลต่อต้นทุนการสำรวจมากกว่าอัตราความสำเร็จ

  • ความสะอาดของโค้ดไม่ได้สร้างความเปลี่ยนแปลงอย่างมีนัยสำคัญต่อ อัตราผ่าน ของเอเจนต์
  • ในโค้ดที่สะอาดกว่า ตัวชี้วัดเทียบเท่า token ลดลง 7~8%
  • การกลับมาเปิดไฟล์ซ้ำ ลดลง 34% แสดงให้เห็นว่าโค้ดสะอาดสามารถลดต้นทุนการย้อนกลับไปอ่านซ้ำได้ แม้เป็นงานเดียวกัน
  • ดังนั้นความสะอาดของโค้ดจึงมองได้ว่าเป็นอีกแกนหนึ่งที่กำหนดต้นทุนการรันเอเจนต์ ควบคู่กับการเลือกโมเดล harness และ prompt

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

 
GN⁺ 3 시간 전
ความคิดเห็นจาก Hacker News
  • เป็นคำถามที่น่าสนใจและควรศึกษา แต่ผมสงสัยมากกับ การออกแบบการทดลอง
    ในการทดลอง พวกเขาใช้ Opus 4.6 สังเคราะห์ codebase แบบ “คุณภาพลดลง” หรือ “จัดระเบียบแล้ว” เพื่อใช้เปรียบเทียบกัน
    ที่แย่กว่านั้นคือไม่ได้ควบคุมว่าได้ทำให้เทสต์ของแอปพลิเคชันพังหรือไม่
    “อัตราการผ่านให้คะแนนสถานะสุดท้ายของเอเจนต์ตามเกณฑ์เทสต์ที่ซ่อนอยู่ซึ่งเราเขียนขึ้นสำหรับแต่ละงาน เราไม่ได้ตรวจสอบว่าเอเจนต์ทำให้เทสต์ที่ไม่เกี่ยวข้องซึ่งมีอยู่แล้วใน repository พังหรือไม่ และแม้ว่าวิธีแก้ของฝั่งสะอาดกับฝั่งรกจะผ่านเทสต์ที่ซ่อนอยู่ทั้งคู่ ก็อาจแตกต่างกันในเทสต์ที่ไม่ได้ถูกนำมาคิดคะแนน”
    ถ้าไม่ควบคุมคุณภาพของผลลัพธ์สุดท้าย ข้อสรุปเกี่ยวกับ ปริมาณโทเคนที่ใช้ ก็แทบไม่มีความหมาย

    • ถ้าเปรียบเทียบโปรเจกต์ที่รกกับโปรเจกต์ที่มีโครงสร้างดีด้วยจำนวนเทสต์ที่ล้มเหลว อัตราความสำเร็จอาจเอนเอียงไปทาง codebase ที่รก ซึ่งตั้งแต่แรกก็น่าจะมี test coverage และความทนทานต่ำกว่า
      ถ้าจะเปรียบเทียบอย่างเป็นธรรม ควรเขียนชุดเทสต์เดียวที่ทำงานได้กับทั้งสองโปรเจกต์ในแต่ละคู่
      ไม่ได้หมายความว่างานวิจัยนี้ดี แต่ผมเข้าใจการตัดสินใจแบบนั้นได้ เพราะการผ่านเทสต์ไม่จำเป็นต้องสัมพันธ์กับประสิทธิผลของเอเจนต์เสมอไป
    • ต่อให้ข้อสรุปถูกต้อง อย่างมากก็เป็นแค่กรณีที่ดีที่สุดสำหรับ โค้ดคุณภาพลดลง
      มันแค่แสดงสถานการณ์ที่ในเชิงฟังก์ชันดูเหมือนจะโอเค แต่ต้องจ่ายค่าโทเคนมากขึ้นเพื่อทำงานให้เสร็จ
    • ถ้าไม่ควบคุมการทำให้เทสต์ของแอปพลิเคชันพัง ก็แทบเป็น งานวิจัยที่ไร้ค่า
      ความเหนื่อยล้าจาก AI น่าเบื่อมานานแล้ว และตอนนี้มันก็เจ็บปวดเสียมากกว่า
  • จากประสบการณ์ของผม ความต่างของประสิทธิภาพเอเจนต์ระหว่าง codebase ที่เต็มไปด้วย dead code, โค้ดซ้ำ, เส้นทางสำรองที่ไปไม่ถึง, abstraction ที่รั่ว, design pattern ที่ยังไม่สุกงอม กับ codebase ที่ data flow ชัดเจน มี encapsulation และโครงสร้างสะอาดนั้นค่อนข้างมาก
    ในโค้ดแย่ ๆ โมเดลแนวหน้าทุกตัวต้องผ่านหลายรอบของ code review, การตรวจคุณภาพ และการแก้ไข ส่วนในโค้ดดี ๆ ผมเห็นว่ามักทำถูกได้ตั้งแต่ครั้งที่ 1–2

    • ปัญหาที่กล่าวข้างต้นอย่างการลบ dead code, โค้ดซ้ำ, โค้ดที่ไปไม่ถึง ใน ecosystem ของภาษาส่วนใหญ่ถูกแก้ด้วย deterministic linter มานานแล้ว
      เราสามารถให้ LLM รันสคริปต์เพื่อตรวจรายการเหล่านี้ และบังคับใช้สคริปต์เดียวกันเป็น pre-commit hook ได้
      การใส่การตั้งค่าแบบนี้อย่างเข้มงวดในทุก codebase ที่ผมทำงานด้วยเป็นสิ่งที่ให้ผลมากที่สุดในการเขียนโค้ดแบบเอเจนต์
      ผมเขียนรายละเอียดเพิ่มเติมเกี่ยวกับ linter หลายตัวที่ผมใช้ไว้ที่นี่: https://www.balajeerc.info/Use-Deterministic-Guardrails-for-...
    • ผมทำงานกับเครื่องมือพวกนี้มาค่อนข้างนาน และทุกครั้งดูเหมือนว่าประสิทธิภาพจะดีขึ้นเมื่อปฏิบัติกับมัน เหมือนปฏิบัติกับคน
      ผมคิดว่าเอเจนต์ก็ย่อมทำงานกับ codebase ที่สะอาดได้ดีกว่า codebase ขนาดใหญ่ที่เละเทะอยู่แล้ว
      เหมือนกับที่มันทำงานได้ดีขึ้นเมื่อมีสเปกที่เขียนดีและเข้าถึงเอกสารได้
    • ผมก็รู้สึกคล้ายกันตอนทำงานกับ codebase ที่รก
      ถึงจุดหนึ่ง pattern แย่ ๆ เหล่านั้นก็เริ่มติดมาที่ตัวผมด้วย
    • ผมอ่านแล้วก็เห็นด้วย แต่พอลองคิดว่าทำไมถึงรู้สึกเหมือนเป็นคอมเมนต์ที่ไม่ดี ก็เพราะ คำกล่าวเชิงประสบการณ์ส่วนตัว แบบนี้อยู่คนละฝั่งกับการอภิปรายเชิงวิทยาศาสตร์
      ที่นี่มี paper ที่พยายามตอบคำถามนี้อยู่ และคำให้การเชิงประสบการณ์ส่วนตัวเพียงทำให้ผู้อ่านมีอคติ ไม่ได้เพิ่มคุณค่าในการสรุปประเด็นอย่างเป็นกลาง
      การอภิปรายที่มีประโยชน์ที่สุดน่าจะเป็นการที่ทุกคนอ่าน paper แล้ววิจารณ์ระเบียบวิธีหรือผลลัพธ์
    • อันนี้ก็ใกล้เคียงกับความรู้สึกเหมือนกัน แต่ผมเป็นคนกังวลมากเกินไปจนทำ pass สำหรับ refactoring และจัดระเบียบโค้ดบ่อย ๆ และไม่เคยข้าม จึงพูดให้แน่ชัดได้ยากว่ามีความต่างด้านประสิทธิภาพจริงหรือไม่
      แต่คนที่บ่นว่า LLM ไม่ค่อยดี โดยทั่วไปดูเหมือนเป็นประเภทที่มี codebase รก
  • เคล็ดลับที่ผมเห็นว่าใช้ได้ดีคือ ถ้าเป็น Python ให้สั่ง refactor ประมาณนี้
    “Refactor โค้ด Python ให้เป็น Pythonic มากขึ้น เช่น ลด class และ singleton โดยเฉพาะถ้ามีการเพิ่มความเร็ว โค้ด Python ต้องเป็นไปตามมาตรฐานการจัดโครงสร้างโค้ดที่คาดหวังจากโค้ดของแพ็กเกจ Python โอเพนซอร์สยอดนิยม โดยไม่มี performance regression ใน benchmark”
    สำหรับโค้ด Rust ผมลองใช้รูปแบบนี้
    “codebase Rust ใน /src บวมจนมีหลายไฟล์ที่ยาวเกิน 1,000 บรรทัด ให้ refactor codebase Rust ให้สอดคล้องกับมาตรฐานการจัดโครงสร้างโค้ดที่คาดหวังจากโค้ด Rust โอเพนซอร์สยอดนิยม โดยไม่มี performance regression ใน benchmark”
    prompt แบบนี้ดูเหมือนจะทำให้ประสิทธิภาพเอเจนต์ดีขึ้น เพราะ a) จัดโครงสร้างโค้ดใหม่อย่างมีตรรกะ และ b) ชื่อไฟล์ให้ hint เชิงความหมายเกี่ยวกับตำแหน่งของโค้ดที่เกี่ยวข้อง
    ในไฟล์บวม ๆ 5,000 บรรทัด เอเจนต์ไม่มีประสิทธิภาพเพราะต้องอ่านหลายก้อนเพื่อหาโค้ดที่เกี่ยวข้อง
    benchmark performance ก็มักดีขึ้นหลัง refactor ด้วย โดยเฉพาะใน Rust ที่คอมไพล์ได้ ซึ่งอาจเป็นเรื่องบังเอิญ แต่ก็ไม่ใช่เรื่องให้บ่น

    • ใช่ แค่ขอให้เครื่องมือเขียนโค้ดแบบเอเจนต์จัดระเบียบ codebase, ทำ targeted refactoring, ใช้ หลักการ SOLID และ good practices ก็ได้การปรับปรุงง่าย ๆ มากมาย
      โดยพื้นฐานแล้ว เครื่องมือเขียนโค้ดแบบเอเจนต์มักลังเลที่จะลบโค้ด ต่อให้สั่งให้ลบก็เถอะ และจะพยายามทุกวิถีทางที่จะเก็บโค้ดเก่าไว้ หรือเพิ่มความซับซ้อนเพื่อให้โค้ดนั้นยังถูกเรียกได้ต่อไป
      ถ้าคุณแค่กำลังทำ prototype มันน่ารำคาญมาก เพราะสุดท้าย dead code จะสะสมเยอะ และทำให้สับสนในภายหลังเมื่อพยายามเพิ่มฟีเจอร์
      พอรู้เรื่องนี้แล้ว ก็แค่ขอให้มันกำจัด legacy ออกไป
      การรักษา codebase ให้สะอาดจะกระตุ้นให้ AI ทำสิ่งที่ถูกต้อง ถ้ามีเทสต์เยอะ มันจะเพิ่มเทสต์มากขึ้นเมื่อสร้างฟีเจอร์ใหม่ และถ้ามีเอกสาร มันจะอัปเดตให้เองโดยไม่ต้องบอก
      เมื่อ code harness ดีขึ้น สิ่งเหล่านี้จะค่อย ๆ ถูกฝังมาในตัว และคนที่มีประสบการณ์ prompt น้อยก็จะได้ผลลัพธ์ที่ดีได้ง่ายขึ้น
    • การขอให้ใช้ หลักการ YAGNI ก็ดูเหมือนใช้ได้ดีในการลดขนาด codebase
      โดยปกติผมจะให้มันรีวิวก่อนแล้วทำรายการประเด็นรีวิว จากนั้นค่อยดูแต่ละรายการร่วมกัน แล้วผมตัดสินใจว่าใช่/ไม่ใช่ หรือเสนอการแก้ไขเพิ่มเติม
    • ผมเข้าใจว่าการทำแบบค่อยเป็นค่อยไปนั้นสมเหตุสมผล แต่การทำแบบนี้กับ codebase ที่ใช้งานจริงทั้งก้อนในครั้งเดียวดู เสี่ยงสุด ๆ
      โดยเฉพาะถ้าไม่มี end-to-end tests ที่รอบคอบสำหรับทั้งระบบ
    • แค่พูดว่า “refactor codebase” ก็ใช้ได้ค่อนข้างดี
      ยังไงกฎ style ของโค้ดก็ใส่ไว้ใน CLAUDE.md แล้ว
    • คำที่คุณกำลังมองหาคือ idiomatic
  • แนวทางที่เรียกว่า “ไปป์ไลน์เอเจนต์สำหรับจัดระเบียบรีโพซิทอรีที่เละเทะ” ดูแย่มาก และแค่นี้ก็น่าจะเพียงพอที่จะปฏิเสธงานวิจัยทั้งหมดแล้ว
    ดูเหมือนว่าในงานนี้ ครึ่งหนึ่งของ คู่ขั้นต่ำ ถูกสร้างขึ้นด้วยวิธีแบบนั้น
    ผมจะไม่เชื่อข้อสรุปใด ๆ เลยที่ต้องตั้งสมมติฐานว่ารีโพซิทอรีที่ AI “จัดระเบียบ” แล้วเป็นตัวแทนของโค้ดเบสที่ดีจริง ๆ

    • ผมเป็นผู้เขียนคนแรก ขอชี้แจงอย่างหนึ่ง
      “ความสะอาด” ในที่นี้ไม่ใช่การขอให้เอเจนต์แค่เขียนโค้ดให้ดีขึ้น
      เราให้รายการ การละเมิดกฎของ static analyzer 50~100 รายการพร้อมจำนวนบรรทัดของโค้ด แล้วขอให้กำจัดสิ่งเหล่านี้ออก
      จากนั้นตรวจสอบว่าการละเมิดกฎถูกแก้ไขแล้วหรือไม่
      การใช้ LLM เขียนโค้ดใหม่เพื่อกำจัดการละเมิดเหล่านี้เป็นแนวปฏิบัติที่ค่อนข้างเป็นที่ยอมรับ
      แนวทางแบบ one-shot ที่ใช้ LLM ของ Sonar [1] เปิดใช้งานมานานกว่า 1 ปีแล้ว และแนวทางแบบเอเจนต์ล่าสุด [2] ก็ทำงานแบบเดียวกันได้ค่อนข้างดี
      [1] https://www.sonarsource.com/solutions/ai/ai-codefix/
      [2] https://www.sonarsource.com/products/sonarqube/remediation-a...
    • ถ้าเป็นรีโพซิทอรีที่สะอาดแต่ถูก AI ทำให้เละ คุณจะเชื่อไหม?
  • ผมคิดว่ามันย่อมส่งผลอย่างแน่นอน
    ไม่มีโมเดลใดใส่โค้ดเบสจริงทั้งหมดไว้ในบริบทได้ และต้องไล่อ่านโค้ดเหมือนมนุษย์
    คือใช้วิธีค้นหาและอ่านไฟล์
    ถ้าไฟล์อยู่ในตำแหน่งที่คาดไว้ และถูกตั้งชื่อแบบที่โมเดลหรือมนุษย์น่าจะค้นหาเป็นอย่างแรก ก็จะเจอตั้งแต่ครั้งแรก แต่ถ้าไม่ใช่ ก็ต้องค้นหาลึกขึ้นและลองหลายครั้ง

    • LLM ไม่จำเป็นต้องถือ โค้ดเบสทั้งหมด ไว้ในบริบท
      แค่ดูทุกพาธ ข้ามส่วนที่จัดการไปแล้ว แล้วไปพาธถัดไปก็พอ
      ค่อนข้างคล้ายกับวิธีที่นักพัฒนาทำ
  • ในงานที่คล้ายกันซึ่งกำลังทำอยู่ที่ NJIT เราก็เห็นผลลัพธ์คล้ายกัน เราเรียกสิ่งนี้ว่า การแพร่กระจายคุณภาพเชิงบริบท
    ส่วนที่น่าสนใจตรงนี้คือสถานการณ์จริงที่พบได้บ่อยในอุตสาหกรรม เช่น โค้ดเบสที่มีคุณภาพปะปนกัน หรือโค้ดเบสที่มีทั้งแพตเทิร์นโค้ด legacy และแพตเทิร์น “ที่ดี” แบบใหม่กว่า จนทำให้เอเจนต์สับสนเรื่องธรรมเนียมปฏิบัติ
    การออกแบบแบบคู่ขั้นต่ำจริง ๆ แล้วเป็นหนึ่งในจุดแข็ง เพราะพยายามแยก ความสะอาด ออกจากปัจจัยอื่นอย่างโครงสร้าง dependency และการทดสอบ แทนที่จะเปรียบเทียบข้ามรีโพซิทอรี
    อย่างไรก็ตาม การใช้โค้ดที่ LLM สร้างให้ “เละ” นั้นค่อนข้างน่ากังขา เพราะไม่ใช่วิธีเชิงกลไกหรือมีมนุษย์ชี้นำ
    คำวิจารณ์ที่ใหญ่ที่สุดคือการเลือกไม่ตรวจสอบชุดทดสอบทั้งหมดอย่างที่หลายคนชี้ไว้ถูกต้องแล้ว ข้ออ้างเรื่อง “ความเท่าเทียมเชิงพฤติกรรม” จะใช้ได้เท่าที่การทดสอบและ coverage รองรับเท่านั้น
    เหตุผลที่สมมติฐานนี้น่าเชื่อมีสองข้อ 1) LLM เลียนแบบสิ่งที่เห็นในโค้ดเบส ดังนั้น garbage in, garbage out จึงสมเหตุสมผล 2) มันสอดคล้องกับสิ่งที่วิศวกรจำนวนมากรู้สึกโดยสัญชาตญาณจากการใช้โมเดลเหล่านี้ในช่วง 1~2 ปีที่ผ่านมา
    งาน greenfield แทบจะง่ายกว่าการเข้าไปร่วมในโค้ดเบสที่วุ่นอยู่เสมอ และความยุ่งเหยิงเกิดจากการผสานรวมที่ซับซ้อนกับการดูแลระบบเพื่อวัตถุประสงค์ legacy

  • ต่อให้เอเจนต์เรียนรู้วิธีฝ่าดง stub และ โค้ด WET ที่ตัวเองทิ้งไว้ได้ เราอยากได้โค้ดเบสที่มนุษย์ตามไม่ทันจริง ๆ หรือว่ากำลังเกิดอะไรขึ้น?

    • ต่อให้เอเจนต์จัดการทุกอย่างได้ ภาษาอังกฤษก็อธิบายสิ่งที่โค้ดทำได้ไม่แม่นยำ
      ดังนั้นโดยส่วนตัวแล้ว อย่างน้อยผมก็อยากให้โค้ด เล่าเป็นโค้ด ว่ามันทำอะไร
    • ผมกลับเคยเห็นกรณีที่ผลัก DRY มากเกินไป
      แม้จะมี logic ในฟังก์ชันเล็ก ๆ สองตัวที่ดึงออกมาเป็น shared helper ได้ แต่บางครั้งโปรแกรมเมอร์มนุษย์จะไม่ทำ เพราะรู้ว่า abstraction นั้นจะรก และถ้าต้องเปลี่ยนหนึ่งในสองตัวเพียงเล็กน้อยก็อาจพังได้
  • การได้เห็นสิ่งนี้ถูกวัดเป็นตัวเลขน่าสนใจดี
    โครงสร้างที่สะอาด ดูเหมือนจะลดภาระทางความคิดของทั้งมนุษย์และเอเจนต์ และจึงอธิบายได้ว่าการตั้งชื่อกับการแยกเป็นโมดูลสำคัญกว่าที่คิด

    • ผมคิดว่าคุณภาพโค้ดสุดท้ายแล้วควรถูกนิยามจากความง่ายในการ แก้ไขโค้ดได้อย่างถูกต้อง
      มันวัดเชิงปริมาณได้ยาก แต่ตัวชี้วัดคุณภาพโค้ดทั้งหมดก็พยายามจับสิ่งนี้ในท้ายที่สุด
      เมื่อมองจากเกณฑ์นั้น ถ้าตัวชี้วัดคุณภาพโค้ดที่ใช้สมเหตุสมผล ก็เป็นข้อสรุปที่ไม่น่าประหลาดใจนัก
      ถ้าตัวชี้วัดคุณภาพดีในบริบทของ coding agent ผลลัพธ์ที่ควรคาดหวังก็คือแบบนี้
  • โทเค็นจำนวนมากถูกใช้ไปกับการสำรวจโค้ด กระบวนการคือการค้นหาโค้ดหรือไล่ตามจุดที่ถูกเรียก เพื่อสร้างบริบทให้เพียงพอสำหรับทำงาน
    ถ้าให้เอเจนต์เข้าถึง LSP ได้ในรูปแบบใดรูปแบบหนึ่ง และถ้าเป็น monorepo ก็ให้คำแนะนำแบบลำดับชั้นผ่านไฟล์อย่าง AGENTS.md จะลดการใช้โทเค็นในการสำรวจได้มาก
    แต่โค้ดเบสที่กระจัดกระจายสุดท้ายก็ยังต้องมีการสำรวจในรูปแบบใดรูปแบบหนึ่งเพื่อแก้แต่ละงาน
    และการสำรวจนี้ไม่ใช่แค่การใช้โทเค็นเท่านั้น ในแต่ละขั้นจะมีความหน่วงแบบไป-กลับซ้ำ ๆ ตั้งแต่เวลารอของ LLM, prefill, decoding, เอาต์พุตไปสู่การ parsing ของเอเจนต์, การเรียก tool, การตอบกลับของ tool แล้ววนกลับไปที่ LLM
    บางส่วนทำขนานกันได้ แต่ในทางปฏิบัติส่วนใหญ่เป็นแบบลำดับ ทำให้งานช้าลงมาก
    หากต้องการใช้เอเจนต์อย่างมีประสิทธิภาพ locality และโครงสร้าง คือหัวใจสำคัญ context window มีขีดจำกัดเสมอ และ attention ภายในนั้นก็ไม่ได้สม่ำเสมอ

  • จากประสบการณ์ของผม ทุกสิ่งที่ส่งผลต่อวิศวกรก็ส่งผลต่อเอเจนต์ด้วย
    ไม่ว่าจะเป็น abstraction ที่ดี เมธอดที่มีขนาดเหมาะสม ชื่อที่ดี โครงสร้างภายในบริการและระหว่างบริการที่มีหลักการ รวมถึง unit test
    สิ่งเหล่านี้ในอดีตเป็นงานของวิศวกร และมีไว้เพื่อทำให้ผู้อื่นมีส่วนร่วมกับโค้ดได้ง่ายขึ้น
    ตอนนี้มันไม่ได้ช่วยแค่ผู้อื่น แต่ยังช่วยให้ เอเจนต์อื่น ๆ มีส่วนร่วมกับโค้ดได้ง่ายขึ้นด้วย