ข้ามไปยังเนื้อหา
KoishiAI
EN
← สารบัญ

บทที่ 7 จาก 12 · Agentic Engineering — คู่มือปฏิบัติเขียนซอฟต์แวร์ระดับ Production ด้วย AI Agent

จากศูนย์ถึง Production — เส้นทาง 9 ขั้น

ตัวอย่างจริงของการเพิ่มฟีเจอร์เข้าระบบที่รันอยู่แล้ว ตั้งแต่สเปกจนถึง rollout พร้อมระบุว่าขั้นไหนคนทำ ขั้นไหน agent ทำ วิธีเขียนสเปกที่ agent ทำงานต่อได้จริง และวิธีรีวิวเมื่อโค้ดไม่ได้เขียนโดยคน

ตัวอย่างจริง: เพิ่มระบบคูปองใน checkout service ที่รันอยู่แล้ว แต่ละขั้นระบุว่าใครทำ ใช้เวลาเท่าไร และผลลัพธ์ที่ต้องได้คืออะไร

ขั้นงานใครทำผลลัพธ์ที่ต้องได้
0วางพื้นฐาน (ทำครั้งเดียวต่อ repo)คนAGENTS.md, verify.sh, hooks, memory/, PR template
1เขียน specคน + agent ช่วยถามdocs/specs/coupon.md ที่ตอบคำถามกำกวมได้ครบ
2ซอยงานคนรายการ 5–8 งานย่อย แต่ละงานปิด loop ได้ใน 30 นาที
3RED — เขียน testagenttest แดงที่คนอ่านและอนุมัติแล้ว
4GREEN — implementagent (loop)gate เขียวทั้งชุด พร้อม output จริง
5รีวิวคนตรวจ spec, คุณภาพ test, blast radius — ไม่ใช่ทุกบรรทัด
6MergeคนCI เขียวบน main, ADR อัปเดต, pitfalls อัปเดต
7Canary + วัดระบบ5% เป็นเวลา 24 ชม. guardrail ทุกตัวปกติ
8Rollout เต็มคนอนุมัติ100% แล้วลบ flag ภายใน 2 สัปดาห์

7.1 ขั้นที่ 1 — spec ที่ agent ทำงานต่อได้จริง

สเปกที่ดีไม่ใช่สเปกที่ยาว แต่คือสเปกที่ ไม่เหลือคำถามที่ต้องเดา เทคนิคที่ได้ผลคือให้ agent อ่านร่างแรกแล้วถามคำถามที่มันจะต้องเดาถ้าไม่ถาม

อ่านร่างสเปกนี้ แล้วบอกฉัน 10 คำถามที่คุณจะต้องเดาคำตอบเองถ้าลงมือ
implement ตอนนี้ เรียงตามความเสี่ยงที่การเดาผิดจะทำให้ผู้ใช้เสียหาย
สำหรับแต่ละข้อ ให้เสนอคำตอบที่คุณคิดว่าน่าจะถูกด้วย ฉันจะได้แค่ยืนยันหรือแก้

โครงสร้างสเปกที่ใช้ได้:

# Spec: Coupon Discount (v1)

## Goal
ลูกค้าใส่รหัสคูปองตอน checkout แล้วได้ส่วนลดตามชนิดของคูปอง

## In scope
- คูปองแบบ % (1–100) และแบบจำนวนเงินคงที่
- จำกัดจำนวนครั้งต่อคูปองทั้งระบบ และต่อผู้ใช้
- วันหมดอายุ

## Out of scope (v1) — ระบุให้ชัดเพื่อกัน agent ทำเกิน
- ใช้คูปองหลายใบพร้อมกัน
- คูปองเฉพาะสินค้าหรือเฉพาะหมวด
- คูปองแบบสร้างอัตโนมัติต่อผู้ใช้

## กติกาธุรกิจ
R1  ส่วนลดคิดจาก subtotal (ก่อนภาษี ก่อนค่าส่ง)
R2  ภาษีคำนวณจากยอดหลังหักส่วนลด
R3  ค่าส่งไม่ถูกลด
R4  ยอดสุทธิต่ำสุดคือ 0 — ส่วนลดเกินยอด ให้ตัดที่ยอด ไม่ทอนเงิน
R5  ปัดเศษที่ 2 ตำแหน่ง แบบ ROUND_HALF_UP ตอนคำนวณส่วนลดเท่านั้น
R6  คูปองถูกนับใช้เมื่อ order ชำระเงินสำเร็จ ไม่ใช่ตอนใส่รหัส

## เคสที่ต้อง reject (พร้อม error code ที่ตายตัว)
| เงื่อนไข              | HTTP | code                |
|-----------------------|------|---------------------|
| ไม่มีรหัสนี้           | 404  | COUPON_NOT_FOUND    |
| หมดอายุ               | 422  | COUPON_EXPIRED      |
| ใช้ครบโควตาระบบ        | 422  | COUPON_EXHAUSTED    |
| ผู้ใช้คนนี้ใช้ครบแล้ว   | 422  | COUPON_USER_LIMIT   |
| ยอดขั้นต่ำไม่ถึง        | 422  | COUPON_MIN_NOT_MET  |
| ใส่มาสองใบ            | 422  | COUPON_MULTIPLE     |

## Invariants (ใช้เขียน property test)
I1  net_total >= 0 เสมอ
I2  discount + net_total == subtotal เสมอ
I3  ทศนิยมทุกค่าไม่เกิน 2 ตำแหน่ง
I4  จำนวนครั้งที่ใช้จริง <= โควตา เสมอ แม้มี request พร้อมกัน

## ประเด็นที่ตัดสินใจแล้ว (กัน agent ถามซ้ำ)
- concurrency: ใช้ SELECT ... FOR UPDATE บนแถวคูปอง ไม่ใช้ optimistic lock
  เหตุผล: จำนวนคูปองต่ำ contention ไม่สูง และเราต้องการความถูกต้องเด็ดขาด (I4)
- ไม่ cache สถานะคูปองใน Redis ใน v1 — ความถูกต้องสำคัญกว่า latency

## Definition of done
- ทุก R และ I มี test อย่างน้อยหนึ่งตัว โดยชื่อ test อ้างรหัสกติกา (test_r4_...)
- verify.sh เขียว
- มี feature flag `coupon_v1` ที่ปิดได้ทันที

7.2 ขั้นที่ 2 — ซอยงานให้ loop ปิดได้

งานย่อยที่ดีคือ มีเกณฑ์ผ่านชัด แตะไฟล์น้อย และไม่ขึ้นกับงานที่ยังไม่ทำ

งานสิ่งที่ทำtest
T1domain model + validation ล้วน ไม่มี DBtest_coupon_domain.py
T2repository + migration (expand phase)test_coupon_repo.py
T3การคิดส่วนลดกับภาษี R1–R5test_calculation.py
T4concurrency + โควตา I4test_concurrency.py
T5HTTP endpoint + error mappingtest_api_coupon.py
T6feature flag + shadow modetest_rollout.py
T7observability: metric, log, alertตรวจด้วยตาใน staging

ลำดับสำคัญคือ T1 ก่อนเสมอ เพราะมันคือที่ที่ความกำกวมของสเปกจะโผล่ ถ้า T1 ยาก แปลว่าสเปกยังไม่ชัดพอ ให้กลับไปแก้สเปก อย่าดันต่อ

7.3 ขั้นที่ 5 — รีวิวอย่างไรเมื่อโค้ดไม่ได้เขียนโดยคน

การอ่านทีละบรรทัดไม่ scale เมื่อ agent ผลิตโค้ดได้เร็วกว่าคนอ่าน 10 เท่า ต้องเปลี่ยนจุดโฟกัสของการรีวิว

เดิม (โค้ดคนเขียน)ใหม่ (โค้ด agent เขียน)
อ่านทุกบรรทัดหา bugอ่าน test ทุกบรรทัด เพราะ implementation จะวิ่งเข้าหา test เสมอ
ตรวจ style และ namingปล่อยให้ linter ทำ ถ้าต้องคอมเมนต์เรื่อง style แปลว่า config ยังไม่ครบ
ถามว่าทำไมเขียนแบบนี้ถามว่า spec ตรงกับที่ธุรกิจต้องการไหม เพราะ bug ส่วนใหญ่ย้ายไปอยู่ที่สเปกแล้ว
ดู diff อย่างเดียวดู diff + ไฟล์ที่ไม่ควรถูกแตะแต่ถูกแตะ + dependency ใหม่
เชื่อว่าผู้เขียนเข้าใจระบบตรวจว่า agent ไม่ได้สร้าง pattern คู่ขนานกับของที่มีอยู่แล้ว

คำถาม 7 ข้อที่ต้องตอบให้ได้ก่อนกด approve:

  1. test พวกนี้จะแดงไหม ถ้าฉันเอา requirement หลักออกจาก implementation (ถ้าไม่แดง = test ไร้ค่า)
  2. มีเคส reject ครบตามสเปกไหม หรือทดสอบแต่ happy path
  3. ไฟล์ที่ถูกแตะ อยู่ในขอบเขตของงานนี้ทั้งหมดไหม
  4. มี dependency ใหม่ไหม จำเป็นจริงไหม ใครดูแล
  5. มี migration ไหม ย้อนกลับได้ไหม ล็อกตารางนานแค่ไหน
  6. ฟีเจอร์นี้ปิดได้ทันทีไหมถ้าพัง
  7. blast radius และแผน rollback ในคำอธิบาย PR สมจริงไหม

เทคนิค mutation test แบบเร็ว

ถ้าไม่แน่ใจว่า test ชุดนี้มีคุณภาพจริงไหม ให้แก้ implementation ให้ผิดโดยเจตนาหนึ่งจุด เช่นเปลี่ยน >= เป็น > แล้วรัน test ถ้าไม่มีตัวไหนแดง แปลว่า test ชุดนั้นไม่คุ้มค่าดูแล สั่ง agent ทำสิ่งนี้อัตโนมัติได้: “สร้าง mutant 10 ตัวจาก diff นี้ รัน test แล้วรายงานว่า mutant ไหนรอด”

สรุปบทนี้

เส้นทางจากสเปกถึง production มี 9 ขั้น และคนถือขั้นที่ 0, 1, 2, 5, 6 กับการอนุมัติขั้นที่ 8 สเปกที่ดีคือสเปกที่ไม่เหลือคำถามให้เดา ซอยงานให้ปิด loop ได้ใน 30 นาที และเปลี่ยนการรีวิวจากการอ่านโค้ดทีละบรรทัด มาเป็นการอ่าน test กับการตรวจขอบเขต

บทถัดไปว่าด้วย MCP ว่าควรใช้เมื่อไหร่ ออกแบบอย่างไร และช่องโหว่ prompt injection ที่มากับ tool output