ระบบ Kanban คืออะไร — คู่มือการจัดการงานฉบับสมบูรณ์
Kanban เป็นระบบจัดการงานที่พัฒนาโดย Toyota ในทศวรรษ 1940 เพื่อควบคุม production flow ในโรงงาน ปัจจุบันถูกนำมาใช้อย่างแพร่หลายในการพัฒนาซอฟต์แวร์ การจัดการโปรเจกต์ และทุกอุตสาหกรรม หลักการคือ visualize งานบน board แบ่งเป็น columns ตามสถานะ (To Do, In Progress, Done) จำกัดจำนวนงานที่ทำพร้อมกัน (WIP Limit) เพื่อลด bottleneck และเพิ่ม flow efficiency บทความนี้อธิบายหลักการ Kanban ทั้งหมด พร้อม Python tools สำหรับสร้างระบบ Kanban
Kanban Principles
# kanban_principles.py — Kanban core principles
import json
class KanbanPrinciples:
CORE_PRACTICES = {
"visualize": {
"name": "1. Visualize Workflow",
"description": "แสดงงานทั้งหมดบน board — เห็นภาพรวม สถานะ และ bottleneck",
"how": "ใช้ board แบ่ง columns: Backlog → To Do → In Progress → Review → Done",
},
"wip_limit": {
"name": "2. Limit Work in Progress (WIP)",
"description": "จำกัดจำนวนงานที่ทำพร้อมกันในแต่ละ column",
"how": "เช่น In Progress: max 3 cards — ห้ามเริ่มงานใหม่จนกว่าจะเสร็จงานเดิม",
"benefit": "ลด context switching, เพิ่ม focus, หา bottleneck เร็ว",
},
"manage_flow": {
"name": "3. Manage Flow",
"description": "ติดตามและปรับปรุง flow ของงาน — ลดเวลาที่งานค้าง",
"metrics": "Lead Time, Cycle Time, Throughput, WIP",
},
"explicit_policies": {
"name": "4. Make Policies Explicit",
"description": "กำหนดกฎชัดเจน — Definition of Done, priority rules, WIP limits",
},
"feedback_loops": {
"name": "5. Implement Feedback Loops",
"description": "ประชุม standup, review, retrospective — ปรับปรุงอย่างต่อเนื่อง",
},
"improve": {
"name": "6. Improve Collaboratively, Evolve Experimentally",
"description": "ปรับปรุงทีละเล็ก — ทดลอง measure ผล แล้วตัดสินใจ",
},
}
def show_practices(self):
print("=== Kanban Core Practices ===\n")
for key, p in self.CORE_PRACTICES.items():
print(f"[{p['name']}]")
print(f" {p['description']}")
if 'how' in p:
print(f" How: {p['how']}")
print()
principles = KanbanPrinciples()
principles.show_practices()
Kanban Board Design
# board.py — Kanban board design
import json
class KanbanBoard:
COLUMNS = {
"backlog": {"name": "Backlog", "wip": None, "description": "งานทั้งหมดที่รอ — ยังไม่ prioritize"},
"ready": {"name": "Ready (To Do)", "wip": 5, "description": "งานที่ prioritize แล้ว พร้อมเริ่ม"},
"in_progress": {"name": "In Progress", "wip": 3, "description": "กำลังทำอยู่ — จำกัด 3 งาน"},
"review": {"name": "Review/QA", "wip": 2, "description": "รอ review หรือทดสอบ"},
"done": {"name": "Done", "wip": None, "description": "เสร็จสมบูรณ์"},
}
CARD_TEMPLATE = {
"title": "ชื่องาน",
"description": "รายละเอียด",
"assignee": "ผู้รับผิดชอบ",
"priority": "High / Medium / Low",
"due_date": "กำหนดส่ง",
"tags": "Labels / Categories",
"blocked_by": "ติดปัญหาอะไร (ถ้ามี)",
}
BOARD_TYPES = {
"basic": {
"name": "Basic Board",
"columns": "To Do → In Progress → Done",
"best_for": "ทีมเล็ก, งานง่ายๆ, เริ่มต้นใช้ Kanban",
},
"dev": {
"name": "Software Development Board",
"columns": "Backlog → Ready → Dev → Code Review → QA → Staging → Done",
"best_for": "ทีม development",
},
"support": {
"name": "Support / IT Board",
"columns": "New Tickets → Triaged → In Progress → Waiting → Resolved → Closed",
"best_for": "IT support, customer service",
},
"personal": {
"name": "Personal Kanban",
"columns": "Ideas → This Week → Today → Doing → Done",
"best_for": "จัดการงานส่วนตัว",
},
}
def show_columns(self):
print("=== Board Columns ===\n")
for key, col in self.COLUMNS.items():
wip = f"WIP: {col['wip']}" if col['wip'] else "No limit"
print(f"[{col['name']}] ({wip})")
print(f" {col['description']}")
def show_types(self):
print(f"\n=== Board Types ===")
for key, bt in self.BOARD_TYPES.items():
print(f"\n[{bt['name']}]")
print(f" Columns: {bt['columns']}")
print(f" Best for: {bt['best_for']}")
board = KanbanBoard()
board.show_columns()
board.show_types()
Python Kanban System
# kanban_system.py — Python Kanban implementation
import json
class KanbanSystem:
CODE = """
# kanban.py — Simple Kanban board in Python
import json
from datetime import datetime, timedelta
from collections import defaultdict
class KanbanCard:
def __init__(self, title, description="", priority="medium", assignee=""):
self.id = id(self)
self.title = title
self.description = description
self.priority = priority
self.assignee = assignee
self.created_at = datetime.now()
self.moved_at = datetime.now()
self.column = "backlog"
self.history = [{"column": "backlog", "time": self.created_at.isoformat()}]
def move_to(self, column):
self.column = column
self.moved_at = datetime.now()
self.history.append({"column": column, "time": self.moved_at.isoformat()})
def cycle_time(self):
'''Calculate cycle time (in_progress → done)'''
start = next((h['time'] for h in self.history if h['column'] == 'in_progress'), None)
end = next((h['time'] for h in self.history if h['column'] == 'done'), None)
if start and end:
s = datetime.fromisoformat(start)
e = datetime.fromisoformat(end)
return (e - s).total_seconds() / 3600 # hours
return None
def lead_time(self):
'''Calculate lead time (created → done)'''
end = next((h['time'] for h in self.history if h['column'] == 'done'), None)
if end:
e = datetime.fromisoformat(end)
return (e - self.created_at).total_seconds() / 3600
return None
class KanbanBoard:
def __init__(self, name="My Board"):
self.name = name
self.columns = ['backlog', 'ready', 'in_progress', 'review', 'done']
self.wip_limits = {'in_progress': 3, 'review': 2}
self.cards = []
def add_card(self, title, **kwargs):
card = KanbanCard(title, **kwargs)
self.cards.append(card)
return card
def move_card(self, card, to_column):
if to_column in self.wip_limits:
current_count = sum(1 for c in self.cards if c.column == to_column)
if current_count >= self.wip_limits[to_column]:
raise Exception(f"WIP limit reached for {to_column} ({self.wip_limits[to_column]})")
card.move_to(to_column)
def get_column(self, column):
return [c for c in self.cards if c.column == column]
def metrics(self):
done_cards = [c for c in self.cards if c.column == 'done']
cycle_times = [c.cycle_time() for c in done_cards if c.cycle_time()]
lead_times = [c.lead_time() for c in done_cards if c.lead_time()]
return {
'total_cards': len(self.cards),
'by_column': {col: len(self.get_column(col)) for col in self.columns},
'completed': len(done_cards),
'avg_cycle_time_hrs': round(sum(cycle_times)/len(cycle_times), 1) if cycle_times else 0,
'avg_lead_time_hrs': round(sum(lead_times)/len(lead_times), 1) if lead_times else 0,
'throughput_per_week': len([c for c in done_cards
if c.moved_at > datetime.now() - timedelta(days=7)]),
}
def display(self):
print(f"\\n=== {self.name} ===")
for col in self.columns:
cards = self.get_column(col)
wip = f" (WIP: {self.wip_limits.get(col, '∞')})" if col in self.wip_limits else ""
print(f"\\n[{col.upper()}{wip}] ({len(cards)} cards)")
for c in cards:
print(f" • [{c.priority[0].upper()}] {c.title} (@{c.assignee})")
# board = KanbanBoard("Sprint Board")
# card1 = board.add_card("Setup CI/CD", priority="high", assignee="dev1")
# board.move_card(card1, "in_progress")
# board.display()
"""
def show_code(self):
print("=== Kanban System ===")
print(self.CODE[:600])
system = KanbanSystem()
system.show_code()
Kanban Metrics
# metrics.py — Kanban metrics and analytics
import json
import random
class KanbanMetrics:
KEY_METRICS = {
"lead_time": {
"name": "Lead Time",
"description": "เวลาตั้งแต่งานเข้า board จนเสร็จ (created → done)",
"target": "ลดลงเรื่อยๆ — แสดงว่า process ดีขึ้น",
},
"cycle_time": {
"name": "Cycle Time",
"description": "เวลาตั้งแต่เริ่มทำจนเสร็จ (in_progress → done)",
"target": "ลดลง = ทำงานเร็วขึ้น",
},
"throughput": {
"name": "Throughput",
"description": "จำนวนงานที่เสร็จต่อช่วงเวลา (cards/week)",
"target": "เพิ่มขึ้นหรือคงที่ = capacity ดี",
},
"wip": {
"name": "Work in Progress",
"description": "จำนวนงานที่กำลังทำอยู่ — ควรอยู่ในขอบเขต WIP limit",
"target": "อยู่ภายใน limit เสมอ — เกิน = bottleneck",
},
"blocked": {
"name": "Blocked Items",
"description": "จำนวนงานที่ติดปัญหา — ต้องแก้เร็ว",
"target": "0 คือดีที่สุด — blocked = flow หยุด",
},
}
def show_metrics(self):
print("=== Key Metrics ===\n")
for key, m in self.KEY_METRICS.items():
print(f"[{m['name']}]")
print(f" {m['description']}")
print(f" Target: {m['target']}")
print()
def sample_dashboard(self):
print("=== Team Dashboard ===")
print(f" Lead Time (avg): {random.uniform(2, 8):.1f} days")
print(f" Cycle Time (avg): {random.uniform(1, 4):.1f} days")
print(f" Throughput: {random.randint(8, 25)} cards/week")
print(f" WIP: {random.randint(3, 8)} cards (limit: 8)")
print(f" Blocked: {random.randint(0, 3)} cards")
print(f" Completion Rate: {random.uniform(85, 100):.1f}%")
metrics = KanbanMetrics()
metrics.show_metrics()
metrics.sample_dashboard()
Kanban Tools & Comparison
# tools.py — Kanban tools comparison
import json
class KanbanTools:
TOOLS = {
"trello": {
"name": "Trello",
"type": "Simple Kanban",
"price": "Free / $5/user/mo",
"pros": "ง่ายมาก, สวย, free plan ดี",
"cons": "Features จำกัดสำหรับทีมใหญ่",
"best_for": "ทีมเล็ก, personal, simple projects",
},
"jira": {
"name": "Jira",
"type": "Full Project Management",
"price": "Free (10 users) / $8.15/user/mo",
"pros": "Features ครบ, reporting ดี, integrations เยอะ",
"cons": "ซับซ้อน, learning curve สูง",
"best_for": "Software development teams, enterprise",
},
"notion": {
"name": "Notion",
"type": "All-in-one Workspace",
"price": "Free / $8/user/mo",
"pros": "Flexible มาก, database + docs + kanban",
"cons": "ช้าบน datasets ใหญ่, ไม่เฉพาะทาง",
"best_for": "ทีมที่ต้องการ docs + kanban ในที่เดียว",
},
"linear": {
"name": "Linear",
"type": "Modern Issue Tracker",
"price": "Free / $8/user/mo",
"pros": "เร็วมาก, UX ดี, keyboard shortcuts",
"cons": "เน้น software dev, ไม่เหมาะงานอื่น",
"best_for": "Software teams ที่ต้องการ speed + simplicity",
},
}
KANBAN_VS_SCRUM = {
"kanban": {
"flow": "Continuous flow — ไม่มี sprint",
"roles": "ไม่มี prescribed roles",
"planning": "Pull-based — ดึงงานเมื่อพร้อม",
"changes": "เปลี่ยนได้ตลอด",
"metrics": "Lead time, cycle time, throughput",
},
"scrum": {
"flow": "Sprint-based — 1-4 สัปดาห์",
"roles": "Scrum Master, Product Owner, Dev Team",
"planning": "Sprint planning — commit งานต้น sprint",
"changes": "ไม่เปลี่ยนระหว่าง sprint",
"metrics": "Velocity, sprint burndown",
},
}
def show_tools(self):
print("=== Kanban Tools ===\n")
for key, tool in self.TOOLS.items():
print(f"[{tool['name']}] ({tool['type']})")
print(f" Price: {tool['price']}")
print(f" Pros: {tool['pros']}")
print(f" Best for: {tool['best_for']}")
print()
def show_vs_scrum(self):
print("=== Kanban vs Scrum ===")
features = ['flow', 'roles', 'planning', 'changes', 'metrics']
print(f" {'Feature':<12} {'Kanban':<35} {'Scrum'}")
for f in features:
print(f" {f:<12} {self.KANBAN_VS_SCRUM['kanban'][f]:<35} {self.KANBAN_VS_SCRUM['scrum'][f]}")
tools = KanbanTools()
tools.show_tools()
tools.show_vs_scrum()
FAQ - คำถามที่พบบ่อย
Q: WIP Limit ควรตั้งเท่าไหร่?
A: กฎง่ายๆ: จำนวนคนในทีม × 1.5 ตัวอย่าง: ทีม 3 คน → WIP limit = 4-5 cards ใน In Progress เริ่มจาก: ตั้ง limit สูงไว้ก่อน → ค่อยลดลงจนรู้สึกว่า flow ดี ถ้า limit ต่ำเกินไป: คน idle รองาน ถ้า limit สูงเกินไป: context switching, bottleneck ดู metrics: ถ้า cycle time เพิ่ม → ลด WIP limit
Q: Kanban เหมาะกับทีมแบบไหน?
A: เหมาะมาก: Support/Ops teams (งานเข้ามาตลอด ไม่สม่ำเสมอ) เหมาะ: Marketing, HR, ทีมที่มีงานหลากหลาย ใช้ได้: Software development (ถ้าไม่ต้องการ sprint structure) ไม่เหมาะ: โปรเจกต์ที่ต้อง commit scope ล่วงหน้า (ใช้ Scrum ดีกว่า) ข้อดี: เริ่มใช้ง่าย ไม่ต้องเปลี่ยน process ทั้งหมด — evolve ทีละนิด
Q: Kanban กับ Scrum ใช้ร่วมกันได้ไหม?
A: ได้ — เรียกว่า Scrumban ใช้ Sprint structure จาก Scrum + WIP limits จาก Kanban ตัวอย่าง: Sprint 2 สัปดาห์ + Kanban board with WIP limits + continuous flow ภายใน sprint เหมาะ: ทีมที่ใช้ Scrum อยู่แล้ว แต่ต้องการ flexibility มากขึ้น
Q: เริ่มใช้ Kanban ต้องทำอะไรบ้าง?
A: 1) สร้าง board — physical (whiteboard + sticky notes) หรือ digital (Trello, Jira) 2) กำหนด columns ตาม workflow ปัจจุบัน 3) ย้ายงานทั้งหมดขึ้น board 4) ตั้ง WIP limits (เริ่มจาก loose → ค่อย tighten) 5) ประชุม standup หน้า board ทุกวัน 6) Track metrics: lead time, throughput 7) Retrospective ทุก 2 สัปดาห์ — ปรับปรุง process สำคัญ: อย่าเปลี่ยนทุกอย่างพร้อมกัน — evolve ทีละเล็กน้อย
