Mở đầu — vì sao bài này quan trọng
Có một hiểu lầm rất phổ biến mà tôi muốn gỡ bỏ ngay từ dòng đầu tiên: nhiều PM nghĩ rằng "code review" là chuyện của engineer, còn mình thì không có chuyên môn đọc code nên đứng ngoài là đúng. Hiểu lầm này khiến PM bỏ lỡ một trong những điểm kiểm soát chất lượng quan trọng nhất trong vòng đời một tính năng — thời điểm code đã được viết xong nhưng chưa được merge và triển khai.
Hãy hình dung một dây chuyền: spec được viết, story được kéo vào sprint, engineer code, rồi pull request (PR) được mở ra chờ review. Nếu PM chỉ xuất hiện ở đầu (viết spec) và ở cuối (test trên môi trường staging khi mọi thứ đã xong), thì có cả một khoảng giữa mà bạn hoàn toàn mù mờ. Code review là cánh cửa để bạn nhìn vào khoảng giữa đó — không phải để soi từng dấu chấm phẩy, mà để kiểm tra hành vi (behavior) của tính năng: nó có làm đúng spec không, edge case nào bị bỏ sót, quyết định kỹ thuật nào đang lặng lẽ thay đổi trải nghiệm người dùng.
Một Technical PM giỏi không cần viết code được, nhưng cần đọc được PR đủ để đặt câu hỏi đúng. Sự khác biệt giữa một PM bị engineer "qua mặt" và một PM được engineer tôn trọng thường nằm chính ở khoảnh khắc này. Bài học hôm nay sẽ tập trung hẹp vào duy nhất một việc: PM tham gia code review như thế nào cho có giá trị, mà không giẫm chân vào vai trò kỹ thuật của engineer.
Khái niệm cốt lõi
PM review behavior, không review code style
Đây là ranh giới quan trọng nhất bạn phải khắc cốt ghi tâm. Trong một PR có hai tầng nội dung:
- Tầng kỹ thuật (engineer chịu trách nhiệm): code style, tên biến, thuật toán, cấu trúc class, hiệu năng, có bị memory leak không, test coverage đủ chưa về mặt kỹ thuật. Đây không phải việc của PM. Nếu bạn nhảy vào bình luận "biến này nên đặt tên khác" hay "sao không dùng map thay vì for-loop", bạn vừa làm sai vai vừa làm engineer khó chịu.
- Tầng hành vi (PM có quyền và nên review): tính năng có khớp với spec không, các trạng thái (states) đã được xử lý đủ chưa, edge case business nào bị bỏ sót, copy/text hiển thị có đúng không, luồng người dùng có đúng ý đồ sản phẩm không, có thay đổi nào ngầm ảnh hưởng tới analytics/tracking không.
"Đọc PR" với PM nghĩa là gì
Bạn không cần hiểu từng dòng. Khi mở một PR, PM nên đọc theo thứ tự ưu tiên sau:
- Mô tả PR (PR description): Engineer giỏi sẽ viết tóm tắt PR làm gì, ảnh hưởng tới phần nào. Đây là chỗ bạn đối chiếu với spec nhanh nhất.
- Danh sách file thay đổi: Bạn không đọc nội dung, chỉ liếc xem PR đụng vào những vùng nào — có đụng vào file thanh toán, file phân quyền, file gửi email không? Nếu một PR "sửa nút màu" mà lại đụng vào module payment, đó là tín hiệu để hỏi.
- Phần copy, text, config, feature flag: Những thứ này PM đọc được trực tiếp và thường là nơi sai về mặt sản phẩm (sai chính tả tiếng Việt, sai giá tiền, sai điều kiện bật/tắt tính năng).
- Screenshot/video demo trong PR: Nhiều team yêu cầu đính kèm ảnh chụp UI. Đây là nơi PM kiểm tra hành vi nhanh nhất mà không cần build.
Acceptance criteria là "hợp đồng" để review
Nếu story của bạn đã có acceptance criteria (tiêu chí nghiệm thu) rõ ràng — thứ ta học kỹ ở Bài 18 — thì việc review PR trở thành đối chiếu một-một: từng tiêu chí có được PR đáp ứng không. Code review không có acceptance criteria giống như chấm bài mà không có đáp án. Vì vậy chất lượng review của PM phụ thuộc trực tiếp vào chất lượng spec và AC bạn viết từ đầu.
Edge case — nơi PM tạo ra giá trị lớn nhất
Engineer thường nghĩ theo "happy path" — luồng thuận lợi nhất. PM, vì hiểu nghiệp vụ và người dùng, là người giỏi nhất trong việc nghĩ ra các tình huống biên: người dùng nhập số âm thì sao, đơn hàng 0 đồng thì sao, người dùng đã hủy gói nhưng còn hạn dùng thì hiển thị gì, mạng chậm timeout thì UI báo gì. Đây chính là phần "việc PM làm trong code review" mà ghi chú gốc của bài bỏ lửng — và là phần tạo ra giá trị thực.
Tình huống thực tế
Ví dụ 1 — Tiki và cái edge case "voucher chồng voucher"
Giả định một team tại Tiki đang làm tính năng áp nhiều mã giảm giá. Spec viết: "Người dùng được áp tối đa 2 voucher: 1 voucher sản phẩm + 1 voucher vận chuyển." Engineer mở PR, mô tả gọn gàng, demo chạy đẹp: chọn 1 voucher sản phẩm, 1 voucher ship, tổng tiền giảm đúng.
PM tên Linh không đọc được Java backend, nhưng cô làm đúng việc của mình. Cô đối chiếu AC và hỏi trong PR: "Trường hợp người dùng áp voucher ship trước, rồi voucher sản phẩm làm đơn hàng tụt xuống dưới ngưỡng tối thiểu để được freeship thì sao? Voucher ship còn hiệu lực không?" Engineer khựng lại — happy path không cover tình huống này. Hóa ra code sẽ vẫn áp voucher ship dù đơn không còn đủ điều kiện, gây thất thoát. Một câu hỏi của PM, đặt đúng lúc PR còn chưa merge, đã chặn được một lỗ hổng có thể tốn hàng chục triệu đồng khuyến mãi sai.
Bài học: PM không cần đọc code để tìm lỗi. PM cần đọc nghiệp vụ và đặt câu hỏi "còn trường hợp nào nữa không" ngay trên PR, khi chi phí sửa còn rẻ nhất.
Ví dụ 2 — Startup fintech và PR "đụng nhầm vùng nhạy cảm"
Một startup fintech ở TP.HCM, đội ngũ 12 engineer. PM tên Hoàng có thói quen liếc danh sách file mỗi PR, dù không đọc nội dung. Một hôm anh thấy một PR tiêu đề "Cập nhật giao diện trang lịch sử giao dịch" — nghe vô hại — nhưng trong danh sách file lại có thay đổi ở transaction_export_service. Trang hiển thị mà sao lại đụng vào service xuất dữ liệu?
Hoàng comment hỏi. Engineer giải thích: "Em tiện tay refactor luôn phần format số tiền cho trang export vì nó dùng chung helper." Nghe hợp lý, nhưng Hoàng biết tính năng export đang được một khách hàng doanh nghiệp lớn dùng để đối soát hàng ngày. Anh yêu cầu tách phần refactor đó ra một PR riêng để QA test export độc lập. Đúng như linh cảm — thay đổi format đã làm lệch định dạng file CSV mà hệ thống kế toán của khách đang import tự động. Nhờ tách PR, lỗi được bắt trước khi chạm production.
Bài học: PM review behavior ở cấp độ "vùng ảnh hưởng". Bạn không cần hiểu refactor là gì về mặt code; bạn chỉ cần biết tính năng nào đang quan trọng với khách hàng nào, và cảnh giác khi một PR đụng vào vùng đó ngoài dự kiến. Đây cũng là lý do nên khuyến khích PR nhỏ, một mục đích.
Ví dụ 3 — Team SaaS và lỗi tracking "vô hình"
Một công ty SaaS B2B làm phần mềm quản lý nhân sự. Họ chuẩn bị ra mắt tính năng mới và toàn bộ quyết định roadmap phụ thuộc vào việc đo lường tỷ lệ người dùng dùng tính năng đó. Engineer mở PR triển khai tính năng, đính kèm screenshot UI đẹp, mọi thứ trông hoàn hảo.
PM tên Trang có một checklist riêng cho mọi PR tính năng mới, trong đó luôn có một dòng: "Event tracking đã được gắn chưa, tên event và thuộc tính có khớp tài liệu tracking plan không?" (chủ đề ta đào sâu ở Bài 30). Cô tìm trong PR và... không thấy đoạn nào gọi tới hàm tracking. Cô hỏi. Engineer thừa nhận: "Spec không ghi rõ tên event nên em chưa làm, định bổ sung sau." Nếu PR này merge và lên production, tính năng sẽ chạy ngon lành nhưng không đo được gì — và một tháng sau khi cần dữ liệu để quyết định đầu tư tiếp, sẽ là con số 0.
Bài học: Có những thứ "đúng spec về mặt chức năng" nhưng vẫn sai về mặt sản phẩm vì thiếu phần vô hình như analytics, logging, hay feature flag. PM là người duy nhất quan tâm tới những thứ này đủ để bắt chúng trong code review.
Hướng dẫn từng bước
Đây là quy trình thực dụng để PM tham gia code review mà không lấn vai engineer:
- Thống nhất với team rằng PM được tag vào PR tính năng. Đề xuất một quy ước nhẹ: PR nào có nhãn
featurethì tag PM để review phần behavior, song song chứ không thay thế review kỹ thuật của engineer khác. PM không phải người phê duyệt (approve) cuối cùng về mặt code.
- Đọc mô tả PR và đối chiếu acceptance criteria. Mở story/AC ra cạnh PR. Tích từng tiêu chí: cái nào PR thể hiện rõ là đáp ứng, cái nào bạn không chắc.
- Liếc danh sách file để soi vùng ảnh hưởng. Tự hỏi: PR này có đụng vào vùng nào nhạy cảm (thanh toán, phân quyền, dữ liệu cá nhân, tích hợp bên thứ ba) ngoài phạm vi mong đợi không? Nếu có, hỏi lý do.
- Săn edge case bằng tư duy nghiệp vụ. Với mỗi tính năng, viết ra 3–5 tình huống biên và hỏi engineer xem PR đã xử lý chưa: dữ liệu rỗng, giá trị cực đại/cực tiểu, trạng thái chuyển tiếp, người dùng quyền khác nhau, lỗi mạng.
- Kiểm tra phần PM đọc được trực tiếp. Copy/text tiếng Việt, giá tiền, đơn vị, điều kiện feature flag, tên event tracking, nội dung email/thông báo. Đây là nơi bạn có thẩm quyền tuyệt đối.
- Bình luận bằng câu hỏi, không bằng mệnh lệnh kỹ thuật. Viết "Trường hợp X thì hành vi mong muốn là Y, PR đã cover chưa?" thay vì "Sửa hàm này đi". Bạn nêu vấn đề sản phẩm, để engineer chọn giải pháp kỹ thuật.
- Phân biệt blocker và nice-to-have. Nói rõ comment nào là chặn merge (sai spec, sai số tiền) và comment nào chỉ để ghi nhận làm sau (đưa vào backlog). Đừng để mọi comment đều mang sức nặng như nhau.
- Xác nhận và đóng vòng. Khi engineer trả lời hoặc sửa, bạn xác nhận lại đúng tiêu chí đã ổn rồi mới để PR đi tiếp. Đây là lúc bạn thực sự "nghiệm thu" ở cấp độ code, trước cả khi QA vào cuộc.
Lỗi thường gặp & mẹo
Lỗi 1 — PM nhảy vào review code style. Bình luận về tên biến, cách viết hàm, hay khen chê thuật toán là cách nhanh nhất để mất uy tín với engineer. Hãy ở đúng tầng behavior.
Lỗi 2 — Im lặng vì sợ "không đủ trình". Ngược lại của lỗi trên: PM không dám comment gì vì thấy code khó hiểu. Bạn không cần hiểu code; bạn cần hiểu sản phẩm. Một câu hỏi nghiệp vụ ngây thơ thường có giá trị hơn mười nhận xét kỹ thuật.
Lỗi 3 — Biến code review thành nơi viết lại spec. Nếu trong lúc review bạn phát hiện cả một mảng yêu cầu chưa từng được nói tới, đó là dấu hiệu spec ban đầu thiếu, không phải lỗi của PR. Đừng nhồi yêu cầu mới vào PR đang chạy; ghi nhận và xử lý ở vòng refinement tiếp theo (Bài 16).
Lỗi 4 — Comment mơ hồ. "Cái này nhìn sai sai" không giúp được ai. Hãy nêu rõ: tình huống nào, đầu vào gì, hành vi hiện tại là gì, hành vi mong muốn là gì.
Mẹo 1 — Yêu cầu screenshot/video trong PR template. Hãy đề xuất thêm mục "ảnh chụp UI" và "các edge case đã test" vào mẫu PR. Việc này giúp PM review nhanh hơn nhiều lần.
Mẹo 2 — Tự xây một checklist PM riêng. Như Trang ở ví dụ 3: tracking, copy, feature flag, vùng nhạy cảm, edge case. Dán vào mỗi PR để không bao giờ quên.
Mẹo 3 — Khen công khai khi engineer cover edge case tốt. Code review không chỉ để bắt lỗi. Ghi nhận khi engineer chủ động xử lý tình huống biên sẽ khuyến khích văn hóa nghĩ sâu, và khiến những comment chặn của bạn sau này dễ được tiếp nhận hơn.
Mẹo 4 — Đừng làm nghẽn (bottleneck). Nếu bạn quá bận, hãy chỉ review những PR thật sự rủi ro cao về mặt sản phẩm, và tin tưởng acceptance criteria + QA cho phần còn lại. PM review PR là để tăng chất lượng, không phải để làm chậm cả team.
Bài tập thực hành
- Lập checklist review của riêng bạn. Viết ra danh sách 6–8 điểm bạn sẽ kiểm tra trên mỗi PR tính năng (gợi ý: đối chiếu AC, vùng file nhạy cảm, copy tiếng Việt, tracking, feature flag, edge case, trạng thái lỗi, thông báo cho người dùng). Đây sẽ là công cụ bạn dùng thật trong công việc.
- Bài tập săn edge case. Lấy một tính năng quen thuộc — ví dụ "đặt lịch hẹn với mentor" trên một nền tảng học trực tuyến. Viết ra ít nhất 7 edge case nghiệp vụ mà một PM nên hỏi khi review PR (gợi ý: đặt trùng giờ, mentor hủy phút chót, lệch múi giờ, người dùng đặt rồi không thanh toán, hết slot ngay lúc bấm xác nhận).
- Viết lại comment. Cho comment kỹ thuật sai vai sau: "Hàm calculateDiscount nên tách nhỏ ra và đặt lại tên cho dễ đọc." Hãy viết lại thành một comment đúng tầng PM, tập trung vào behavior và đặt dưới dạng câu hỏi.
- Phân loại blocker. Lấy 5 phát hiện giả định trên một PR (ví dụ: sai giá hiển thị, thiếu tracking, một nút lệch màu nhẹ, chưa xử lý trường hợp đơn 0 đồng, tên biến khó hiểu) và phân loại từng cái: chặn merge, làm sau, hay không phải việc của PM.
Tóm tắt
Code review không phải đặc quyền riêng của engineer, và cũng không phải nơi PM thể hiện kiến thức kỹ thuật. Đây là điểm kiểm soát chất lượng cuối cùng trước khi code chạm tới người dùng, và vai trò của PM ở đó rất rõ ràng: review behavior, không review code style. Bạn đối chiếu tính năng với spec và acceptance criteria, soi vùng ảnh hưởng qua danh sách file, săn các edge case nghiệp vụ mà engineer dễ bỏ sót, và kiểm tra những phần PM đọc được trực tiếp như copy, giá tiền, feature flag và event tracking.
Ba tình huống — voucher chồng voucher ở Tiki, PR đụng nhầm vùng nhạy cảm ở startup fintech, và lỗi tracking vô hình ở team SaaS — đều cho thấy cùng một điều: giá trị PM tạo ra trong code review không đến từ việc đọc code, mà từ việc đặt đúng câu hỏi nghiệp vụ vào đúng thời điểm, khi chi phí sửa còn rẻ nhất. Hãy bình luận bằng câu hỏi chứ không bằng mệnh lệnh kỹ thuật, phân biệt rõ blocker với nice-to-have, và đừng bao giờ biến mình thành nút nghẽn của team. Làm được vậy, bạn không chỉ tăng chất lượng sản phẩm mà còn xây được sự tôn trọng từ chính những engineer bạn làm việc cùng.