สัญชาตญาณเมื่อเจอฟีเจอร์ซับซ้อนคือ "ลองดูก่อน" — แต่การตัดสินใจเชิงสถาปัตยกรรมซ่อนอยู่ใน model ที่ 3, edge case ที่ 5 คุณค่าแท้จริงของ plan mode คือย้ายบทสนทนาระดับสถาปัตยกรรมไปที่ข้อความก่อนเขียนโค้ด เคสจริง: ระบบคณะลูกขุนชุมชนของ Pickful — 3,032 บรรทัด, 119 spec เขียวหมด, commit เดียว, ศูนย์ครั้งที่ต้องทำสถาปัตยกรรมใหม่หลังจากนั้น
เจอฟีเจอร์ซับซ้อน สัญชาตญาณของคนส่วนใหญ่คือ "ลองเขียนอะไรดูก่อน"
ปัญหาคือ ระบบซับซ้อนมีคุณสมบัติอย่างหนึ่ง—การตัดสินใจเชิงสถาปัตยกรรมซ่อนอยู่ในโมเดลที่ 3, edge case ที่ 5, กฎคะแนนที่ 8 การดำดิ่งลงไปในโค้ดแล้วไปสะดุดกับการตัดสินใจเหล่านั้นกลางทาง แล้วถอยกลับมาแก้ จะแพงกว่าการคุยให้จบในระดับข้อความตั้งแต่ต้น 10 เท่า
ผมใช้ plan mode ของ Claude Code สร้าง TopicReview ระบบคณะลูกขุนชุมชนใน Pickful และได้เห็นเวอร์ชันสุดโต่งของอสมการนี้: หนึ่ง commit, 3,032 บรรทัด, spec 119 ตัวเขียวหมด, ส่งขึ้นใช้งานครั้งเดียวจบ commit สิบกว่าตัวที่ตามมาไม่มีสักตัวที่เป็นการรื้อสถาปัตยกรรมใหม่—ทั้งหมดเป็นการจูนพารามิเตอร์, ขัด UI, ปะแปะ edge case ระบบนี้ทำงานได้มั่นคงมาตลอด และตอนนี้เป็นหัวใจของวิธีที่ชุมชนดูแลตัวเอง
บทความนี้พูดถึงว่าทำไมฟีเจอร์ซับซ้อนต้องใช้ plan mode ก่อน, ช่วง plan ทำอะไรจริง ๆ, และต้องคุยกันถึงระดับไหนจึงจะเริ่มเขียนโค้ดได้
TopicReview คือการโหวตของชุมชนเพื่อตัดสินว่าโพสต์คุณภาพต่ำควรถูกลบหรือไม่ ประโยคเดียวก็จบ—แต่สเปกแผ่ออกเป็นชั้น ๆ:
แก่นของความซับซ้อนไม่ได้อยู่ในกฎใดเดี่ยว ๆ—มันอยู่ที่ กฎโต้ตอบกันอย่างไร ทุกกฎที่เพิ่มเข้ามาอาจ trigger rollback ที่อื่น
เวลาเขียนรวดเดียว ปัญหาที่ยากที่สุดไม่ใช่ข้อเท็จจริงที่เห็น—มันคือคำถามที่คุณไม่ได้คิดจะถาม อ่านโค้ด TopicReview ย้อนกลับ จะเห็นอย่างน้อยสี่กำแพงที่คุณจะชนแน่หากข้าม plan ไป:
กฎคุณสมบัติของลูกขุน. ดูผิวเผินก็แค่ User.jurors_and_judges.sample(12) แต่กฎจริงคือ: กันผู้เขียนโพสต์, กันผู้ที่รายงานโพสต์, กันผู้ที่โหวตในรอบต้นแล้ว (เพื่อคนเดิมจะไม่โหวตในชั้นอุทธรณ์ด้วย) การกันสามชั้นซ้อน เขียน model รวดเดียว มักจะหายไปหนึ่งหรือสองข้อ
การจ่ายคะแนนเลื่อน. คำตัดสิน remove ปกติจะทริกเกอร์การจ่ายคะแนนให้ลูกขุน แต่การอุทธรณ์อาจพลิก remove ได้—เมื่อพลิก ลูกขุนที่โหวตตามคำตัดสินเก่าจะไปอยู่ฝั่งที่ผิด ต้องคำนวณการจ่ายใหม่ตามคำตัดสินใหม่ ดังนั้นคำตัดสิน remove ต้อง รอให้หน้าต่างอุทธรณ์ 24 ชม. ปิดก่อน จึงจะจ่ายลูกขุน ถ้าข้ามการเขียนกฎนี้ จ่ายไปก่อน จะไปคว้าคะแนนกลับคืน—ยุ่งกว่าการจ่ายช้า 10 เท่า
การออกแบบ interface ของ job ที่กำหนดเวลา. CloseTopicReviewJob ดูเหมือนแค่ "ปิด review" แต่จริง ๆ แล้วจัดการสามสถานการณ์:
# หน้าต่างโหวตชั้นต้นหมดเวลา
CloseTopicReviewJob.set(wait_until: voting_ends_at).perform_later(review.id)
# จ่ายลูกขุนเลื่อนหลังคำตัดสิน remove
CloseTopicReviewJob.set(wait: 24.hours).perform_later(review.id, award_juror_points: true)
# หน้าต่างอุทธรณ์หมดเวลา
CloseTopicReviewJob.set(wait: 24.hours).perform_later(review.id, appeal_id: appeal.id)
ไม่วางแผนก่อน จะเขียน signature แรก แล้วพอถึงกรณีที่สองพบว่าต้องออกแบบ interface ใหม่ทั้งหมด
กำแพงที่แพงที่สุด: ช่วงลบชั่วคราวอุทธรณ์ได้ไหม? เมื่อโหวต remove ข้ามเกณฑ์ โพสต์ถูกซ่อนทันที (ชั่วคราว) แต่ review ทั้งหมดยังอยู่ในสถานะ voting—ยังไม่ decided ผู้ใช้อุทธรณ์ได้เลยหรือไม่?
decided กับ appealedการตัดสินใจนี้ครั้งเดียวแผ่กลับไปกระทบการตรวจสอบพารามิเตอร์ใน open_appeal! และตรรกะของ state machine การตัดสินใจกลางทาง = เขียนระบบใหม่ครึ่งระบบ
plan mode ของ Claude Code คือโหมดที่ ห้ามเขียนโค้ด—Claude อ่าน repo ได้ คิดวิธีได้ คุยกับคุณได้ แต่การแก้ไขไฟล์ใด ๆ จะถูก hard-block จนกว่าคุณจะอนุมัติ plan
ข้อจำกัดเชิงกลไกนั้นคือแก่น: มัน บังคับให้บทสนทนาระดับสถาปัตยกรรมเกิดขึ้นในตัวอักษร
สิ่งที่ช่วง plan ทำจริงในทางปฏิบัติ:
1. วาด state machine และบทบาท 5 สถานะ, 4 บทบาท (ลูกขุน / judge / ผู้เขียนโพสต์ / ผู้รายงาน), แต่ละบทบาททำและไม่ทำอะไรในแต่ละสถานะ—ทั้งหมดอยู่ใน markdown ไม่กี่บรรทัด ไม่กี่บรรทัด vs หลายสิบไฟล์ ต้นทุนการแก้ต่างกันสองลำดับความสูง
2. Walkthrough flow ของแต่ละบทบาท:
จุดที่การเดินสะดุด จะมีคำถามซ่อนอยู่โผล่ขึ้นมา: "ลูกขุนเห็นโหวตของลูกขุนคนอื่นได้ไหม?", "ผู้เขียนทำอะไรได้ในช่วงลบชั่วคราว?"
3. สอบสวน edge case ช่วง plan ไม่ใช่ออกแบบ "เส้นทางปกติ"—แต่จงใจถามคำถามที่ปกติไม่ได้นึกถึง:
finalize พร้อมกัน race จะจ่ายซ้ำไหม? (เพิ่มฟิลด์ juror_points_awarded ให้ idempotent)คำถามเหล่านี้ 95% ไม่ขึ้นมาตามธรรมชาติระหว่างเขียนโค้ด ช่วง plan บังคับให้คุณตอบทีละข้อ
4. บัญชีคะแนน ระบบคะแนนซับซ้อนจนคุยอย่างเดียวไม่พอ—ต้อง วาดตารางจริง ๆ: แต่ละการไหลของคะแนนพร้อมเงื่อนไข trigger + จำนวน + เส้นทาง rollback เมื่อบัญชีลงตัว ทุก edge case (คืนค่าปรับชั่วคราว, คืนอุทธรณ์, bonus) เข้ากันได้หมด
เกณฑ์แข็ง:
closed (keep / remove / warn × มี / ไม่มีอุทธรณ์ × ชั่วคราว / ไม่ชั่วคราว)—เล่าได้ตั้งแต่ต้นจนจบพอถึงเกณฑ์นี้ การเขียนโค้ดกลายเป็นการแปล plan เป็น Ruby
การ ship ครั้งแรกของระบบนี้:
d162f1e Add community moderation system with jury/judge review and appeals
63 files changed, 3032 insertions(+)
119 specs, 0 failures
63 ไฟล์, 3,032 บรรทัด, spec 119 ตัวเขียวหมด ส่งขึ้นใช้งานครั้งเดียวจบ
commit สิบกว่าตัวที่ตามมายืนยันว่าสถาปัตยกรรมยืนหยัด:
Apply legacy penalty (1pt) for posts created before 2026-03-26
Fix topic review appeal bugs: window mismatch and verdict not updated
Add topic_removed status for posts removed by community review
Default to keep verdict when review expires with zero votes
Reduce provisional removal penalty to 1pt during trial period
Allow topic creator to withdraw active reviews
Add handled tab to jury dashboard, fix tabs styling
แต่ละอันคือ tune / fix / polish / ฟีเจอร์เล็ก ไม่มีอันไหนเป็น "กลับไปออกแบบ state machine ใหม่" หรือ "ต้องเปลี่ยนโมเดลคะแนน" โครงกระดูกถูกต้องหมด
นี่คือผลตอบแทนจริงของ plan: การ execute ไม่ถูกขัดจังหวะ ไม่มี "เดี๋ยว เส้นนี้จัดการยังไง"—plan เขียนไว้แล้ว ไม่มี "ไม่ได้คิดถึง edge case นี้"—ช่วง plan ถามแล้ว ไม่มี "interface นี้ต้องออกแบบใหม่"—plan จัดไว้เรียบร้อย
หลายชั่วโมงเขียนโค้ด ทำอย่างเดียว: แปลดีไซน์ที่ชัดเจนลงคีย์บอร์ด
ไม่ใช่ทุกงานคุ้มกับ plan:
ผลกำไรของ plan mode มาจาก การลดต้นทุนการเขียนใหม่ ถ้างานไม่มีความเสี่ยงเขียนใหม่ plan เป็นเพียงค่าโสหุ้ย
"คิดก่อนทำ" ฟังเหมือนคำแนะนำเรื่องนิสัย plan mode ไม่ใช่แบบนั้น
plan mode คือทำให้ บทสนทนาระดับสถาปัตยกรรม เกิดขึ้นในที่ที่ 10 คำเปลี่ยนได้—ไม่ใช่ในที่ที่ต้องเปลี่ยน 30 ไฟล์
ภายใต้ความซับซ้อน ต้องกลับด้านคำคมเก่าของวงการ "words are cheap, code is expensive"—มันไม่ได้หมายความว่า "เขียนโค้ดก่อนแล้วค่อยดู" (นั่นใช้ได้เมื่อส่วนต่างต้นทุนเล็ก) แต่หมายถึงใช้ประโยชน์จากส่วนต่างต้นทุน: ยกบทสนทนาที่แพงไปข้างหน้า ในสื่อที่ถูก
3,000 บรรทัดใน commit เดียวรู้สึกยอดเยี่ยม ไม่ใช่เพราะผมเขียนเร็ว—แต่เพราะ plan เปลี่ยน "การเขียน" ให้เป็นการกระทำเชิงกลไกล้วน ๆ