Technology

agile scrum คือ

agile scrum คอ
agile scrum คือ | SiamCafe Blog
2025-10-28· อ. บอม — SiamCafe.net· 11,177 คำ

Agile และ Scrum Framework

Agile เป็นแนวทางพัฒนาซอฟต์แวร์ที่เน้นการส่งมอบงานเป็นรอบสั้นๆ ปรับเปลี่ยนได้ตาม Feedback Scrum เป็น Framework ที่นิยมที่สุดภายใต้ Agile แบ่งงานเป็น Sprint มี Roles, Events และ Artifacts ที่ชัดเจน

Agile Manifesto มี 4 ค่านิยมหลัก ให้ความสำคัญกับ Individuals and Interactions มากกว่า Processes, Working Software มากกว่า Documentation, Customer Collaboration มากกว่า Contract Negotiation และ Responding to Change มากกว่า Following a Plan

หัวข้อWaterfallAgile/Scrum
การวางแผนวางแผนทั้งหมดตั้งแต่ต้นวางแผนเป็นรอบ Sprint
การส่งมอบส่งมอบครั้งเดียวตอนจบส่งมอบทุก Sprint
การเปลี่ยนแปลงยากและแพงยินดีรับการเปลี่ยนแปลง
Feedbackได้ตอนจบ Projectได้ทุก Sprint
ความเสี่ยงรู้ตอนจบรู้เร็วแก้เร็ว
เหมาะกับRequirements ชัดเจนRequirements เปลี่ยนได้

Scrum Roles, Events และ Artifacts

# scrum_framework.py — Scrum Framework Implementation
from dataclasses import dataclass, field
from typing import List, Optional
from datetime import datetime, timedelta
from enum import Enum

class Priority(Enum):
    CRITICAL = 1
    HIGH = 2
    MEDIUM = 3
    LOW = 4

class Status(Enum):
    TODO = "To Do"
    IN_PROGRESS = "In Progress"
    IN_REVIEW = "In Review"
    DONE = "Done"

@dataclass
class UserStory:
    id: str
    title: str
    description: str
    acceptance_criteria: List[str]
    story_points: int
    priority: Priority
    status: Status = Status.TODO
    assignee: str = ""
    sprint: Optional[str] = None

@dataclass
class Sprint:
    name: str
    goal: str
    start_date: datetime
    duration_weeks: int = 2
    stories: List[UserStory] = field(default_factory=list)
    velocity: int = 0

    @property
    def end_date(self):
        return self.start_date + timedelta(weeks=self.duration_weeks)

    @property
    def total_points(self):
        return sum(s.story_points for s in self.stories)

    @property
    def completed_points(self):
        return sum(s.story_points for s in self.stories if s.status == Status.DONE)

    @property
    def progress_pct(self):
        if self.total_points == 0:
            return 0
        return self.completed_points / self.total_points * 100

@dataclass
class ProductBacklog:
    items: List[UserStory] = field(default_factory=list)

    def add(self, story: UserStory):
        self.items.append(story)
        self.items.sort(key=lambda s: s.priority.value)

    def top(self, n=10):
        return [s for s in self.items if s.status == Status.TODO][:n]

class ScrumBoard:
    """Scrum Board สำหรับจัดการ Sprint"""

    def __init__(self, team_name: str, velocity: int = 30):
        self.team_name = team_name
        self.avg_velocity = velocity
        self.backlog = ProductBacklog()
        self.sprints: List[Sprint] = []
        self.current_sprint: Optional[Sprint] = None

    def create_story(self, title, description, criteria, points, priority):
        story_id = f"US-{len(self.backlog.items)+1:04d}"
        story = UserStory(
            id=story_id, title=title, description=description,
            acceptance_criteria=criteria, story_points=points,
            priority=priority,
        )
        self.backlog.add(story)
        return story

    def sprint_planning(self, sprint_name, goal, start_date):
        """Sprint Planning — เลือก Stories สำหรับ Sprint"""
        sprint = Sprint(name=sprint_name, goal=goal, start_date=start_date)
        remaining = self.avg_velocity

        for story in self.backlog.top(20):
            if story.story_points <= remaining:
                story.sprint = sprint_name
                story.status = Status.TODO
                sprint.stories.append(story)
                remaining -= story.story_points

        self.current_sprint = sprint
        self.sprints.append(sprint)

        print(f"\n{'='*55}")
        print(f"Sprint Planning: {sprint_name}")
        print(f"  Goal: {goal}")
        print(f"  Duration: {sprint.start_date.strftime('%Y-%m-%d')} to {sprint.end_date.strftime('%Y-%m-%d')}")
        print(f"  Stories: {len(sprint.stories)} ({sprint.total_points} points)")
        print(f"  Capacity: {self.avg_velocity} points")
        print(f"{'='*55}")

        for story in sprint.stories:
            print(f"  [{story.id}] {story.title} ({story.story_points} pts) — {story.priority.name}")

    def daily_scrum(self):
        """Daily Scrum — สรุปสถานะรายวัน"""
        if not self.current_sprint:
            return

        sprint = self.current_sprint
        print(f"\n  Daily Scrum — {sprint.name}")
        print(f"  Progress: {sprint.progress_pct:.0f}% ({sprint.completed_points}/{sprint.total_points} pts)")

        for status in Status:
            stories = [s for s in sprint.stories if s.status == status]
            if stories:
                print(f"\n    [{status.value}]")
                for s in stories:
                    assignee = f" @{s.assignee}" if s.assignee else ""
                    print(f"      {s.id}: {s.title}{assignee}")

    def sprint_review(self):
        """Sprint Review — Demo และ Review"""
        if not self.current_sprint:
            return

        sprint = self.current_sprint
        done = [s for s in sprint.stories if s.status == Status.DONE]
        not_done = [s for s in sprint.stories if s.status != Status.DONE]

        print(f"\n{'='*55}")
        print(f"Sprint Review: {sprint.name}")
        print(f"  Goal: {sprint.goal}")
        print(f"  Velocity: {sprint.completed_points} points")
        print(f"  Completed: {len(done)}/{len(sprint.stories)} stories")
        print(f"{'='*55}")

        if done:
            print(f"\n  Completed:")
            for s in done:
                print(f"    [DONE] {s.id}: {s.title}")
        if not_done:
            print(f"\n  Not Completed (carry over):")
            for s in not_done:
                print(f"    [{s.status.value}] {s.id}: {s.title}")

    def retrospective(self):
        """Sprint Retrospective"""
        print(f"\n{'='*55}")
        print(f"Sprint Retrospective")
        print(f"{'='*55}")
        print(f"  What went well?")
        print(f"    - ทีมส่งมอบตาม Sprint Goal")
        print(f"    - Code Review ดีขึ้น")
        print(f"  What could improve?")
        print(f"    - Estimation ยังไม่แม่นยำ")
        print(f"    - Technical Debt สะสม")
        print(f"  Action Items:")
        print(f"    [ ] ปรับ Estimation ใช้ Planning Poker")
        print(f"    [ ] จัดสรรเวลา 20% สำหรับ Tech Debt")

# ตัวอย่าง
board = ScrumBoard("Team Alpha", velocity=30)

# สร้าง User Stories
board.create_story("User Login", "ผู้ใช้สามารถ Login ด้วย Email/Password",
    ["Login สำเร็จแสดง Dashboard", "Login ผิดแสดง Error"], 5, Priority.HIGH)
board.create_story("User Registration", "ผู้ใช้สามารถสมัครสมาชิก",
    ["กรอก Email, Password, Name", "ส่ง Verification Email"], 8, Priority.HIGH)
board.create_story("Dashboard", "แสดง Dashboard หลัง Login",
    ["แสดง Summary", "แสดง Recent Activity"], 5, Priority.MEDIUM)
board.create_story("Profile Settings", "ผู้ใช้แก้ไข Profile ได้",
    ["เปลี่ยนชื่อ", "เปลี่ยนรูป"], 3, Priority.LOW)

# Sprint Planning
board.sprint_planning("Sprint 1", "User Authentication", datetime(2024, 1, 15))
board.daily_scrum()

Agile Metrics และ Reporting

# agile_metrics.py — Agile Metrics Dashboard

class AgileMetrics:
    """คำนวณ Agile Metrics"""

    def __init__(self, sprints):
        self.sprints = sprints

    def velocity_chart(self):
        """Velocity Chart"""
        print(f"\nVelocity Chart")
        print(f"{'─'*40}")

        velocities = []
        for sprint in self.sprints:
            vel = sprint.completed_points
            velocities.append(vel)
            bar = "█" * (vel // 2)
            print(f"  {sprint.name:<12} {bar} {vel} pts")

        if velocities:
            avg = sum(velocities) / len(velocities)
            print(f"\n  Average Velocity: {avg:.0f} points/sprint")
            print(f"  Trend: {'↑' if velocities[-1] > avg else '↓'}")

    def burndown(self, sprint):
        """Sprint Burndown"""
        total = sprint.total_points
        remaining = total - sprint.completed_points
        days = sprint.duration_weeks * 5  # working days

        print(f"\nBurndown: {sprint.name}")
        print(f"  Total: {total} pts | Remaining: {remaining} pts")
        print(f"  Ideal: {total/days:.1f} pts/day")

        # Simulate burndown
        ideal_per_day = total / days
        for day in range(days + 1):
            ideal = max(0, total - ideal_per_day * day)
            actual = max(0, remaining * (days - day) / days)
            bar_ideal = "·" * int(ideal / 2)
            bar_actual = "█" * int(actual / 2)
            if day % 2 == 0:
                print(f"  Day {day:>2}: {bar_actual}")

    def cumulative_flow(self):
        """Cumulative Flow Diagram"""
        print(f"\nCumulative Flow")
        for sprint in self.sprints:
            done = sum(1 for s in sprint.stories if s.status == Status.DONE)
            ip = sum(1 for s in sprint.stories if s.status == Status.IN_PROGRESS)
            todo = sum(1 for s in sprint.stories if s.status == Status.TODO)
            print(f"  {sprint.name}: Done={done} InProgress={ip} ToDo={todo}")

    def team_health(self):
        """Team Health Metrics"""
        if not self.sprints:
            return

        last = self.sprints[-1]
        commitment = last.total_points
        delivered = last.completed_points
        ratio = delivered / commitment * 100 if commitment > 0 else 0

        print(f"\nTeam Health")
        print(f"  Commitment: {commitment} pts")
        print(f"  Delivered: {delivered} pts")
        print(f"  Delivery Ratio: {ratio:.0f}%")
        print(f"  Sprint Goal: {'Achieved' if ratio >= 80 else 'Not Achieved'}")

        health_indicators = [
            ("Sprint Goal Achievement", ratio >= 80),
            ("Velocity Stable", True),
            ("Team Morale", True),
            ("Technical Debt Manageable", True),
            ("Stakeholder Satisfied", ratio >= 70),
        ]

        print(f"\n  Health Check:")
        for indicator, healthy in health_indicators:
            status = "✓" if healthy else "✗"
            print(f"    [{status}] {indicator}")

# ตัวอย่าง Sprint Data
sprint1 = Sprint("Sprint 1", "Auth", datetime(2024, 1, 15))
sprint1.stories = [
    UserStory("US-1", "Login", "", [], 5, Priority.HIGH, Status.DONE),
    UserStory("US-2", "Register", "", [], 8, Priority.HIGH, Status.DONE),
    UserStory("US-3", "Dashboard", "", [], 5, Priority.MEDIUM, Status.DONE),
]

sprint2 = Sprint("Sprint 2", "Profile", datetime(2024, 1, 29))
sprint2.stories = [
    UserStory("US-4", "Profile", "", [], 3, Priority.LOW, Status.DONE),
    UserStory("US-5", "Settings", "", [], 5, Priority.MEDIUM, Status.DONE),
    UserStory("US-6", "Notifications", "", [], 8, Priority.HIGH, Status.IN_PROGRESS),
]

metrics = AgileMetrics([sprint1, sprint2])
metrics.velocity_chart()
metrics.team_health()

Scrum Tools Comparison

# scrum_tools.py — เปรียบเทียบ Scrum Tools

tools = [
    {
        "name": "Jira",
        "company": "Atlassian",
        "price": "ฟรี 10 users, $7.75/user/mo",
        "pros": ["Features ครบที่สุด", "Integrations มากมาย", "Custom Workflows"],
        "cons": ["ซับซ้อน", "ช้าบางครั้ง", "แพง"],
        "best_for": "Enterprise, ทีมใหญ่",
    },
    {
        "name": "Linear",
        "company": "Linear",
        "price": "ฟรี 250 issues, $8/user/mo",
        "pros": ["UI สวยเร็ว", "Keyboard Shortcuts", "GitHub Integration ดีเยี่ยม"],
        "cons": ["Features น้อยกว่า Jira", "ไม่มี Time Tracking"],
        "best_for": "Startup, ทีม Dev",
    },
    {
        "name": "Notion",
        "company": "Notion",
        "price": "ฟรี, $8/user/mo",
        "pros": ["ยืดหยุ่นมาก", "Docs + Tasks ที่เดียว", "Template เยอะ"],
        "cons": ["ไม่ได้ออกแบบเฉพาะ Scrum", "ช้าเมื่อข้อมูลเยอะ"],
        "best_for": "ทีมเล็ก, Non-tech Teams",
    },
    {
        "name": "GitHub Projects",
        "company": "GitHub",
        "price": "ฟรี",
        "pros": ["อยู่กับ Code เลย", "ฟรี", "Automation ง่าย"],
        "cons": ["Features จำกัด", "ไม่มี Burndown Chart"],
        "best_for": "Open Source, ทีม Dev เล็ก",
    },
]

print("Scrum Tools Comparison")
print("=" * 55)

for tool in tools:
    print(f"\n  {tool['name']} ({tool['company']})")
    print(f"    Price: {tool['price']}")
    print(f"    Best for: {tool['best_for']}")
    print(f"    Pros: {', '.join(tool['pros'])}")
    print(f"    Cons: {', '.join(tool['cons'])}")

เคล็ดลับ

Agile คืออะไร

แนวทางพัฒนาซอฟต์แวร์เน้นส่งมอบงานรอบสั้นๆ ปรับเปลี่ยนตาม Feedback Individuals and Interactions Working Software Customer Collaboration Responding to Change ตาม Agile Manifesto

Scrum คืออะไร

Framework ภายใต้ Agile แบ่งงานเป็น Sprint 1-4 สัปดาห์ มี 3 Roles (PO SM Dev) 5 Events (Planning Daily Review Retro Sprint) 3 Artifacts (Product Backlog Sprint Backlog Increment)

Scrum Master ทำหน้าที่อะไร

Servant Leader ดูแลทีมตาม Scrum Framework ขจัดอุปสรรค Facilitate Events Coach Agile Practices ปกป้องทีมจากรบกวนภายนอก ไม่ใช่ Project Manager

Sprint Planning ทำอย่างไร

Meeting ตอนเริ่ม Sprint เลือก Backlog Items กำหนด Sprint Goal Break Down เป็น Tasks Estimate ด้วย Story Points ใช้เวลาไม่เกิน 8 ชั่วโมงสำหรับ Sprint 4 สัปดาห์

สรุป

Agile Scrum เป็น Framework ที่ช่วยทีมพัฒนาซอฟต์แวร์ส่งมอบงานเร็วขึ้นและมีคุณภาพ แบ่งงานเป็น Sprint มี Sprint Goal ชัดเจน ทำ Daily Scrum ทุกวัน Sprint Review Demo ให้ Stakeholders Sprint Retrospective ปรับปรุงกระบวนการ ใช้ Velocity วัด Performance Burndown Chart ติดตาม Progress

📖 บทความที่เกี่ยวข้อง

GCP Cloud Spanner Agile Scrum Kanbanอ่านบทความ → Kotlin Coroutines Agile Scrum Kanbanอ่านบทความ → Kubernetes Pod Security Agile Scrum Kanbanอ่านบทความ → Kubernetes Operator Agile Scrum Kanbanอ่านบทความ → Kubernetes Network Policy Agile Scrum Kanbanอ่านบทความ →

📚 ดูบทความทั้งหมด →