Quest 28 - Sprint Planner
Quest 28: Sprint Planner
hard 30 minutes🎯 Learning Objectives
- Breaking large features into small, estimable sprint tasks
- Estimating task complexity and comparing against team capacity
- Understanding when features don't fit in a sprint and need splitting
- The engineering habit: Decompose Work — large features must be broken into small tasks
📖 Concept: Sprint Planning — แบ่งศึกให้เล็กพอที่จะชนะได้
Sprint Planning คือการ แบ่ง features ขนาดใหญ่ให้เป็น tasks ขนาดเล็ก ที่สามารถทำเสร็จได้ใน 1 sprint (ปกติ 1-2 สัปดาห์) — เหมือนนักรบที่แบ่งศึกออกเป็นกลยุทธ์ย่อยๆ แทนที่จะเข้าปะทะตรงๆ
ทำไมต้อง decompose? เพราะ feature ขนาดใหญ่ที่ไม่ได้แบ่ง = ไม่มีวันเสร็จ — ทีมจะรู้สึกว่าไม่มีความคืบหน้าและท้อไปในที่สุด
Sprint Planner ต้องคิดถึง 2 สิ่งพร้อมกัน:
| Concept | คำถามที่ตอบ |
|---|---|
| Tasks | feature นี้แบ่งเป็นกี่ sub-tasks? แต่ละตัวใช้เวลากี่ชั่วโมง? |
| Capacity | ทีมมี capacity กี่ชั่วโมงต่อ sprint? แล้ว fit ไหม? |
⚙️ How It Works
Sprint Planning Workflow
1. รับ feature list พร้อม priority และ complexity ↓2. แบ่งแต่ละ feature เป็น sub-tasks ↓3. ประมาณการเวลา (estimate) แต่ละ task ↓4. บวกรวม (totalEstimate) เทียบกับ teamCapacity ↓5. ตัดสินใจว่า fitsInSprint หรือไม่Estimation Rules
Rule 1: ทุก task ต้องมี estimate > 0
// ❌ Bad: task ไม่มี estimate{ name: 'Build login', estimate: 0 }
// ✅ Good: task มี estimate ชัดเจน{ name: 'Build login form UI', estimate: 4 }Rule 2: totalEstimate ต้องเท่ากับผลรวมของ tasks
// ❌ Bad: totalEstimate ไม่ตรงtasks = [{ estimate: 4 }, { estimate: 6 }]; // total = 10totalEstimate = 8; // ผิด!
// ✅ Good: totalEstimate ตรงtasks = [{ estimate: 4 }, { estimate: 6 }]; // total = 10totalEstimate = 10; // ถูก!Rule 3: fitsInSprint ต้องเทียบกับ capacity จริง
// ❌ Bad: totalEstimate = 40 ชั่วโมง แต่ capacity = 20fitsInSprint = true; // ผิด!
// ✅ Good: totalEstimate = 40 ชั่วโมง, capacity = 20fitsInSprint = false; // ถูก!💡 Example: The Right Way
Step 1: รับ features
const features = [ { name: 'User Auth', priority: 'high', complexity: 'medium' }, { name: 'Dashboard', priority: 'medium', complexity: 'high' }];const teamCapacity = 20; // 20 ชั่วโมงต่อ sprintStep 2: แบ่งเป็น sub-tasks พร้อม estimate
function planSprint(features, teamCapacity) { const tasks = [];
for (const feature of features) { // แบ่ง feature เป็น sub-tasks ตาม complexity if (feature.complexity === 'medium') { tasks.push( { name: `${feature.name} - Design`, estimate: 4, priority: feature.priority }, { name: `${feature.name} - Implement`, estimate: 8, priority: feature.priority }, { name: `${feature.name} - Test`, estimate: 4, priority: feature.priority } ); } else if (feature.complexity === 'high') { tasks.push( { name: `${feature.name} - Research`, estimate: 4, priority: feature.priority }, { name: `${feature.name} - Design`, estimate: 6, priority: feature.priority }, { name: `${feature.name} - Implement`, estimate: 12, priority: feature.priority }, { name: `${feature.name} - Test`, estimate: 6, priority: feature.priority } ); } }
const totalEstimate = tasks.reduce((sum, t) => sum + t.estimate, 0); const fitsInSprint = totalEstimate <= teamCapacity;
return { tasks, totalEstimate, fitsInSprint };}Step 3: Run tests
node test.jsStep 4: ตรวจสอบ — totalEstimate (40) > teamCapacity (20) → fitsInSprint ต้องเป็น false
⚠️ Common Mistakes
Mistake 1: คืน totalEstimate ไม่ตรงกับผลรวม tasks
“ประมาณไว้ 20 ชั่วโมง แต่รวม tasks ได้ 40” → Test จะ fail เพราะ
totalEstimate === tasks.reduce(...)
Mistake 2: ไม่คิดถึง team capacity
“ทำได้ทุกอย่าง ไม่ต้องดู capacity” → ถ้า totalEstimate > teamCapacity →
fitsInSprintต้องเป็นfalse
Mistake 3: task ไม่มี estimate
“เดี๋ยวค่อยประมาณทีหลัง” → ทุก task ต้องมี estimate > 0 — ไม่งั้นคำนวณ total ไม่ได้
Mistake 4: แบ่ง task ใหญ่เกินไป
“Feature 1: Build entire auth system — 20 ชั่วโมง” → Task ขนาดใหญ่ควรแบ่งเป็น sub-tasks เล็กๆ เช่น Design, Implement, Test
📝 Knowledge Check
📝 Knowledge Check
Q1:Sprint Planning คืออะไร?
Q2:เพราะอะไร `totalEstimate` ต้องเท่ากับผลรวมของ tasks เท่านั้น?
Q3:เมื่อ totalEstimate > teamCapacity ควรทำอย่างไร?
🏋️ Quest: Sprint Planner
ตอนนี้ถึงเวลาฝึกฝน! แบ่ง features เป็น sprint tasks พร้อมประมาณการเวลา
-
Download ไฟล์เริ่มต้นของ quest:
Terminal window npx bluebeltdojo download quest-28-sprint-plannercd quest-28-sprint-planner -
เปิด
problem.jsใน editor ของคุณพร้อม AI tool (Copilot, Claude Code, Cursor ฯลฯ) -
ดู instructions ใน
problem.js— implementplanSprint(features, teamCapacity)ที่แบ่ง features เป็น tasks พร้อม estimate -
สำคัญ: Run
node test.jsและอ่าน failure messages ให้ละเอียด — ตรวจสอบว่า totalEstimate ตรงกับผลรวม -
แก้ไข edge cases ที่ AI พลาด
-
ตรวจสอบว่า test ผ่านทั้งหมด:
Terminal window node test.js -
เมื่อ test ผ่านทั้งหมด ส่งคำตอบ:
Terminal window npx bluebeltdojo submit
💡 Tip: Feature ที่ไม่ fit ใน sprint = ต้องแบ่งต่อ ไม่ใช่บีบเข้าไป — การบีบ lead ไปสู่ quality issues
คำใบ้
- อ่าน instructions ใน
problem.jsอย่างละเอียด - สำคัญ:
totalEstimateต้องเท่ากับtasks.reduce((s, t) => s + t.estimate, 0)เป๊ะๆ - ทุก task ต้องมี
estimate > 0 - ตรวจสอบ
fitsInSprintเทียบกับteamCapacityจริง - ถ้าติดขัด ลองอ่าน “Common Mistakes” อีกครั้ง — อย่าดู solution โดยตรง