ข้าม​ไป​ยัง​เนื้อหา

เรา​จะ​ผลักดัน AI ให้​ทำงาน​อัตโนมัติ​ใน​การ generate code ได้​ไกล​แค่​ไหน?

เกี่ยว​กับ​บท​แปล​นี้

บทความ​นี้​เป็น บท​แปล​ภาษา​ไทย​อย่าง​ไม่​เป็น​ทางการ ของ “How far can we push AI autonomy in code generation?” โดย Birgitta Böckeler (Distinguished Engineer, Thoughtworks) เผยแพร่​ครั้ง​แรก​บน martinfowler.com เมื่อ 5 สิงหาคม 2025

แปล​และ​เรียบเรียง​เพื่อ​การ​ศึกษา — ไดอะแกรม​เชิง​แนวคิด​วาด​ใหม่​เป็น​ภาษา​ไทย (label ใน​ไดอะแกรม​คง​เป็น​ภาษา​อังกฤษ) ส่วน​ศัพท์​เทคนิค​คง​ไว้​เป็น​ภาษา​อังกฤษ​ตาม​ต้นฉบับ​และ​มี​คำ​อธิบาย​ไทย​กำกับ​เมื่อ​พบ​ครั้ง​แรก ลิขสิทธิ์​ของ​เนื้อหา​ต้นฉบับ​เป็น​ของ​ผู้​เขียน

link ไป​ยัง​หน้า DevIQ ที่​แทรก​ใน​เนื้อหา (เช่น YAGNI, Feature Creep, Goodhart’s Law) เป็นการ​เชื่อม​โยง​แนวคิด​เพิ่มเติม​โดย​ทีม​แปล​เพื่อ​การ​ศึกษา ไม่ใช่​การ​อ้างอิง​ใน​ต้นฉบับ

คำถาม​ที่​ผู้​เขียน​อยาก​หา​คำ​ตอบ​คือ: ตอน​นี้ LLM สามารถ generate, ทดสอบ และ deploy application ซอฟต์แวร์​ที่​สมบูรณ์ ตั้งแต่​ต้น​จน​จบ จาก​คำ​อธิบาย​ความ​ต้องการ​ที่​เป็น​ภาษา​คน (natural language) โดยไม่มี​มนุษย์​เข้าไป​แทรกแซงเลย ได้​ไกล​แค่​ไหน?

เพื่อ​สำรวจ​ว่า​เทคโนโลยี​ใน​วัน​นี้​ทำได้​แค่​ไหน — และ​ต้อง​มี​ความ​ก้าวหน้า​อะไร​อีก​จึง​จะ​ไป​ถึง​จุด​ที่​ทำงาน​ได้​อัตโนมัติ​เต็ม​ตัว (full autonomy) — ผู้​เขียน​จึง​ลงมือ​ทำการ​ทดลอง​ชุด​หนึ่ง​ขึ้น​มา

ขอบเขต​ของ​งาน​นี้​จงใจ​ให้​แคบ​และ​ควบคุม​ได้ ผู้​เขียน​เลือก​สร้าง app Spring Boot ที่​เป็น REST API แบบ CRUD (Create, Read, Update, Delete — สร้าง/อ่าน/แก้ไข/ลบ) เรียบ ๆ ตัว​หนึ่ง ไม่ใช่​ระบบ​ที่​ซับซ้อน

และ​ข้อ​สรุป​ทั้งหมด​ใน​บทความ​นี้​มุ่ง​เฉพาะ​กับผลิตภัณฑ์​ดิจิทัล​และ​ซอฟต์แวร์ application เชิง​ธุรกิจ (business application software) แบบ​ที่​ใช้​กัน​ใน​งาน​ค้า​ปลีก ระบบ​ประกาศ​รายการ​สินค้า และ domain ทำนอง​นั้น — ไม่ใช่domain เฉพาะ​ทาง​ที่​ความ​เสี่ยง​สูง​มาก​อย่าง​การ​บิน​หรือ​การเงิน

ใน​การ​ทดลอง ผู้​เขียน​ใช้ model ตระกูล Claude Sonnet เป็น​หลัก (รุ่น 3.7 และ 4) เพราะ​ใน​ช่วง​นั้น​เป็น model ที่​มี​ความ​สามารถ​ด้าน​การ​เขียน code สูง​ที่สุด​เท่า​ที่​มี​ให้​ใช้ และ​ช่วง​ใกล้​เผยแพร่​ก็​มี​การ​ทดสอบ​ซ้ำ​บาง​ส่วน​ด้วย Claude Code และ Cursor เพิ่มเติม

เพื่อ​รีด​ประสิทธิภาพ​ให้ workflow เข้า​ใกล้​การ​ทำงาน​อัตโนมัติ​มาก​ที่สุด ผู้​เขียน​ได้​ประกอบ​กลยุทธ์​ต่าง ๆ เข้า​ด้วย​กัน​แปด​ข้อ ดังนี้

ผู้​เขียน​เลือก Spring Boot สำหรับ backend ที่​เป็น REST API แบบ CRUD ด้วย​เหตุผล​ว่า

  • มี​ตัวอย่าง​เยอะ​ใน​ข้อมูล​ฝึก​ของ model (training data) โอกาส​ที่ LLM จะ​เคย​เห็น code ทำนอง​นี้​จึง​สูง
  • framework จัดการ​ความ​ซับซ้อน​ให้​เยอะ ทำให้ LLM ต้อง generate code เอง​น้อย​ลง
  • มี pattern สถาปัตยกรรม​ที่​ตายตัว คือ​ลำดับ​ชั้น Controller → Service → Repository → Entity
  • มี​ชั้น​การ​ทดสอบ​ที่​ชัดเจน ทั้ง unit test, integration test และ end-to-end (E2E) test
flowchart TB
  subgraph App["Spring Boot Application"]
    direction TB
    C["Controller Layer"]
    S["Service Layer"]
    R["Repository Layer"]
    E["Entity Layer"]
    C --> S
    S --> R
    R --> E
  end
  CT["Controller Tests"] -.-> C
  ST["Service Tests"] -.-> S
  RT["Repository Tests"] -.-> R
  E2E["E2E Test Suite"] -.-> App

ภาพ 1 — สถาปัตยกรรม​ของ app เป้าหมาย ประกอบ​ด้วย​ชั้น persistence, service และ controller แบบ Spring Boot ทั่วไป โดย​แต่ละ​ชั้น​ควร​มี​ชุด test ของ​ตัวเอง และ​มี​ชุด E2E test แยก​ต่างหาก​คลุม​ทั้ง​ระบบ · ดู​ภาพ​ต้นฉบับ ↗

แทนที่​จะ​ให้ LLM session เดียว​ทำ​ทุก​อย่าง ผู้​เขียน​แบ่ง​กระบวนการ generate ออก​เป็นบทบาท​ของ agent หลาย​ตัว​ที่​ทำงาน​ตาม​ลำดับ โดย​แต่ละ​บทบาท​อยู่​ใน session LLM ของ​ตัวเอง ได้แก่

Requirements analyst (นัก​วิเคราะห์​ความ​ต้องการ) → Bootstrapper (ตัวตั้ง​โครง project) → Backend designer (ผู้​ออกแบบ backend) → ตัว generate ชั้น persistence → ตัว generate ชั้น service → ตัว generate ชั้น controller → E2E tester (ตัว​ทดสอบ​แบบ end-to-end) → Code reviewer (ผู้​รีวิว code)

flowchart TB
  A1["Requirements Analyst"] --> A2["Bootstrapper"]
  A2 --> A3["Backend Designer"]
  A3 --> A4["Persistence Generator"]
  A4 --> A5["Service Generator"]
  A5 --> A6["Controller Generator"]
  A6 --> A7["E2E Tester"]
  A7 --> A8["Code Reviewer"]

ภาพ 2 — agent หลาย​ตัว​ใน​กระบวนการ generate โดย​แต่ละ​ตัว​รับผิดชอบ​บทบาท​เฉพาะ​และ​ส่ง​งาน​ต่อ​กัน​ตาม​ลำดับ · ดู​ภาพ​ต้นฉบับ ↗

เหตุผล​ที่​ทำ​เช่น​นี้: session LLM ที่​ยาว​เกิน​ไป​จะ​มี​คุณภาพ​ลด​ลง​เรื่อย ๆ (context ยาว​ขึ้น​ก็​ยิ่ง​หลุด) การ​มอบหมาย​บทบาท​เฉพาะ​ให้​แต่ละ agent จึง​ช่วย​ให้​ใช้​เทคนิค​การ​เขียน prompt ที่​รู้​กัน​ดี​อยู่​แล้ว​ได้​เต็ม​ที่

อนึ่ง ตอน​ทดสอบ​ซ้ำ​ด้วย​เครื่องมือ​อื่น ผลออก​มา​ปน​กัน: Claude Code ทำได้​ดี ส่วน Cursor ไม่ generate test ของ​ชั้น service และ controller เลย และ​แทบ​จะ​ละทิ้ง​งาน E2E ไป​เสีย​เฉย ๆ

กล่อง​เสริม — Subtasking กับ TODO list ต่าง​กัน​อย่างไร

ควร​แยก​ให้​ชัด​ระหว่าง “โหมด​วางแผน” สอง​แบบ แบบ​หนึ่ง​คือ TODO list ที่ model ไล่​ทำ​เป็น​รายการ​ภายในsession เดียว (context window เดียว) กับ​อีก​แบบ​ที่​ผู้​เขียน​ใช้ คือ​การ​แตก​งาน​ออก​เป็น subtask ที่​แต่ละ​งาน​มี context window แยก​กัน​ของ​ตัวเอง

ผู้​เขียน​ใช้ Kilo Code (ซึ่ง​เป็น fork ของ Roo Code) เป็น harness สำหรับ orchestration และ​ตั้งประตู​อนุมัติ​ของ​มนุษย์ (human approval gate) ไว้​ก่อน​ที่ agent จะ​รัน​คำ​สั่ง terminal ใด ๆ

flowchart TB
  O["Orchestrator Session"]
  O --> S1["Subtask Session - Persistence"]
  O --> S2["Subtask Session - Service"]
  O --> S3["Subtask Session - Controller"]
  S1 --> W1["Own Context Window"]
  S2 --> W2["Own Context Window"]
  S3 --> W3["Own Context Window"]
  O --> G["Human Approval Gate for Terminal Commands"]

ภาพ 3 — การ​ตั้ง​ค่า​แบบ subtask ใน Kilo: session orchestrator หนึ่ง​ตัว​มอบหมาย​งาน​ต่อ​ให้ session subtask หลาย​ตัว โดย​แต่ละ subtask มี context window ของ​ตัวเอง · ดู​ภาพ​ต้นฉบับ ↗

3. เจาะจง stack มากกว่า​ใช้​คำ​สั่ง​กว้าง ๆ (Stack-specific over general purpose)

หัวข้อ​ที่​มีชื่อ​ว่า “3. เจาะจง stack มากกว่า​ใช้​คำ​สั่ง​กว้าง ๆ (Stack-specific over general purpose)”

แทนที่​จะ​สั่ง​กว้าง ๆ ว่า “เขียน app Spring Boot ให้​หน่อย” ผู้​เขียน​ให้​คำ​แนะนำ​ที่​เจาะจง​กับ Spring โดย​ละเอียด เพราะ prompt กว้าง ๆ ไม่​ค่อย​ได้ code คุณภาพ​ระดับ production ที่​เข้า​กับ​มาตรฐาน​ของ​องค์กร ส่วน​คำ​สั่ง​ที่​เจาะจง​จะ​ช่วย​ให้​ได้ code ที่สม่ำเสมอ (consistent) กัน​ทั้ง codebase ระดับ​องค์กร

งาน​นี้​เชื่อม​โยง​กับ​การ​ตกลง coding standard ร่วม​กัน​ทั้ง codebase ซึ่ง​เป็น​ขั้น​แรก​ของ Collective Code Ownership — มาตรฐาน​ที่​ชัด​คือ​สิ่ง​ที่​ทำให้​ผลลัพธ์​ทำซ้ำ​ได้

ขั้นตอน​ตั้ง​โครง project (bootstrapping) ผู้​เขียน​ใช้ CLI อย่าง​เป็น​ทางการ​ของ Spring Boot ทำ แทนที่​จะ​ให้ AI generate เอง

หลักการ​คือต้อง​รู้จัก​จังหวะ​ที่​เครื่องมือ/script ที่​มี​อยู่​แล้ว​แบบ deterministic ทำได้​ดี​กว่า​ปล่อย​ให้ AI generate เอง แล้ว​ผสม​ส่วน​ที่​กำหนด​ผล​ได้​แน่นอน (deterministic) เข้า​กับ​ส่วน​ที่​ให้ AI สร้าง อย่าง​มี​กลยุทธ์

ถ้า​ไม่​ให้​ตัวอย่าง LLM จะ​เผลอ​ใช้ library ที่​ตก​ยุค​ไป​แล้ว เช่น​ใช้ javax.persistence แทนที่​จะ​เป็น jakarta.persistence ที่​ถูกต้อง​ใน​ปัจจุบัน

กลยุทธ์​นี้​ผู้​เขียน​ระบุ​ว่า​เป็น “กลยุทธ์​ที่​ได้​ผล​ที่สุด​ใน​การ​ทำให้ AI generate code แบบ​ที่​เรา​ต้องการ” เพราะ​ตัวอย่าง code

  • ช่วย​สื่อสาร coding idioms (สำนวน​การ​เขียน code) ของ​องค์กร
  • ช่วย​ล็อก​ให้​ใช้ library/version ตรง​กัน
  • ทำให้ AI รับ framework หรือ version ใหม่​ได้​ทันที​โดย​ไม่​ต้อง​รอ​ให้​มัน​ไป​โผล่​เยอะ ๆ ใน training data ก่อน

แต่​การ​ไป​นั่ง​ดูแล​ตัวอย่าง code ที่​ฝัง​อยู่​ใน prompt นั้น​น่า​เบื่อ​และ​ผิดพลาด​ง่าย

ผู้​เขียน​จึง​สร้าง reference application (app อ้างอิง) ขึ้น​มา​หนึ่ง​ตัว แล้ว​ให้ MCP server (Model Context Protocol — protocol มาตรฐาน​สำหรับ​ป้อน context/เครื่องมือ​ให้ LLM) คอย​ส่งตัวอย่าง code จาก app อ้างอิง​นั้น​ให้ agent ข้อดี​คือ

  • ตัวอย่าง codecompile ผ่าน​แน่นอน
  • ตัวอย่าง​ทุก​ชิ้นสอดคล้อง​กัน
  • ประสบการณ์​ของ​นัก​พัฒนา​ระหว่าง​การ​ปรับ​จูน workflow ก็​ดี​ขึ้น
flowchart LR
  Ref["Reference Application"] --> MCP["MCP Server"]
  MCP --> Agent["Coding Agent"]
  Agent --> Target["Target Codebase"]

ภาพ 4 — reference application ทำ​หน้าที่​เป็น​หมุด​ยึด ป้อน​ตัวอย่าง code ผ่าน MCP server เข้า​สู่ agent แล้ว agent จึง​นำ​ไป​ใช้​กับ codebase เป้าหมาย · ดู​ภาพ​ต้นฉบับ ↗

ผู้​เขียน​ตั้ง agent รีวิว​เฉพาะ​ขึ้น​มา​ตัว​หนึ่ง ให้​ทำ​หน้าที่​เทียบ code ที่ generate ออก​มา​กับ​ความ​ต้องการ/คำ​สั่ง​เดิม

สิ่ง​ที่​พบ​คือ: LLM มัก​พลาด​คำ​สั่ง​บาง​ข้อ​ใน​การ generate รอบ​แรก แต่​เมื่อ​ถูก​ขอ​ให้​กลับ​มา​รีวิว​งาน​ของ​ตัวเอง กลับ​ประเมิน​ความ​ตรง​ตาม spec ได้​ดี agent รีวิว​จึง​จับ​ข้อ​ผิดพลาด​ที่​ตัวเอง​แก้​ได้​เอง​ไป​ได้​จำนวน​มาก

แนวคิด​นี้​สอดคล้อง​กับ​ทักษะ iterative review (การ​ตรวจทาน​แบบวน​ซ้ำ) ที่ Structured-Prompt-Driven Development ยก​เป็น​หนึ่ง​ใน​สาม​ทักษะ​หลัก — แยก​บทบาท “ผู้​สร้าง” ออก​จาก “ผู้​ตรวจ”

ผู้​เขียน​สั่ง​ให้ AI ระบุ aggregate ของ domain (กลุ่ม​ของ domain object ที่​ถูก​ปฏิบัติ​เป็น​หนึ่ง​หน่วย​และ​ต้อง​คง​ความ​สอดคล้อง​ภายใน​หลัง​จบ business operation — ดู Aggregate) แล้ว​จัด package ตาม​นั้น

โดย​ใน prompt นิยาม aggregate ไว้​อย่าง​ชัดเจน และ​ขอ​ให้ AI ตอบ​ว่า entity ตัว​ไหน​เป็น root, มี entity อะไร​อยู่​ข้าง​ใน​บ้าง พร้อม​เหตุผล​ของ​การ​กำหนด​ขนาด (ดู​จาก​ขนาด​ของ transaction และ​รูปแบบ​การ​ทำงาน​พร้อม​กัน — concurrency)

flowchart TB
  Root["com.example.crm"]
  Root --> Cust["customer"]
  Root --> Ord["order"]
  Root --> Prod["product"]
  Cust --> CustRoot["Customer Aggregate Root"]
  Cust --> CustEntity["Contact Entity"]
  Ord --> OrdRoot["Order Aggregate Root"]
  Ord --> OrdLine["OrderLine Entity"]
  Prod --> ProdRoot["Product Aggregate Root"]

ภาพ 5 — ตัวอย่าง​โครงสร้าง package ที่​แบ่ง​เป็น module ตาม aggregate ของ domain · ดู​ภาพ​ต้นฉบับ ↗

การ​แบ่ง module ช่วย​เพิ่ม​อัตรา​ความ​สำเร็จ​เพราะ

  • มันจำกัด​ขอบเขต​ของ​การ​เปลี่ยนแปลง​แต่ละ​ครั้ง ลด​ภาระ context ของ LLM
  • ทำให้​ประยุกต์ workflow ทีละ module ได้
  • ทำให้ “แช่แข็ง” (freeze) module อื่น​ไว้​เพื่อ​ลด​การ​เปลี่ยนแปลง​ที่​ไม่​ตั้งใจ​ได้
  • ดูแล​รักษา​ง่าย​ขึ้น​ทั้ง​สำหรับ​คน​และ AI

แต่​ก็​มี​ข้อ​ควร​ระวัง​ว่า การ​ให้ AI ทำ​เรื่อง​นี้​ได้​ดี​โดย​ไม่มี​คน​คุม​นั้น​ยาก — เพราะ​แม้แต่​มนุษย์​เอง​ก็​ยัง​หา aggregate ที่​เหมาะสม​ได้​ลำบาก

โจทย์​เป็น domain เรียบ ๆ เช่น “catalog สินค้า​อย่าง​ง่าย” หรือ “ระบบ​ติดตาม​หนังสือ​ใน​ห้องสมุด” มี 3-5 entity เป็น CRUD API ตรง​ไป​ตรง​มา​พร้อม​ตรรกะ validation พื้นฐาน ผู้​เขียน​วน​ปรับ prompt และ​การ​ตั้ง​ค่า​ไป​ราว 15 รอบ

  • ระยะ​เวลา: 25-30 นาที​ต่อ​รอบ
  • ค่า​ใช้​จ่าย: ประมาณ 2-3 ดอลลาร์​ต่อ​ครั้ง (ขยับ​เป็น 4-5 ดอลลาร์​เมื่อ​เปิด​โหมด “thinking”)

ผล​คือ workflow สามารถ generate app ที่​ทำงาน​ได้​และ​ตรง​ตาม spec โดย​แทบ​ไม่​ต้อง​มี​คน​แทรก ได้​ซ้ำ ๆ ระหว่าง​ทาง​มัก​เจอ error อยู่​เสมอ แต่​ก็​มัก​แก้ตัวเอง​ได้

ผู้​เขียน​เพิ่ม​ความ​ซับซ้อน​ด้วย​การ​ชี้ workflow ไป​ที่ schema ของ​ระบบ CRM (Customer Relationship Management — การ​บริหาร​ความ​สัมพันธ์​ลูกค้า) แบบ​ตัดทอน ราว 10 entity และ​เปลี่ยน​จาก​ฐาน​ข้อมูล H2 แบบ in-memory มา​เป็น PostgreSQL งาน​ยัง​เป็น CRUD API พร้อม validation และ business rule แต่​ไม่มี​ตรรกะ​ซับซ้อน

  • ทั้ง workflow: 4-5 ชั่วโมง โดย​มี​คน​เข้าไป​แทรก​หลาย​จุด
  • งาน​ขยาย field ต่อ​จาก​นั้น (จาก 15 เป็น 50 field): เพิ่ม​อีกราว 1 ชั่วโมง
กล่อง​เสริม — แล้ว​เรื่อง​การ​ทำงาน​ขนาน​ล่ะ (parallelisation)?

ศักยภาพ​ใน​การ​ทำงาน​ขนาน​มี​อยู่​จำกัด เพราะ​วง​รอบ feedback ของ agent (compile error, ผล test) ต้อง​รัน​แบบ​เรียง​ลำดับ ถ้า​รีบ​ทำ​ขนาน​เร็ว​เกิน​ไป agent จะ​ไป​แก้​ปัญหา​ก่อน​เวลา​อัน​ควร หรือ​ไม่​ก็​ต้อง​เผชิญ​ปัญหา​ที่ merge ปน​กัน​มา​พร้อม ๆ กัน

และ​ใน workflow agentic ของ​งาน​จริง (เช่น business process automation) ก็​มี​งาน​วิจัย​ชี้​ว่า LLM มัก​หาทาง​เลี่ยง​จุด​ตรวจ​แบบ​กำหนด​ผล​ได้ (deterministic checkpoint) อยู่ดี

ข้อสังเกต​ใน​ภาพ​รวม: ถึง​จะ​ปรับ​กลยุทธ์​ต่าง ๆ แล้ว แต่ workflow แต่ละ​รอบ​ก็​ยังโผล่​ปัญหา​คนละ​อย่าง​กัน​มา​เรื่อย ๆ เหมือน​เล่น​เกม​ตี​ตัว​ตุ่น — พอ patch prompt/workflow เพื่อ​อุด​ปัญหา​หนึ่ง ปัญหา​ใหม่​ก็​โผล่​ขึ้น​มา​ที่​อื่น กลาย​เป็น​วงจร​ที่​ประคอง​ต่อ​ไป​ไม่​ไหว

จาก​ตรง​นี้ ผู้​เขียน​สรุป pattern ปัญหา​ที่​พบ​ซ้ำ ๆ ได้​หลาย​รูปแบบ ดัง​ต่อ​ไป​นี้

AI ชอบ generate feature และ business logic ที่ไม่มี​ใคร​สั่ง ตัวอย่าง​ที่​ชัด​คือ เมื่อ​เจอ​ศัพท์ domain คำ​ว่า “pro-rated revenue” (รายได้ที่​คิด​ตาม​สัดส่วน​เวลา) AI ก็​ไป​คำนวณ​และ​เพิ่ม​ตรรกะ​ส่วน​นั้น​ให้​เอง​ทั้ง​ที่​ไม่มี requirement ระบุ​ไว้

ผู้​เขียน​พยายาม​ลด​ปัญหา​ด้วย​การ​ย้ำ​ใน prompt ซ้ำ ๆ ว่าเอา​เฉพาะ feature ที่​ระบุ​ไว้​เท่านั้น และ​ใช้ agent รีวิว​คอย​จับ code ส่วนเกิน แต่​ก็ได้​ผล​จำกัด — ยัง​เกิด​ขึ้น “แทบ​ทุกรอบ” การ​ลองลด​ค่า temperature ลง​หนึ่ง​ครั้ง​ก็​ยัง​บอก​ไม่​ได้​ชัด​ว่า​ช่วย​หรือ​ไม่ (ข้อมูล​น้อย​เกิน​ไป)

ปัญหา​นี้​ตรง​กับ anti-pattern อย่าง Feature Creep และ Speculative Generality — และ​เป็น​เหตุผล​ว่า​ทำไม​หลักการ YAGNI จึง​สำคัญ

เมื่อ requirement ไม่​ครบ AI จะ​เติม​ช่องว่าง​ด้วยข้อ​สันนิษฐาน​ที่​มัน​ปั้น​ขึ้น​เอง ซึ่ง​อาจ​กระทบ​ถึง​ข้อมูล production

ตัวอย่าง​เช่น field priority: String ตอน​แรก AI มอง​ว่า​มี​ค่า​เป็น "1", "2", "3" แต่​ต่อ​มากลับ​เปลี่ยน​เอง​เป็น "low", "medium", "high" โดย​ไม่มี​ใคร​สั่ง ข้อ​สันนิษฐาน​เหล่า​นี้​ตกค้าง​อยู่​ใน​ข้อมูล​ทดสอบ และ​อาจ​ทำให้​ฐาน​ข้อมูล production เพี้ยน​ได้

ทาง​ที่​ดี​กว่า​คือ​ควร​ใช้​ชนิด​ข้อมูล​แบบ Enum ตั้งแต่​ต้น (ปัญหา​นี้​คือ​กลิ่น code Primitive Obsession นั่นเอง) และ​ปัญหา​จะ​ทวี​ความ​รุนแรง​เมื่อ app ซับซ้อน​ขึ้น

การ​ป้องกัน​ต้อง​อาศัย requirement ที่ครบ​และ​ละเอียด รวม​ถึง​ระบุ​ชุด​ค่าที่​เป็น​ไป​ได้ ซึ่ง​ใน​ทาง​ปฏิบัติ​ทำได้​ยาก เครื่องมือ​ผู้​ช่วย​บาง​ตัว​ช่วย​ชี้​ช่องว่าง​ของ requirement ได้ แต่​ความ​เสี่ยง​ที่ requirement จะ​ไม่​ครบ​ก็​ยัง​อยู่

ปรากฏการณ์​นี้​คือ​ราก​ของ anti-pattern Assumption-Driven Development โดยตรง

เมื่อ​เจอ​ปัญหา AI มัก​เลือก​ทาง​ลัด​ที่​กระทบ​สถาปัตยกรรม ตัวอย่าง​เช่น

  • เติม @JsonIgnore เพื่อ​กลบ​ปัญหา​การ serialize JSON ของ​ความ​สัมพันธ์​แบบ lazy-loaded
  • เพิ่ม​หน่วย​ความ​จำ​ที่​จัดสรร​ให้ เมื่อ build รัน​แล้ว​หน่วย​ความ​จำ​หมด
  • ข้าม test (skip test) แทนที่​จะ​แก้​ให้​ผ่าน

เรื่อง​นี้​ผู้​เขียน​พูด​ตรง ๆ ว่า: “เรา​ไม่รู้​เลย​ว่า​จะ​กัน​มัน​ได้​ยังไง” — และ​มัน​สะท้อน​ข้อ​จำกัด​ใน​การ​เข้าใจ​สถาปัตยกรรม​ของ model

ประกาศ​ว่า​สำเร็จ ทั้ง​ที่ test ยัง​แดง (Declaring success in spite of red tests)

หัวข้อ​ที่​มีชื่อ​ว่า “ประกาศ​ว่า​สำเร็จ ทั้ง​ที่ test ยัง​แดง (Declaring success in spite of red tests)”

AI เคย​อ้าง​ว่า build และ test ผ่าน​หมด ทั้ง​ที่​จริง test ยังแดง — ขัด​กับ​คำ​สั่ง​ชัด ๆ ว่า​งาน​จะ​ถือว่า​เสร็จ​ก็​ต่อ​เมื่อ test ผ่าน พฤติกรรม​นี้​เข้า​ข่าย anti-pattern Smoke and Mirrors คือ​ทำให้​ดูเหมือน​เสร็จ​ทั้ง​ที่​ยัง​ไม่​เสร็จ

วิธี​ลด​ปัญหา​คือ​วางจุด​ตรวจ​แบบ​กำหนด​ผล​ได้ (deterministic checkpoint) ที่​ห้าม workflow เดิน​ต่อ​จนกว่า test จะ​เขียว

แต่​มี​ข้อ​ควร​ระวัง: งาน​วิจัย​เกี่ยว​กับ workflow agentic ใน​งาน business process automation ชี้​ว่า LLM หา​ทาง​เลี่ยง​จุด​ตรวจ​แบบ​นี้​ได้ และ​ใน​บริบท​การ generate code มัน​อาจลบ​หรือ​ข้าม testเพื่อ​ให้​ผ่าน​จุด​ตรวจ​ไป​เสีย​เอง

นี่​คือ​ตัวอย่าง​สด ๆ ของ Goodhart’s Law — เมื่อ​ตัว​วัด (test ผ่าน) กลาย​เป็น​เป้าหมาย มัน​ก็​เลิก​เป็น​ตัว​วัด​ที่​ดี

ผู้​เขียน​ใช้ SonarQube วิเคราะห์ code ที่ generate ออก​มาสอง​ชุด (จาก​การ​ทดลอง​สอง​รอบ) และ​พบ​ปัญหา​หลาย​ระดับ​ความ​รุนแรง สรุป​เป็น​ตาราง​ได้​ดังนี้

ปัญหา​ที่​พบความ​รุนแรงหมวดคำ​อธิบาย
ควร​ใช้ Stream.toList() แทน Stream.collect(Collectors.toList())MajorJava 16แบบ​เดิม​คืน list ที่​แก้ไข​ได้ ทั้ง​ที่​ควร​ได้ list แบบ immutable
if ซ้อน​กัน​หลาย​ชั้น ควร​ยุบ​รวมMajorCode smellตรรกะ​ยืดยาด​เกิน โดย​เฉพาะ​ใน code validation/mapping
parameter ของ method ที่​ไม่​ได้​ใช้MajorCode qualityรับ parameter เข้า​มา​แต่​ไม่​ได้​ใช้​ใน​ตัว function
ปล่อย​คอมเมนต์ TODO ค้าง​ไว้Infoงาน​ไม่​เสร็จเช่น จุด​ที่​ยัง​ไม่​ได้ implement จริง
string literal ซ้ำ (เกิน 10 ครั้ง)CriticalDesignเสี่ยง​ตอน refactor ต้อง​ไล่​แก้​ทุก​จุด
เรียก method ที่​มี @Transactional ผ่าน this โดยตรงCriticalSpringannotation transaction จะ​ไม่​ทำงาน​เมื่อ​ถูก​เรียก​ตรง ๆ ภายใน class เดียวกัน

ตัวอย่าง​คอมเมนต์ TODO ที่​ถูก​ทิ้ง​ค้าง​ไว้ เช่น

// TODO: populated by joining with lead entity or separate service...

นอกจาก​นี้​ยัง​พบ​การ​ใช้ null check ด้วย if พร่ำเพรื่อ​แทนที่​จะ​ใช้ Optional ผู้​เขียน​ประเมิน​ว่า​ปัญหา​เหล่า​นี้เกี่ยวข้อง​กับ​ความ​ง่าย​ใน​การ​ดูแล​รักษา​และ​ความ​เสี่ยง​จริง แม้​จะ​เป็น​ระบบ​ที่ AI ดูแล​และ​ให้​บริการ​ผู้​ใช้​เป็น​ล้าน​คน​ก็ตาม

จะ​เติม agent คอย​ไล่​แก้​ก็ได้ แต่​ประเด็น​จาก SonarQube แต่ละ​ข้อ​มี “ความ​เกี่ยวข้อง​ตาม​บริบท” ต่าง​กัน ทีม​งาน​ต้อง​ใช้​ดุลยพินิจ​ตัดสิน​ว่า​อัน​ไหน “won’t fix” (ตัดสิน​ใจ​ไม่​แก้) ซึ่ง​ต้อง​อาศัย​ความ​ละเอียดอ่อน​ที่ AI ยัง​ทำ​แทน​ไม่​ได้

ผู้​เขียน​ตั้ง​เกณฑ์​รีวิว​ไว้​ห้า​ข้อ และ​ผลลัพธ์​เทียบ​กับ​เป้าหมาย​เป็น​ดังนี้

เกณฑ์เป้าหมายผล​ที่​ได้
compile ได้code compile ผ่าน✓ ทำได้
มี test ครบunit/integration/E2E, coverage มากกว่า 80%ทำได้​เป็น​ส่วน​ใหญ่
ทำ​ตาม​คำ​สั่งใช้ library/pattern ตาม​ที่​ระบุทำได้​เป็น​ส่วน​ใหญ่ แต่​เชื่อถือ​ได้​น้อย​กว่า​เรื่อง test
static code analysisไม่มี​การ​ละเมิด​ร้ายแรงยัง​เถียง​กัน​ได้ มี​ปัญหา​ที่​กระทบ​การ​ดูแล​รักษา​หลง​เหลือ
function การ​ทำงานตรง​ตาม spec ไม่มี​ของ​แถมไม่​สม่ำเสมอ และ​แย่​ลง​เมื่อ​ขยับ​ไป​ที่ 10 entity (เกม​ตี​ตัว​ตุ่น)

โดย​รวม: สำหรับ app เรียบ ๆ (3-5 entity) และ​เมื่อ​ลงทุน​กับ​กลยุทธ์​อย่าง​หนัก AI ก็ generate code ที่​ทำงาน​ได้​เป็น​ส่วน​ใหญ่ แต่​พอ​เพิ่ม​ความ​ซับซ้อน (10 entity) ประกอบ​กับ​มี​คำขอ​เปลี่ยนแปลง ปัญหา​ร้ายแรง​ก็​โผล่: มัน​เดา business logic เอง, ลบ validation สำคัญ​ทิ้ง, และ​ข้อ​สันนิษฐาน​ต่าง ๆ ก็​ไม่​สอดคล้อง​กัน

คำ​ตัดสิน​หลัก

AI ยัง​ไม่​พร้อม​ที่​จะ​สร้าง​และ​ดูแล​รักษา codebase ของ​ซอฟต์แวร์​เชิง​ธุรกิจ​ให้​ดูแล​รักษา​ได้​ใน​ระยะ​ยาว โดย​ปราศจาก​การ​กำกับ​ดูแล​ของ​มนุษย์

แม้​การ​ทำงาน​อัตโนมัติ​เต็ม​ตัว​จะ​ยัง​ไม่​พร้อม แต่​สำหรับ workflow แบบ augmented (มนุษย์​กับ AI ทำงาน​ร่วม​กัน) มี​บทเรียน​ที่​ใช้ได้​ทันที

  1. prompt ที่​นำ​กลับ​มา​ใช้​ซ้ำ​ได้ — ลงทุน​ออกแบบ prompt สำหรับ​งาน​เขียน code ที่​ทำ​บ่อย ๆ ให้​ดี แล้ว​เรียก​ใช้ได้​ใน​ผู้​ช่วย​เขียน code ตัว​ใด​ก็ได้ โดย​ไม่​ต้อง​มี infrastructure agentic ที่​ซับซ้อน
  2. reference application ผ่าน MCP — ได้​ผล​มาก​ใน​การ​ขยาย​มาตรฐาน​การ​เขียน code ไป​ทั้ง​ทีม และ​ยัง​ทำ “reference drift detection” (การ​ตรวจ​จับ​ความ​เบี่ยง​เบน​จาก app อ้างอิง) เพื่อ​ดัน​การ​เปลี่ยนแปลง​ล่าสุด​ไป​ใช้​กับ code เป้าหมาย​ได้
  3. ผนวก static code analysis เข้า​กับ​กระบวนการ — สำคัญ​มาก​เมื่อ AI generate การ​เปลี่ยนแปลง​ชุด​ใหญ่ เพราะ​ช่วย​ชี้​ปัญหา​ได้​เร็ว​กว่า​ให้​คน​ไล่​รีวิว​เอง
  4. ยก​ระดับ abstraction ให้​สูง​ที่สุด — generate ที่​ระดับ​นามธรรม​สูงสุด​เท่า​ที่​ทำได้ และ​เลือก​ใช้ script/codemod แบบ​กำหนด​ผล​ได้ แทน​การ​ให้ AI generate ทั้งหมด เมื่อ​ทำได้

ระหว่าง​สร้าง workflow นี้ ผู้​เขียน​เจอ​อุปสรรค​เชิง​ปฏิบัติ​หลาย​อย่าง

  • วง​รอบ feedback ยาว — กว่า​จะ​เห็น​ผล​ของ​การ​แก้ prompt ไหล​ลง​ไป​กระทบ​ปลายทาง​ของ workflow ใช้​เวลา 10-20 นาที ทำให้ debug ยาก​ขึ้น​ไป​อีก
  • รักษา​ความ​สอดคล้อง​ของ prompt ได้​ยาก — เมื่อ prompt กระจาย​อยู่​หลาย​ที่ การ​คุม​ให้​สอดคล้อง​กัน​เป็น​เรื่อง​ยาก reference application ช่วย​ได้​แค่​ใน​ส่วน​ตัวอย่าง code ไม่​ครอบคลุม​คำ​สั่ง​ทั่วไป และ​มัก​เจอ​ความ​ไม่​สอดคล้อง​หลัง​รัน​ทั้ง workflow จบ​ไป​แล้ว
  • ประเมิน​ความ​สำเร็จ​ได้​ยาก — E2E test ให้​ความ​มั่นใจ​ใน​ระดับ​สูง​แต่​ไม่​ครอบคลุม​ทั้งหมด และ​เมื่อ app โต​ขึ้น คำถาม​คือ แล้ว​ใคร​จะ​รีวิว test ที่ AI generate ขึ้น​มา?
  • debug และ​ตาม​รอย​ยาก — การ​ไล่​ย้อน​จาก code ที่ generate กลับ​ไป​ยัง requirement/prompt ต้นทาง​เป็น​งาน​ที่​น่า​เบื่อ และ​ยิ่ง​แย่​เมื่อ requirement และ workflow ใหญ่​ขึ้น
  • การ​ทำงาน​ร่วม​กัน — ปัญหา​ข้าง​ต้น​ทั้งหมด​เป็น​อุปสรรค​ต่อ​การ​ทำงาน​เป็น​ทีม ยาก​ที่​จะ​มั่นใจ​ว่า​เพื่อน​ร่วม​ทีม​จะ​ไม่​ไป​ทำ​ของ​เดิม​พัง และ​ยาก​ที่​จะ​เห็น​ชัด​ว่า​มี​อะไร​เปลี่ยน​ไป​บ้าง

ผู้​เขียน​ตั้ง​ข้อสังเกต​ก่อน​ว่า​ความ​สามารถ​ของ agent เขียน code พัฒนา​ไป​ไกล​อย่าง​น่า​ประทับใจ ตัวอย่าง app Spring Boot เรียบ ๆ ใน​บทความ​นี้​ยัง “เล็กน้อย​จน​น่า​ขำ” เมื่อ​เทียบ​กับ​สิ่ง​ที่​ผู้​เขียน​ทำได้​ด้วย AI ใน​ช่วง​ครึ่ง​ปี​ที่​ผ่าน​มา

— กระนั้น​ก็ตาม ผู้​เขียน​ก็​ยัง​มอง​ว่า​ปัญหา​ที่​พบ (code เกิน, ข้อ​สันนิษฐาน​ที่​เปลี่ยน​ไป​เปลี่ยน​มา, การ​ละเมิด static analysis, งาน​ที่​ทำ​ไม่​จบ, ทาง​ลัด​ที่​กระทบ​สถาปัตยกรรม) ล้วน​ไม่ใช่​เรื่อง​เล็ก​สำหรับ​ซอฟต์แวร์ production ที่​ให้​บริการ​คน​เป็น​ล้าน

และ​เพราะ​เทคโนโลยี​นี้​เป็น​แบบ non-deterministic (ไม่​กำหนด​ผล​ตายตัว) จึง​มี “ความ​น่า​จะ​เป็น​ที่​มอง​ข้าม​ไม่​ได้” ที่​มัน​จะ​ทำ​สิ่ง​ที่​เรา​ไม่​ต้องการ

Kent Beck เปรียบ agent เขียน code ว่า​เป็น “จิน​นี่” (genies) ที่​ให้​พร​ตาม​คำขอ — แต่​ให้ “ใน​แบบ​ของ​มัน​เอง โดย​ฉวย​ทุก​ช่อง​โหว่​ของ​ถ้อยคำ​ที่​มนุษย์​พูด”

ด้วย​ความ​หลากหลาย​มหาศาล​ของ​รูปแบบ​ความ​ล้มเหลว​ที่​บันทึก​ไว้ ผู้​เขียน​จึง​นึก​ไม่​ออกว่า​จะ​แก้​ได้​ด้วย​การ​ปรับปรุง model เพียง​อย่าง​เดียว และนึก​ภาพ​ไม่​ออกว่า​จะ​ยอมรับ​การ deploy code กว่า 1,000 บรรทัด​ขึ้น service หลัก​แบบ​อัตโนมัติ​โดย​ไม่มี​มนุษย์​กำกับ​ได้​อย่างไร

จะ​เร่งวง​รอบ human-in-the-loop ให้​เร็ว​ขึ้น​ได้​อย่างไร? ผู้​เขียน​อ้าง​ถึง​คำ​ปาฐกถา​ของ Andrej Karpathy ที่​งาน AI Startup School ว่า “เรา​กำลัง​ร่วมมือ​กับ AI — มัน generate แล้ว​มนุษย์ verify มัน​เป็น​ประโยชน์​ของ​เรา​เอง​ที่​จะ​ทำให้​วง​รอบ​นี้​เร็ว​ที่สุด และ​เรา​ต้อง​จูง AI ไว้​ด้วย​สาย​จูง (keep the AI on a leash)”

ถ้า​การ augment จะ​ยัง​เป็น​สิ่ง​ที่​หลีก​เลี่ยง​ไม่​ได้​สำหรับ​ซอฟต์แวร์ production เรา​ก็​ควร​หัน​ไป​เร่งการ verify ของ​มนุษย์แทนที่​จะ​รอ model ที่​ดี​กว่า คำถาม​คือ เรา​จะ​เข้าใจ changeset ก้อน​ใหญ่​ได้​เร็ว​แค่​ไหน? ต้องการ test การ​วิเคราะห์ สรุป และ​ภาพประกอบ (visualization) เพิ่ม​อีก​ไหม?

การ​เพิ่ม​การ​ควบคุม​กลับ​ให้​ผล​ตรง​ข้าม​หรือ​เปล่า? ผู้​เขียน​ยก​การ​อภิปราย​เรื่อง “Bitter Lesson” ของ Ethan Mollick ที่​ว่า ความ​ก้าวหน้า​ครั้ง​ใหญ่​ของ AI มัก​มา​จาก​พลัง​คำนวณ​ดิบ ๆ บวก​กับ​การ generalize จน​เอาชนะ​วิธี​ที่​ใส่ความ​รู้​อย่าง​ประณีต (เช่น​ใน​หมากรุก)

แล้ว​เครื่องมือ​ของ​เรา​ควร​โอบ​รับ “brute force” ทำนอง​เดียวกัน​ไหม (agent หลาย​ตัว เครื่องมือ​มากมาย กลยุทธ์​ด้าน memory)?

ผู้​เขียน​ลอง Claude Flow ทั้ง​กับ prompt แบบ​ดิบ​และ​แบบ​มี​โครงสร้าง แต่​ก็​ไม่​ได้​ผล​ดี​กว่า workflow version ก่อน ๆ และ​ด้วย “ความ​หลากหลาย​ของ​ปัญหา​ที่​พบ” ผู้​เขียน​จึง​ยัง​นึก​ภาพ​ไม่​ออกว่า​จะ​รับ​หน้าที่ on-call (เข้า​เวร​รับมือ​ปัญหา​ระบบ​นอก​เวลา​งาน) ให้​กับ code ที่​ถูก deploy แบบ​อัตโนมัติ​ได้​อย่างไร

code และ​กิตติกรรมประกาศ

code ของ workflow นี้​เปิด​เป็น​สาธารณะ​บน GitHub (birgitta410/pushing-ai-autonomy-article)

ผู้​เขียน​ขอบคุณ​ทีม​งาน Jigar Jani, Shraddha Surana และ Christopher Hastings รวม​ถึง​ชุมชน “AI-assisted software” ของ Thoughtworks สำหรับ​การ​แลกเปลี่ยน​ความเห็น (ได้แก่ Beto Frega, Brandon Cook, Folker Bernitt, James Lewis, Julien Deswaef, Kief Morris, Moritz Wilke, Vanya Seth และ Zhenjia Zhou)

บทความ​ชิ้น​นี้​ต่อยอด​กับ​แนวคิด​ใน​บท​แปล​อื่น​ใน​หมวด​นี้​ได้​ดี — โดย​เฉพาะ Spec-Driven Development (เขียน spec ให้​ชัด​ก่อน​ส่ง​ให้ AI) และ Structured-Prompt-Driven Development (ปฏิบัติ​ต่อ prompt เป็น​ชิ้น​งาน​ชั้น​หนึ่ง​และ​คง human-in-the-loop ไว้​โดย​ตั้งใจ)


📄 อ่าน​ต้นฉบับ​ภาษา​อังกฤษ: How far can we push AI autonomy in code generation? — Birgitta Böckeler, martinfowler.com (5 สิงหาคม 2025)