Ước lượng khi còn ẩn số, nói "không" và ưu tiên tech debt
Tiếp đi: ước lượng. PM hỏi mình "migrate payment sang provider mới mất bao lâu?" mà mình chưa đọc docs provider đó. Mình nói đại "2 tuần" rồi trễ thành 5 tuần. Lần sau phải trả lời sao?
Chuyện này senior nào cũng gặp. Vấn đề không phải bạn ước lượng sai, mà là bạn đưa một con số chắc chắn cho một việc chưa chắc chắn.
1. Bài toán
PM: "Chuyển payment từ Provider A sang Provider B, bao lâu?"
Biết: API A, code checkout hiện tại
Chưa biết: webhook B ra sao, sandbox B có ổn không,
refund cũ (đơn trả bằng A) xử lý thế nào,
team legal có cần review không
2. Vấn đề: vì sao "2 tuần" hỏng
- Con số đơn lẻ bị nghe thành cam kết, PM báo lên trên, marketing lên lịch.
- Ước lượng chỉ tính phần code, quên test, review, deploy, migration dữ liệu, chờ team khác.
- Ẩn số lớn nhất (webhook, refund cũ) chỉ lộ ra ở tuần thứ 3.
3. Giải pháp: range + spike + breakdown
| Công cụ | Ý nghĩa |
|---|---|
| Range | Đưa khoảng "3–6 tuần" kèm độ tự tin, không đưa một số |
| Spike | Timebox 2–3 ngày để khám phá ẩn số lớn nhất, sau đó ước lượng lại |
| Breakdown | Chia việc đến khi mỗi phần ≤ 2–3 ngày; phần nào không chia được là ẩn số |
| Assumptions | Ghi rõ giả định; giả định sai thì ước lượng thay đổi |
| Re-estimate | Cập nhật khi biết thêm, báo sớm, không đợi đến hạn |
4. Ví dụ và mẫu dùng ngay
Mẫu 1: Breakdown cho migrate payment
Việc Ước lượng Độ chắc
------------------------------------- ---------- -------
Spike: sandbox B, webhook, refund 2-3 ngày cao
Adapter PaymentGateway cho B 3-5 ngày vừa
Webhook handler + idempotency 3-5 ngày thấp (*)
Feature flag chuyển dần A → B 1-2 ngày cao
Xử lý refund đơn cũ của A 2-8 ngày thấp (*)
Contract test + E2E sandbox 3-4 ngày vừa
Rollout 5% → 50% → 100% + theo dõi 3-5 ngày vừa
------------------------------------- ----------
Tổng 17-32 ngày ≈ 4-6 tuần
(*) sẽ rõ sau spike
Mẫu 2: Câu trả lời cho PM
"Hiện tại em ước lượng 4–6 tuần, độ tự tin khoảng 60%.
Hai ẩn số lớn: webhook của B và refund cho đơn cũ.
Cho em 3 ngày spike, sau đó em đưa con số chắc hơn (±1 tuần).
Nếu cần ra mắt sớm, mình có thể làm checkout mới trước,
refund đơn cũ vẫn đi qua A thêm 1 tháng."
Câu cuối là trade-off: bạn không chỉ nói "lâu", bạn đưa lựa chọn.
Mẫu 3: Nói "không" (thật ra là "có, nếu…")
PM muốn thêm "mã giảm giá theo nhóm khách" vào sprint đang đầy:
Không nên: "Không kịp đâu anh."
Nên: "Được anh. Sprint đang full với migrate payment.
Mình có 3 lựa chọn:
1. Làm coupon, lùi migrate 1 tuần (rủi ro: hợp đồng A hết hạn 30/11)
2. Làm bản coupon đơn giản (chỉ % cố định), 2 ngày
3. Để sprint sau
Em nghiêng về 2. Anh chọn cái nào theo ưu tiên business?"
Tam giác cố định: scope / time / quality. Thêm scope thì phải bớt cái khác. Senior không hy sinh quality âm thầm (bỏ test), mà nói rõ trade-off để người có quyền business quyết định.
Mẫu 4: Ưu tiên tech debt vs feature
Đừng nói "code xấu, cần refactor". Nói bằng chi phí:
Tech debt: OrderService 2.500 dòng, không có test cho tính giá
Chi phí hiện tại:
- 3/5 incident quý này liên quan tính giá
- Mỗi feature giá mới mất thêm ~3 ngày vì sợ vỡ
Đề xuất: dành 20% mỗi sprint, 3 sprint
- Sprint 1: characterization test cho PriceCalculator
- Sprint 2: tách PricingService
- Sprint 3: xóa code chết
Đo: số incident giá, lead time feature giá
Bảng chấm điểm nhanh để xếp backlog:
| Item | Impact (1-5) | Effort (1-5) | Risk nếu bỏ qua | Ưu tiên |
|---|---|---|---|---|
| Fix double charge | 5 | 2 | Mất tiền, mất khách | Ngay |
| Test cho tính giá | 4 | 3 | Incident lặp lại | Sprint này (20%) |
| Coupon theo nhóm | 3 | 3 | Thấp | Bản đơn giản |
| Đổi sang Kotlin | 1 | 5 | Không | Không làm |
5. Cách hoạt động: vòng ước lượng
Yêu cầu mơ hồ
|
v
Breakdown ──> phần nào không chia được? ──> Spike (timebox)
| |
v v
Range + giả định <────────── cập nhật ───────┘
|
v
Commit theo milestone, theo dõi hàng tuần
|
v
Lệch > 20%? ──> báo PM ngay + đưa lựa chọn (cắt scope / lùi ngày)
6. So sánh
| Tình huống | Phản xạ sai | Phản xạ senior |
|---|---|---|
| Bị hỏi "bao lâu?" | Một con số, đoán | Range + giả định + spike |
| Sắp trễ | Im lặng, làm OT | Báo sớm kèm phương án |
| Yêu cầu thêm | "Không" hoặc "OK" rồi bỏ test | "Có, nếu…" với 2–3 lựa chọn |
| Tech debt | "Code xấu" | Chi phí đo được + kế hoạch nhỏ |
7. Khi nào nên / không nên
- Nên spike khi ẩn số chiếm > 30% công việc.
- Không nên spike vô hạn: timebox rõ, kết quả là một tài liệu ngắn hoặc prototype vứt đi.
- Không nên cộng "buffer bí mật" gấp đôi. Nói rõ buffer và lý do thì PM tin bạn hơn.
- Việc lặp lại quen thuộc (thêm một endpoint CRUD) thì không cần range phức tạp.
Story point với giờ thì nên dùng cái nào? Team mình cãi nhau mãi.
Cả hai đều dùng được, quan trọng là dùng cho đúng việc:
- Story point: đo độ phức tạp tương đối trong team, dùng để lập kế hoạch sprint qua velocity. Không đổi ra giờ, không so team này với team khác.
- Ngày/tuần dạng range: dùng khi nói với PM/stakeholder về mốc thời gian. Họ cần ngày, không cần point.
Trong phỏng vấn, đừng sa vào tranh luận công cụ. Nói ý chính: "ước lượng là để ra quyết định, nên em chọn đơn vị người nghe hiểu và luôn kèm độ tự tin."
Nếu PM vẫn ép "phải xong trong 2 tuần" dù mình đã giải thích thì sao?
Đúng rồi, chuyện này xảy ra thường xuyên. Deadline đôi khi là thật (hợp đồng, sự kiện Black Friday). Khi đó bạn cố định thời gian, linh hoạt scope:
"2 tuần thì em làm được:
✔ Checkout mới qua B cho thẻ Visa/Master
✔ Feature flag, rollback về A trong 1 phút
✘ Ví điện tử, refund đơn cũ → sprint sau
Em gửi lại scope này qua Slack để mình thống nhất nhé."
Ghi lại bằng văn bản. Không phải để đổ lỗi sau này, mà để mọi người cùng hiểu một scope. Thứ duy nhất không cắt: test cho đường tiền và khả năng rollback.
Phỏng vấn hỏi "Bạn ước lượng thế nào khi yêu cầu chưa rõ?" và "Bạn cân bằng tech debt với feature ra sao?" thì trả lời sao?
Q1. Bạn ước lượng thế nào khi yêu cầu chưa rõ?
🇻🇳 Tiếng Việt:
Em chia việc nhỏ đến mức mỗi phần vài ngày, phần nào không chia được là ẩn số. Em đưa khoảng thời gian kèm giả định và độ tự tin, rồi đề xuất spike có timebox cho ẩn số lớn nhất. Ví dụ migrate payment provider, em báo 4–6 tuần, sau 3 ngày spike thu về 5 tuần ±1. Khi lệch, em báo sớm kèm lựa chọn cắt scope hoặc lùi ngày.
🇬🇧 English:
I break the work down until each piece is a few days; anything I can't break down is an unknown. I give a range with assumptions and a confidence level, and propose a time-boxed spike for the biggest unknown. For a payment provider migration I said 4 to 6 weeks, and after a 3-day spike narrowed it to 5 weeks plus or minus one. If we drift, I raise it early with options: cut scope or move the date.
Q2. Bạn cân bằng tech debt với feature ra sao?
🇻🇳 Tiếng Việt:
Em biến tech debt thành chi phí business: số incident, số ngày bị chậm mỗi feature. Sau đó đề xuất phần nhỏ, thường khoảng 20% mỗi sprint, gắn với khu vực sắp có feature mới để vừa trả nợ vừa ship. Em đo lại sau vài sprint để chứng minh nó đáng làm.
🇬🇧 English:
I translate tech debt into business cost: incidents and days lost per feature. Then I propose small chunks, usually around 20% of each sprint, focused on the area where upcoming features will land, so we pay debt and ship at the same time. I measure again after a few sprints to show it was worth it.
Q3. Bạn từng nói "không" với stakeholder chưa?
🇻🇳 Tiếng Việt:
Có, nhưng em thường nói "có, nếu…". Khi PM muốn thêm coupon vào sprint đầy, em đưa ba lựa chọn với chi phí của từng cái và đề xuất bản đơn giản. PM chọn, và scope được ghi lại rõ. Em không bao giờ âm thầm bỏ test để kịp.
🇬🇧 English:
Yes, but usually as "yes, if…". When the PM wanted coupons added to a full sprint, I laid out three options with the cost of each and recommended a simpler version. The PM chose, and we wrote the scope down. I never silently drop tests to hit a date.
Cách nhớ ngắn gọn
- Ước lượng = range + giả định + độ tự tin.
- Ẩn số lớn → spike có timebox.
- Nói "không" = đưa lựa chọn, người có quyền business quyết định.
- Tech debt nói bằng chi phí, trả dần 20%.
Tự kiểm tra
Vì sao không nên đưa một con số đơn lẻ?
Nó bị hiểu là cam kết, che mất mức độ không chắc chắn.
Spike là gì, kết quả của spike là gì?
Khám phá có timebox cho ẩn số lớn; kết quả là tài liệu ngắn/prototype và ước lượng chính xác hơn.
Deadline cố định thì linh hoạt cái gì?
Scope. Không cắt test đường tiền và khả năng rollback.
Cách trình bày tech debt với PM?
Bằng chi phí đo được (incident, ngày chậm) và kế hoạch nhỏ có đo lường.
Story point dùng để làm gì, không dùng để làm gì?
Lập kế hoạch sprint trong team; không đổi ra giờ, không so giữa các team.