สรุปสั้นก่อนเริ่ม
YAGNI = "You Aren't Gonna Need It" — กฎจาก Extreme Programming ที่ Kent Beck บัญญัติและ Ron Jeffries สรุปสั้นๆ ว่า
"Always implement things when you actually need them, never when you just foresee that you will need them."
แปลตรง — "เขียนเมื่อต้องการจริง อย่าเขียนเพราะเดาว่าจะต้องใช้"
ฟังดูง่ายเหมือนสุภาษิตในตำราเรียน — แต่ทีมเขียนโค้ดทั่วโลกยังพังเพราะข้อนี้ทุกวัน
ทำไม?
เพราะมันขัดสัญชาตญาณของ engineer — engineer ดีๆ ชอบ "คิดล่วงหน้า" ชอบสร้าง abstraction ที่ "flexible" ชอบเขียน option ที่ "เผื่อใช้" และนั่นคือกับดัก
บทความนี้รวม
- ที่มาของ YAGNI และทำไม XP community เน้นข้อนี้
- 4 ต้นทุนของการเผื่อ ที่ Martin Fowler วิเคราะห์ (Build / Delay / Carry / Repair)
- 5 สัญญาณว่าคุณกำลัง violate YAGNI ในโปรเจกต์ตัวเอง
- เมื่อไหร่ที่ YAGNI ผิด — กรณีที่ต้อง over-engineer จริง (security, audit, compliance)
- วิธีที่ทีม Enersys ใช้ YAGNI ในงาน Odoo / AI / PDPA สำหรับลูกค้าจริง
ใครที่เป็น CTO, tech lead, product manager หรือเจ้าของธุรกิจที่จ้างทีมเขียน software — บทความนี้คุ้ม 14 นาทีของคุณ
YAGNI คืออะไร — และมาจากไหน
YAGNI ไม่ใช่คำใหม่ ไม่ใช่ trend ปี 2026
มันเก่าระดับยุค late 1990s — ตอนที่ Kent Beck เขียนหนังสือ Extreme Programming Explained (1999) และทีม XP ที่ Chrysler Comprehensive Compensation system ทดลองวิธีทำงานใหม่ — เน้น TDD, refactoring, pair programming, simple design
ใน XP มีหลักการ "Do The Simplest Thing That Could Possibly Work" (DTSTTCPW) — ทำสิ่งที่ง่ายที่สุดที่ work ได้
YAGNI คือเครื่องมือบังคับใช้ DTSTTCPW — เพราะ "simplest" จะถูก rationalize เป็น "complex" ได้ง่ายมาก ถ้าไม่มี guardrail
Ron Jeffries (หนึ่งในสามผู้ร่วมก่อตั้ง XP — Beck, Jeffries, Cunningham) สรุปไว้เรียบๆ ว่า
"Always implement things when you actually need them, never when you just foresee that you will need them."
นี่คือนิยามที่ดีที่สุดของ YAGNI — สั้น คม และ actionable
ตั้งแต่นั้นมา YAGNI กลายเป็นส่วนหนึ่งของ vocabulary ของ engineer ทั่วโลก — ถูกอ้างใน code review, ใน architecture meeting, ใน PR description
แต่ก็ยังเป็นสิ่งที่ทีม violate ทุกวัน เพราะมันสวนกับสัญชาตญาณ "อยากเตรียมพร้อม"
4 ต้นทุนของการ "เผื่อไว้" — Martin Fowler Framework
ปี 2015 Martin Fowler เขียน entry ใน bliki ของเขาเรื่อง YAGNI — และจัด framework ของต้นทุนที่ใช้อ้างอิงในวงการมาจนถึงทุกวันนี้
ฟังดูเหมือนแค่เรื่อง "เขียน code เยอะไป" — แต่ Fowler ชี้ให้เห็นว่าต้นทุนของการเผื่อแบ่งออกเป็น 4 ประเภท ที่แยกจากกันชัดเจน
1. Cost of Build (ต้นทุนการสร้าง)
ค่าแรงและเวลาที่ใช้ในการ analyze, code, test, document ฟีเจอร์ที่ สุดท้ายไม่ได้ใช้
ลองคิดง่ายๆ — ถ้าคุณใช้ 2 สัปดาห์เขียนฟีเจอร์ที่ "เผื่อใช้" แล้วใน 6 เดือนข้างหน้าไม่ได้ใช้ — 2 สัปดาห์นั้น = ขาดทุน 100%
ตัวเลขในวงการที่ทีมเรา (และทีมที่เรา audit งานให้) เห็นบ่อย:
- 30-50% ของ feature ที่ "เผื่อไว้" → ไม่เคยถูกใช้
- 20% เคยใช้ แต่ใช้ในรูปแบบที่ต่างจากที่ออกแบบเลย → เขียนใหม่ดีกว่า
- เหลือ 30-50% ที่ใช้จริง → ก็ยังต้องปรับเล็กน้อยเพราะ requirement เปลี่ยน
จาก 100% ที่ลงทุน เผลอๆ ได้ใช้จริงตามที่คาด เพียง 20-30%
2. Cost of Delay (ต้นทุนของการล่าช้า)
นี่คือต้นทุนที่ "มองไม่เห็น" และ เจ็บที่สุด
ถ้าทีมใช้ 2 สัปดาห์ทำฟีเจอร์ A ที่ "เผื่อใช้" — เวลาเดียวกันนั้นเอาไปทำฟีเจอร์ B ที่ลูกค้าต้องการ ตอนนี้ ได้
Fowler ยกตัวอย่างของบริษัทประกันสตาร์ทอัพ — ใช้เวลา 6 เดือนเขียน pricing engine ที่รองรับ piracy insurance (ที่ยังไม่ขาย) แทนที่จะทำ storm-risk pricing (ที่ขายได้แล้ว) ผลคือพลาดตลาดเปิดของ storm-risk
ในธุรกิจจริง:
- เวลาที่เสียไป = revenue ที่ไม่เกิด
- คู่แข่งที่ไม่ over-engineer → ship เร็วกว่า → ได้ลูกค้าก่อน
- delay 1 เดือนใน market timing = อาจเสีย market position 1-2 ปี
ในมุมของลูกค้า software house (เช่นลูกค้า Enersys) — ต้นทุนนี้คือ ค่าเสียโอกาส ที่ระบบยังไม่ได้ใช้งาน
3. Cost of Carry (ต้นทุนการแบกรับ)
นี่คือต้นทุนที่ทีมยังไม่ค่อยตระหนัก — แต่สะสมไปเรื่อยๆ
โค้ดที่ "เผื่อไว้" ทุกบรรทัด = ภาระที่ทุกคนต้อง:
- อ่าน (เวลา onboarding คนใหม่)
- เข้าใจ (เวลา debug)
- maintain (เวลา dependency เปลี่ยน)
- ทดสอบ (เวลา regression test)
- ระวัง (เวลาแก้ feature ใกล้เคียง)
ตัวอย่างที่เราเจอใน audit งาน Odoo ลูกค้าใหม่:
ทีมเดิมเขียน abstraction layer เผื่อรองรับ multi-tenant ตอนเริ่มโปรเจกต์ — แต่ 3 ปีผ่านไป ระบบยังเป็น single-tenant อยู่ และไม่มีแผนเปลี่ยน
abstraction นั้นกลายเป็น:
- 3 ชั้นซ้อนกัน เวลา trace bug ต้องเปิด 5-6 ไฟล์
- developer ใหม่ใช้เวลา 2-3 สัปดาห์ก่อนจะ navigate codebase ได้
- ทุก feature ใหม่ต้องคิดว่า "abstraction นี้รองรับไหม"
- เวลา upgrade Odoo version → compatibility break ที่ abstraction layer ทำให้ migration ยาก
นี่คือ cost of carry ที่ compound ทุกเดือน
4. Cost of Repair (ต้นทุนการซ่อม)
เมื่อ "วันที่ต้องใช้" มาถึง 6 เดือน 1 ปี หรือ 3 ปีต่อจากตอนเขียน — สิ่งที่เผื่อไว้ ไม่ตรงกับความต้องการจริง เกือบทุกครั้ง
เหตุผล:
- ตอนเขียน → guess จาก requirement ใน mind (ที่ไม่ verify)
- ตอนใช้จริง → requirement ที่จริงต่างออกไป เพราะ business เปลี่ยน, user feedback มา, regulation เปลี่ยน
ผลคือต้อง:
- ลบของเก่า
- เขียนใหม่
- หรือ ปรับของเก่า — ซึ่งบางทียากกว่าเขียนใหม่
Fowler บอกตรงๆ ว่า — feature ที่ปล่อยทิ้งไว้ 6 เดือน มักจะ outdated มากกว่า useful
นี่คือ technical debt ที่ "ไม่ได้ดอกเบี้ย" — เพราะคุณไม่ได้กู้มาทำอะไร แค่จ่ายค่าซ่อมเฉยๆ
ทำไม Developer ดีๆ ยังพังเพราะ YAGNI
อันนี้น่าสนใจ — engineer ที่เก่งหลายคนยังตกหลุม over-engineer ทุกวัน ทำไม?
เหตุผล 1 — สัญชาตญาณ "เตรียมพร้อม"
engineer ฝึกมาให้ "คิดล่วงหน้า" — design pattern, scalability, extensibility ทุกคำสอน
มันยากที่จะหยุด คิดว่า "วันนี้ฉันจะเขียนแค่สิ่งที่จำเป็น" เพราะมันรู้สึกเหมือนเขียนแบบ amateur
เหตุผล 2 — Identity ของ "good engineer"
หลายคนเชื่อมโยง self-worth กับการเขียน abstraction ที่ดู professional
abstraction = ดูเก่ง — เพราะแสดงให้เห็นว่าเข้าใจ pattern, รู้จัก SOLID, เคยอ่าน Clean Code
แต่ great engineer ตัวจริงรู้ว่า — abstraction ที่ดีคือ abstraction ที่จำเป็น
เหตุผล 3 — Resume-Driven Development
บางทีมเขียน abstraction ที่ไม่จำเป็นเพราะอยากใส่ใน resume ได้ว่า "designed microservices for X scale" ทั้งที่ระบบนั้นมี user 50 คน
นี่ไม่ใช่ความผิด individual แต่เป็นความผิดของ industry ที่ reward complexity เกินกว่า simplicity
เหตุผล 4 — กลัวว่า "เดี๋ยวต้องแก้ตอนหลัง"
argument ที่ดูดี — "ตอนนี้ใส่ feature นี้ง่ายกว่าตอนต้องใส่ปีหน้า"
แต่ argument นี้ผิดในหลายมิติ:
- 70%+ ของ "feature ที่ต้องใส่ปีหน้า" → ไม่เคยต้องใส่จริง
- ตอนต้องใส่จริง requirement มักต่างจากที่คิด
- code base ที่เล็กกว่า + clean กว่า → ใส่ feature ใหม่ง่ายกว่า code base ที่ "เผื่อไว้" แต่รก
เหตุผล 5 — Management Pressure
บางครั้งทีมถูก management ถามว่า "scale ได้ถึงล้าน user ไหม" ก่อนจะมีผู้ใช้คนแรก
ทีมเลย over-engineer เพื่อตอบคำถามนั้น — แทนที่จะตอบว่า "ตอนนี้ไม่จำเป็น พอใกล้แสนค่อยคุยกัน"
5 สัญญาณว่าคุณกำลัง Violate YAGNI
อยาก audit ตัวเองง่ายๆ? ดูสัญญาณเหล่านี้ในโปรเจกต์ที่ทำอยู่
1. มี "Manager" หรือ "Factory" Class ที่จัดการของแค่ 1 ชนิด
ถ้าคุณมี UserFactory ที่สร้างได้แค่ User แบบเดียว — มันไม่ใช่ factory มันคือ over-abstraction
UserFactory มีค่าเมื่อจำเป็นต้องสร้าง User หลายแบบ (regular, admin, guest) จาก source หลายที่ — ถ้ายังไม่ใช่ ตัด
2. มี Configuration Option ที่ไม่มีใครเปลี่ยน
ทุก config option = code path เพิ่ม = test case เพิ่ม = ความซับซ้อนเพิ่ม
ถ้า config นั้นมีค่าเดียวมา 6 เดือนแล้ว → ลบมันออก ใส่ค่า hardcode ไปก่อน เมื่อถึงวันที่ต้องใส่ option จริงค่อยใส่กลับ
3. มี Interface ที่มี Implementation เดียว
PaymentProvider interface ที่มี StripePaymentProvider เป็นเพียง implementation เดียว — interface นั้นทำให้ navigation ลำบาก โดยไม่มีประโยชน์จริง
ใช้ class ตรงๆ ก่อน — เมื่อจำเป็นต้องมี implementation 2 — ค่อย extract interface
4. มี Database Field/Column ที่ไม่มี Code อ่าน
users.metadata column ที่เก็บ JSON "เผื่อใช้" — แต่ไม่มี code path ไหนอ่านหรือเขียน
ทุก field = ความรับผิดชอบ — schema migration ยากขึ้น, backup ใหญ่ขึ้น, นัก audit ต้องถามว่าเก็บอะไร PDPA-wise
5. มี "Generic" Function ที่ใช้ครั้งเดียว
utils/processAnyEntity() ที่ทำได้ทุกอย่าง — แต่ในโปรเจกต์เรียกใช้แค่ 1 ที่
function ที่ใช้ครั้งเดียวควรเป็น code ตรงในที่ที่ใช้ ไม่ต้อง extract — ทำให้คนอ่านไม่ต้องกระโดดข้ามไฟล์
เมื่อไหร่ที่ YAGNI กลายเป็นกับดัก
YAGNI เป็นหลัก guideline ไม่ใช่ดogma
มีกรณีที่ ต้อง over-engineer จริงๆ — เพราะการเพิ่มทีหลังจะแพงเกินไป หรือเสี่ยงเกินไป
Security and Compliance
อันนี้ไม่ใช่ YAGNI — ถ้าระบบจัดการข้อมูลส่วนบุคคล PDPA, GDPR หรือ financial data — ใส่ security control ตั้งแต่วันแรก:
- input validation
- authentication / authorization
- audit logging (ทุก action ที่แตะ PII)
- encryption at rest
เพราะการ retrofit security เข้าระบบที่ ship ไปแล้ว = แพงและเสี่ยงระเบิด
Audit Trail and Logging
ถ้าระบบมี business workflow ที่ต้อง trace ย้อนหลัง — ใส่ audit log ตั้งแต่วันแรก
ค่าใช้จ่ายในการเก็บ log = น้อย เทียบกับค่าเสียโอกาสเมื่อ event เกิดขึ้นแล้วไม่มี log
Data Schema Decisions
schema database เป็นสิ่งที่เปลี่ยนทีหลังยาก — โดยเฉพาะตาราง core
ใช้เวลา design schema ให้ดีตั้งแต่แรก (ไม่ใช่ over-engineer แต่ "เผื่อ" ในระดับ data shape ที่ make sense)
External API Contracts
API ที่ client ภายนอกใช้ = เปลี่ยนยากเพราะกระทบ consumer หลายราย
design carefully ตั้งแต่ v1 — versioning, error format, pagination
YAGNI ใช้ไม่ได้ตรงนี้ เพราะ cost of repair แพงมากเมื่อ break compatibility
YAGNI กับ Refactoring — ความเข้าใจผิดที่พบบ่อย
หลายคนคิดว่า YAGNI = "ห้าม refactor" — ผิด
Fowler ย้ำชัด — YAGNI ต้องการ codebase ที่ maintainable ถึงจะ work
หลักการคือ:
- เขียนเท่าที่จำเป็น (YAGNI)
- เมื่อต้องการเพิ่ม → refactor ของเดิม แล้วเพิ่ม (Refactoring discipline)
- มี test coverage ดี → refactor ปลอดภัย (TDD)
- มี continuous integration → ส่ง code ใหม่ได้ง่าย (CI/CD)
ถ้าทีมเขียน "minimal" แต่ codebase รก, ไม่มี test, deploy ลำบาก — YAGNI จะกลายเป็น technical debt generator
นี่คือเหตุผลที่ Beck ออกแบบ XP เป็น ชุดวิธีปฏิบัติร่วมกัน ไม่ใช่หลักเดี่ยว
วิธีที่ทีม Enersys ใช้ YAGNI ในงานจริง
ในฐานะ software house ที่ทำงาน Odoo, AI Integration และ Data Privacy (PDPA) ให้ลูกค้าองค์กรไทย — เราใช้ YAGNI เป็น guideline หลักทุกโปรเจกต์
ไม่ใช่เพราะแฟชั่น — แต่เพราะลูกค้าจ่ายเงินจริง และเราต้อง ส่งคุณค่าทุกบาท
Discovery Phase — ถาม "ต้องใช้เมื่อไหร่"
ก่อนเริ่มทุก feature เราถาม:
- ใครจะใช้ feature นี้?
- ใช้บ่อยแค่ไหน?
- ถ้าไม่มี feature นี้ user ทำงานต่อได้ไหม?
- มี alternative ที่ง่ายกว่าไหม?
ถ้าคำตอบกำกวม → defer ไม่ใส่ใน scope รอบนี้
Scope Negotiation — แยก "Must Have" จาก "Nice to Have"
ลูกค้าหลายรายส่ง requirement ที่มี 100+ ข้อ — บางข้อ "nice to have" ที่ทำให้ผ่านสบายๆ จะ delay timeline ไป 2-3 เดือน
หน้าที่เราในฐานะ consultant คือถามตรงๆ — "ข้อนี้ถ้ายังไม่มีในเดือนหน้า กระทบธุรกิจไหม"
ถ้าไม่กระทบ → ดันไป phase 2
Architecture Decisions — Start Simple, Refactor Later
โปรเจกต์ Odoo ส่วนใหญ่เริ่มจาก standard module + minimal customization
ไม่ build framework ตัวเอง ไม่ทำ abstraction layer ใหม่ ใช้ของ Odoo ตามที่มี
เมื่อ requirement พิเศษมาถึง → ค่อย extend อย่างมีหลัก ไม่ใช่ "preemptive flexibility"
Code Review — Challenge ทุก Abstraction
ใน review ถ้าเห็น interface, factory, manager, generic util — ถามทุกครั้ง
- มี implementation ที่ 2 ไหม?
- ถ้ายังไม่มี ตอนนี้จำเป็นต้องมี abstraction ไหม?
- ลบทิ้งได้ไหม?
หลายครั้งคำตอบคือ — ลบได้ → ลบ → code base เล็กลง → maintain ง่ายขึ้น
Documentation — เก็บ Decision Log
ทุกครั้งที่ ตัดสินใจไม่ทำอะไร — เราจดเหตุผล
"ไม่ใส่ multi-currency เพราะลูกค้ามีบริษัทเดียวในไทย — เมื่อมี subsidiary ต่างประเทศจะกลับมาทบทวน"
document นี้ทำให้:
- 6 เดือนข้างหน้า ทีมไม่งง ว่า "ทำไมไม่ใส่"
- เมื่อ requirement เปลี่ยน → กลับมาดู context ได้
- ลูกค้ามั่นใจว่าทีมคิด ไม่ใช่ลืม
กรณีศึกษา — เลือก "ไม่ทำ" ดีกว่า "เผื่อทำ"
(เราเปลี่ยนรายละเอียดและตัวเลขเล็กน้อยเพื่อปกป้องลูกค้า)
โปรเจกต์ ERP สำหรับธุรกิจ trading นำเข้าส่งออก scope เริ่มต้น 6 เดือน
ใน requirement document มีคำว่า "ในอนาคตอาจรองรับ" 14 ครั้ง
- ในอนาคตอาจรองรับหลาย currency
- ในอนาคตอาจมี subsidiary
- ในอนาคตอาจ integrate กับระบบบัญชี A, B, C
- ในอนาคตอาจรองรับการขายผ่าน marketplace
- ...
ทีมเก่าที่เคยเสนอ proposal → คิดว่า "ต้องเผื่อทุกอย่าง" → quote 14 เดือน, ราคา 3X
เราเสนอ approach ต่างกัน:
- phase 1 (4 เดือน) — ระบบที่ใช้งานวันนี้ได้จริง: single currency, single entity, integrate 1 ระบบบัญชีหลัก
- phase 2 (โต ตามความต้องการ) — extend เมื่อถึงเวลา based on actual data
ลูกค้าเลือก phase 1 → ภายใน 4 เดือน ระบบใช้งานจริง → กระแสเงินสดเข้า payback ได้เร็ว
หลังจากใช้งาน 8 เดือน:
- 3 ข้อจาก 14 ของ "ในอนาคตอาจรองรับ" → ต้องการจริง → ค่อยทำ phase 2
- 11 ข้อ → ไม่ได้ใช้, ไม่ต้องการ, หรือเปลี่ยน requirement ไปแล้ว
ถ้าเราทำตามที่ทีมเก่าเสนอ → 11 จาก 14 ฟีเจอร์ = wasted work = ลูกค้าจ่ายแพงกว่า 3X เพื่อสิ่งที่ไม่ได้ใช้
นี่คือ YAGNI ในธุรกิจจริง
YAGNI สำหรับ AI/LLM Era — สำคัญกว่าเดิม
ปี 2026 ทีมเขียน code ด้วย AI tool (Claude Code, Cursor, Codex) เร็วขึ้น 3-5 เท่า
แต่ "เร็ว" ไม่ได้แปลว่าควรเขียนเยอะ
AI ชอบสร้าง abstraction "เผื่อ" — เพราะ training data ของ AI = code ที่เขียนโดย engineer ทั่วโลกที่ over-engineer
ถ้าทีมไม่มี YAGNI discipline + ปล่อย AI เขียน → ได้ code base ที่ใหญ่ขึ้น 3-5 เท่า ในเวลาเท่าเดิม
cost of carry = mushroom
นี่คือเหตุผลที่ YAGNI ในยุค AI สำคัญกว่าเดิม — เพราะ economics ของการ "เผื่อเขียน" แทบจะ 0 (AI ทำให้) แต่ economics ของการ "เผื่อ maintain" สูงขึ้น (เพราะ code เยอะขึ้น)
ทีมที่ใช้ AI เก่ง = ทีมที่ใช้ AI เพื่อ เขียนสิ่งที่จำเป็น clean ที่สุด ไม่ใช่ทีมที่ใช้ AI เพื่อ เขียนเยอะที่สุด
สรุป — YAGNI เป็น Discipline ไม่ใช่ Tagline
YAGNI ไม่ใช่ excuse ที่จะขี้เกียจ ไม่ใช่ permission ที่จะไม่คิดล่วงหน้า
YAGNI = discipline ที่บังคับให้คุณ:
- พิสูจน์ความจำเป็นก่อนเขียน
- ตัด complexity ที่ไม่ pay off
- เก็บ codebase ให้เล็ก clean ง่าย maintain
- ส่งคุณค่าทุกบาทที่ลูกค้าจ่าย (หรือเวลาที่คุณลงทุน)
4 ต้นทุนของ Fowler:
- Build — เขียนไปแล้วไม่ได้ใช้
- Delay — เสียโอกาส ship ของจำเป็น
- Carry — แบกภาระทุกวัน
- Repair — ซ่อมตอนเวลามาถึง เพราะที่เผื่อไม่ตรง
หลีกเลี่ยงทั้ง 4 ได้ด้วยกฎเดียว — "You Aren't Gonna Need It"
ในยุค AI ที่ทุกคนเขียน code ได้เร็วขึ้น YAGNI สำคัญที่สุด — เพราะคนที่ "เผื่อเขียน" ได้ฟรี ก็จะเป็นคนที่ "เผื่อ maintain" แพงที่สุด
ที่ Enersys เราเลือก discipline นี้ทุกโปรเจกต์ — เพราะลูกค้าจ่ายค่าผลลัพธ์ ไม่ใช่ค่า abstraction ที่ดูเท่
แหล่งข้อมูล