Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

Bài 40 — Tech debt assessment và prioritization

PSPO II Advanced Product Ownership Bài 40/60

Mở đầu — vì sao bài này quan trọng

Hãy hình dung bạn là Product Owner của một ứng dụng đặt đồ ăn. Sprint nào team cũng giao đủ feature, demo Sprint Review mượt mà, stakeholder vỗ tay. Nhưng đến tháng thứ tám, một việc tưởng nhỏ như "thêm nút lưu địa chỉ yêu thích" lại mất tới ba Sprint thay vì một. Engineer thở dài: "Chỗ đó dính tới module thanh toán, đụng vào là vỡ." Velocity tụt dần mà không feature nào "to" hơn trước. Đó chính là lúc technical debt — nợ kỹ thuật — đã âm thầm ăn mòn năng lực giao hàng của bạn.

Nhiều Product Owner mắc một quan niệm sai chí mạng: cho rằng tech debt là "chuyện của engineer", là vùng cấm mà PO không nên đụng vào. Ở cấp độ PSPO II, đây là tư duy phải dứt khoát loại bỏ. Product Owner là người chịu trách nhiệm tối đa hóa giá trị của sản phẩm — mà tech debt chính là một dạng rủi ro làm xói mòn giá trị tương lai. Bạn không cần viết được code, nhưng bạn bắt buộc phải hiểu, đánh giá và ưu tiên việc trả nợ kỹ thuật trong Product Backlog, cạnh tranh sòng phẳng với feature mới.

Bài này trang bị cho bạn ba thứ: cách nhận diện và phân loại nguồn gốc của nợ kỹ thuật, cách lượng hóa nó thành ngôn ngữ giá trị mà bạn và stakeholder cùng hiểu, và cách đưa nó vào quyết định ưu tiên Backlog một cách có kỷ luật. Đây là kỹ năng phân biệt một PO "thư ký Backlog" với một PO thật sự làm chủ vận mệnh sản phẩm.

Khái niệm cốt lõi

Technical debt thực ra là gì

Thuật ngữ "technical debt" do Ward Cunningham đặt ra như một phép ẩn dụ tài chính. Khi bạn vay nợ, bạn có tiền dùng ngay nhưng phải trả lãi. Tương tự, khi team chọn một giải pháp nhanh-nhưng-không-sạch để kịp deadline, họ "vay" tốc độ hôm nay và phải "trả lãi" bằng việc mỗi thay đổi sau này đều chậm hơn, rủi ro hơn. Lãi này tích lũy theo thời gian, và nếu không trả gốc, có ngày "lãi mẹ đẻ lãi con" khiến sản phẩm gần như đóng băng.

Điểm quan trọng PO cần nắm: không phải mọi nợ đều xấu. Có "nợ chiến lược có chủ đích" — ví dụ một startup quyết định viết nhanh, bẩn để kịp ra mắt MVP giành thị trường, rồi refactor sau khi có doanh thu. Đó là quyết định kinh doanh hợp lý. Cái nguy hiểm là "nợ vô tình" tích lũy mà không ai nhìn thấy, và "nợ bị bỏ mặc" mà không có kế hoạch trả.

Bốn góc phần tư của Martin Fowler

Martin Fowler đề xuất một ma trận hữu ích để PO hiểu bản chất nợ, dựa trên hai trục: cố ý/vô tình và thận trọng/liều lĩnh.

  • Thận trọng & Cố ý: "Ta phải ship ngay, sẽ gánh hậu quả và xử lý sau." Đây là nợ tốt nếu được theo dõi.
  • Liều lĩnh & Cố ý: "Không có thời gian cho thiết kế tử tế đâu." Nợ nguy hiểm vì biết sai mà vẫn làm bừa.
  • Thận trọng & Vô tình: "Giờ thì ta đã hiểu lẽ ra nên làm thế nào." Đây là nợ tự nhiên khi kiến thức tăng lên — gần như không tránh được.
  • Liều lĩnh & Vô tình: "Layering là cái gì?" Nợ do thiếu năng lực, không hề biết mình đang tạo nợ.
PO không cần phán xét đạo đức, nhưng hiểu được nợ thuộc loại nào giúp bạn đối thoại với team đúng cách.

Các nguồn nợ kỹ thuật chính

Để đánh giá, bạn cần biết nợ "trú ngụ" ở đâu trong sản phẩm:

Code debt (nợ ở tầng code): Những bản vá nhanh, code trùng lặp, thiếu test, đặt tên khó hiểu, hàm dài hàng trăm dòng. Đây là loại dễ thấy nhất, thường được đo bằng công cụ như SonarQube. Hậu quả: thay đổi nhỏ cũng dễ gây bug.

Architecture debt (nợ ở tầng kiến trúc): Trừu tượng hóa sai, ranh giới module mơ hồ, một khối monolith khổng lồ mà mọi thứ dính chặt vào nhau (tight coupling). Đây là loại đắt và nguy hiểm nhất vì sửa nó đòi hỏi thiết kế lại diện rộng. Một quyết định kiến trúc sai từ năm đầu có thể "giam" cả sản phẩm nhiều năm.

Test debt: Thiếu kiểm thử tự động, khiến mỗi lần release phải test tay tốn ngày trời và vẫn lọt lỗi.

Infrastructure / dependency debt: Thư viện, framework, phiên bản ngôn ngữ lỗi thời không được nâng cấp — đến một ngày nhà cung cấp ngừng hỗ trợ, lỗ hổng bảo mật không được vá.

Knowledge debt: Kiến thức nằm trong đầu một vài người, không tài liệu hóa. Một người nghỉ việc là cả mảng tê liệt.

Lượng hóa nợ: nói ngôn ngữ giá trị, không phải ngôn ngữ kỹ thuật

Sai lầm lớn của PO non kinh nghiệm là để engineer nói "chúng ta cần refactor module X" rồi gật đầu hoặc gạt đi theo cảm tính. Cách làm của PSPO II là quy nợ về tác động đến giá trị. Ba câu hỏi cốt lõi:

  • Tần suất chạm vào (frequency): Vùng nợ này có nằm trên đường đi của các feature sắp tới không? Nợ ở vùng code "đóng băng" không ai sửa thì lãi suất gần bằng 0 — đừng tốn công trả.
  • Mức độ đau (impact): Nó làm chậm bao nhiêu phần trăm thời gian phát triển? Có gây sự cố production, rủi ro bảo mật, hay cản trở khả năng đổi mới (liên hệ với KVA Ability to Innovate ở bài trước)?
  • Chi phí trả nợ (cost to fix): Trả gốc tốn bao nhiêu? Có thể trả từng phần không?
Một kỹ thuật thực hành tốt là kết hợp dữ liệu của engineer (số lượng "hotspot" thay đổi nhiều + phức tạp cao, lấy từ lịch sử Git) với góc nhìn roadmap của bạn. Vùng vừa-phức-tạp-vừa-bị-sửa-liên-tục chính là nơi trả nợ cho ROI cao nhất.

Tình huống thực tế

Tình huống 1 — Sàn thương mại điện tử "ChợViệt" và bức tường monolith

ChợViệt (giả định) là một sàn TMĐT nội địa, sau ba năm tăng trưởng nóng đạt 2 triệu người dùng. Để giành thị phần với các ông lớn, ban đầu họ cố ý chọn nợ chiến lược: viết toàn bộ hệ thống thành một monolith PHP duy nhất, ưu tiên ra tính năng thật nhanh. Quyết định đó đúng cho giai đoạn đầu.

Nhưng đến năm thứ ba, vấn đề bùng nổ. Mỗi lần marketing chạy flash sale, hệ thống quá tải vì module thanh toán, tìm kiếm và giỏ hàng dính chặt nhau, không scale riêng được. Velocity của team rớt 40% so với năm đầu. PO mới về nhận thấy engineer liên tục phàn nàn nhưng không thuyết phục được CEO chi cho việc "không tạo feature".

Cách PO xử lý: thay vì xin một dự án "refactor toàn bộ" kéo dài sáu tháng (gần như chắc chắn bị từ chối), cô dùng dữ liệu hotspot từ Git để chỉ ra module thanh toán là nơi 60% sự cố production xảy ra và là điểm nghẽn của mọi feature doanh thu sắp tới. Cô lượng hóa: mỗi sự cố flash sale ước tính mất 800 triệu đồng doanh thu. Cô đề xuất tách riêng đúng module thanh toán thành service độc lập — một lát cắt nhỏ, đo được, gắn thẳng với tiền.

Bài học: Đừng xin trả hết nợ một lúc. Hãy chọn lát cắt nợ có lãi suất cao nhất, gắn nó với một con số kinh doanh cụ thể mà stakeholder quan tâm.

Tình huống 2 — Fintech "MoMoney" và quả bom dependency

Một công ty fintech ở Đông Nam Á (giả định, gọi là MoMoney) chạy hệ thống cốt lõi trên một phiên bản framework đã ngừng được hỗ trợ bảo mật. Đây là dạng infrastructure/dependency debt — loại "im lặng" mà demo nào cũng đẹp nên bị bỏ quên hết quý này sang quý khác.

Rồi một lỗ hổng nghiêm trọng được công bố trên đúng phiên bản đó. Đội bảo mật báo động đỏ. Việc nâng cấp lẽ ra làm dần trong vài Sprint giờ biến thành một cuộc chạy nước rút khẩn cấp ba tuần, đóng băng toàn bộ roadmap, cộng thêm rủi ro bị cơ quan quản lý tài chính tuýt còi nếu xảy ra rò rỉ dữ liệu khách hàng.

PO ở đây học được bài học bằng nỗi đau: lẽ ra phải đưa "ngân sách trả nợ định kỳ" vào Backlog, dành ra một tỷ lệ ổn định (ví dụ 15–20% năng lực mỗi Sprint) cho việc nâng cấp dependency và bảo trì. Nợ vô hình không tạo áp lực hằng ngày, nên cần PO chủ động làm cho nó "hiện hình".

Bài học: Loại nợ nguy hiểm nhất thường là loại không gây đau ngay. PO phải biến nợ vô hình thành hạng mục hữu hình trong Backlog, đặc biệt ở lĩnh vực có quy định pháp lý.

Tình huống 3 — Startup SaaS và cái bẫy "luôn luôn feature"

Một startup SaaS B2B (giả định) có CEO rất quyết liệt về tăng trưởng, ra lệnh: "100% năng lực cho feature, không refactor gì hết cho tới khi gọi vốn xong." Trong sáu tháng, mọi thứ trông tuyệt vời, số liệu tăng trưởng đẹp. Nhưng nợ tích lũy đến mức team thêm một feature trung bình mất gấp ba lần ban đầu, và tỷ lệ bug rò rỉ ra khách hàng tăng vọt, khiến churn (tỷ lệ rời bỏ) bắt đầu nhích lên.

PO đã thuyết phục CEO bằng một biểu đồ đơn giản: vẽ đường velocity thực tế đang đi xuống và đối chiếu với đường lý thuyết nếu trả nợ đều. Cô không nói "code xấu", cô nói "với đà này, sáu tháng nữa ta chỉ giao được một nửa số feature so với bây giờ với cùng chi phí nhân sự." CEO đồng ý dành 20% mỗi Sprint cho việc trả nợ có chọn lọc. Sau ba tháng, velocity ổn định trở lại và churn giảm.

Bài học: Trả nợ không phải là chống lại tăng trưởng — nó chính là điều kiện để duy trì tốc độ tăng trưởng. Hãy đóng khung nó như một khoản đầu tư vào tốc độ tương lai, không phải chi phí phụ.

Hướng dẫn từng bước

Đây là quy trình thực hành để PO đánh giá và ưu tiên tech debt một cách có kỷ luật:

Bước 1 — Làm cho nợ hiện hình. Cùng team lập một "debt register" (sổ ghi nợ) — có thể là một nhãn (label) riêng trong công cụ Backlog. Mỗi khoản nợ ghi rõ: nó nằm ở đâu, thuộc loại gì (code/architecture/test/dependency/knowledge), và triệu chứng quan sát được. Không có danh sách thì không thể ưu tiên.

Bước 2 — Thu thập tín hiệu định lượng. Lấy từ engineer các dữ liệu khách quan: hotspot từ lịch sử Git (file nào bị sửa nhiều + phức tạp cao), điểm từ công cụ phân tích tĩnh, số sự cố production theo vùng, thời gian build/test. Đây là "lãi suất" của từng khoản nợ.

Bước 3 — Đối chiếu với roadmap. Lấy danh sách nợ phủ lên hướng đi sắp tới của sản phẩm. Khoản nợ nằm chắn đường các feature giá trị cao thì lãi suất thực tế cực lớn; khoản nợ ở vùng không ai động tới thì cứ để đó.

Bước 4 — Cho điểm theo ba trục. Với mỗi khoản, ước lượng: Tác động (đau bao nhiêu), Tần suất (chạm bao nhiêu), Chi phí trả (tốn bao nhiêu). Ưu tiên những khoản tác động cao, tần suất cao, chi phí trả thấp trước.

Bước 5 — Đưa vào một Product Backlog duy nhất. Đừng tạo "Backlog nợ" riêng biệt. Nợ phải cạnh tranh sòng phẳng với feature trong cùng một danh sách được sắp thứ tự. Đây là điểm cốt lõi của Scrum: một Backlog, một thứ tự, do PO chịu trách nhiệm.

Bước 6 — Diễn đạt bằng ngôn ngữ giá trị khi truyền thông. Với stakeholder, không nói "refactor service A". Nói "khoản này giúp ta giao feature thanh toán mới nhanh hơn 30% và giảm rủi ro sự cố flash sale." Gắn nợ với KVA: Current Value (giảm sự cố), Time to Market (giao nhanh hơn), Ability to Innovate (gỡ rào cản đổi mới).

Bước 7 — Đặt nhịp trả nợ bền vững. Thống nhất với team và stakeholder một tỷ lệ năng lực ổn định cho việc trả nợ (thường 15–20%), thay vì làm theo kiểu "khủng hoảng mới chữa cháy".

Lỗi thường gặp & mẹo

Lỗi: Coi tech debt là việc của riêng team Dev. PO né tránh, để Developer tự nhét việc trả nợ vào kẽ hở. Hậu quả là nợ không bao giờ được ưu tiên minh bạch. PO phải sở hữu quyết định này.

Lỗi: Lập một "Backlog kỹ thuật" tách rời. Khi có hai Backlog, cái "không tạo feature" luôn thua. Hãy giữ một Backlog duy nhất.

Lỗi: Xin trả hết nợ một lần bằng một dự án lớn. "Refactor toàn bộ trong sáu tháng" gần như luôn bị từ chối và rủi ro cao. Hãy chia nhỏ thành các lát cắt gắn với giá trị đo được.

Lỗi: Để engineer dùng từ ngữ kỹ thuật khi báo cáo cho business. Stakeholder không hiểu "circular dependency", họ hiểu "chậm 30%", "rủi ro mất 800 triệu", "trễ ra mắt một tháng".

Lỗi: Trả những khoản nợ ở vùng chẳng ai động tới. Đẹp về mặt kỹ thuật nhưng vô nghĩa về giá trị. Chỉ trả nợ có lãi suất thực.

Mẹo: Dùng phép ẩn dụ tài chính khi đối thoại với lãnh đạo — "nợ", "lãi suất", "đầu tư vào tốc độ". Ngôn ngữ này khiến người không kỹ thuật lập tức hiểu.

Mẹo: Theo dõi đường velocity dài hạn. Velocity đi xuống đều mà không có lý do về nhân sự thường là dấu hiệu rõ ràng của nợ đang đè nặng.

Mẹo: Biến nợ vô hình thành hữu hình — đặc biệt dependency và bảo mật. Một dòng trong Backlog "Nâng cấp framework X (rủi ro bảo mật)" tốt hơn nhiều một quả bom im lặng.

Bài tập thực hành

  • Lập debt register cho sản phẩm của bạn. Liệt kê ít nhất năm khoản nợ kỹ thuật bạn biết hoặc nghi ngờ. Phân loại mỗi khoản theo nguồn (code/architecture/test/dependency/knowledge) và ghi triệu chứng quan sát được. Nếu bạn không biết, đó chính là bài tập đầu tiên: ngồi với một Developer trong 30 phút và hỏi.
  • Cho điểm và xếp hạng. Với năm khoản trên, cho điểm 1–5 ở ba trục Tác động, Tần suất, Chi phí trả. Tính thứ tự ưu tiên. Khoản nào lên đầu? Có bất ngờ không so với cảm tính ban đầu của bạn?
  • Viết một "value statement". Chọn khoản nợ ưu tiên cao nhất, viết một câu thuyết phục CEO/stakeholder bằng ngôn ngữ giá trị, có ít nhất một con số định lượng (doanh thu, %, thời gian, rủi ro). Đọc lại: nó có còn từ kỹ thuật nào mà người ngoài không hiểu không?
  • Thiết kế nhịp trả nợ. Đề xuất một tỷ lệ năng lực mỗi Sprint cho việc trả nợ và lý lẽ bảo vệ con số đó trước một stakeholder muốn "100% feature".

Tóm tắt

Technical debt không phải vùng cấm của engineer — nó là một dạng rủi ro làm xói mòn giá trị tương lai mà Product Owner phải chủ động quản lý. Nợ đến từ nhiều tầng: code (vá nhanh, thiếu test), kiến trúc (trừu tượng sai, monolith dính chặt) là hai nguồn nặng nhất, bên cạnh test, dependency và knowledge debt. Không phải mọi nợ đều xấu: có nợ chiến lược có chủ đích, có nợ vô tình tích lũy nguy hiểm.

Nhiệm vụ của PSPO II là lượng hóa nợ thành ngôn ngữ giá trị qua ba trục — tác động, tần suất chạm, chi phí trả — rồi đối chiếu với roadmap để tìm khoản có lãi suất cao nhất. Đưa nợ vào một Product Backlog duy nhất, cạnh tranh sòng phẳng với feature, và truyền thông bằng con số kinh doanh chứ không phải thuật ngữ kỹ thuật. Cuối cùng, hãy thiết lập một nhịp trả nợ bền vững (15–20% năng lực) thay vì chữa cháy khủng hoảng. Làm chủ tech debt chính là làm chủ tốc độ giao hàng tương lai của sản phẩm.