Menu
ESC

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

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

Đang tải...

Bài 13 — Code Review Culture — Build thay vì impose

Technical Leadership Bài 13/60

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

Nếu bạn hỏi mười kỹ sư về code review, bạn sẽ nhận được mười cảm xúc khác nhau — và không ít trong số đó là tiêu cực. Có người thấy code review là nơi bị "soi", bị đồng nghiệp chê bai trước cả team. Có người thấy nó là cái phễu tắc nghẽn khiến pull request (PR — yêu cầu gộp code) của mình nằm chờ ba ngày mới có người ngó tới. Có người thì review qua loa, gõ "LGTM" (Looks Good To Me — trông ổn với tôi) trong ba giây rồi approve mà chẳng đọc dòng nào.

Tất cả những triệu chứng đó đều chung một gốc rễ: code review được áp đặt (impose) như một thủ tục bắt buộc, chứ không được xây dựng (build) như một văn hóa mà đội tự nguyện tin vào. Với vai trò Tech Lead, đây chính là điểm bạn phải nắm. Bạn không thể ra một cái quy trình rồi ép cả team tuân theo và mong đợi chất lượng code tăng lên. Văn hóa không sinh ra từ mệnh lệnh; nó sinh ra từ mục đích chung, từ chuẩn mực được đồng thuận, và từ cách chính bạn hành xử trong từng comment.

Bài này tập trung vào triết lý và cách gây dựng một văn hóa code review lành mạnh — tức là phần "tại sao" và "làm sao để cả đội muốn review tốt". Các phần kỹ thuật hơn như thiết lập chuẩn code, tự động hóa review bằng công cụ (linter, CI), hay pair/mob programming sẽ được bàn ở những bài sau. Ở đây, chúng ta nói về con người và văn hóa.

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

Ba mục đích thật sự của code review

Trước khi build văn hóa, cả đội phải đồng ý code review tồn tại để làm gì. Rất nhiều đội mâu thuẫn chỉ vì mỗi người ngầm định một mục đích khác nhau.

  • Bắt bug và regression. Đây là lý do hiển nhiên nhất, nhưng thú vị là nó lại không phải lý do quan trọng nhất. Nghiên cứu của Google (được công bố trong tài liệu Engineering Practices nội bộ mà họ chia sẻ ra ngoài) cho thấy phần lớn giá trị của review không nằm ở việc bắt bug logic — vì bug logic thường được test tự động bắt tốt hơn — mà nằm ở hai mục đích còn lại.
  • Chia sẻ kiến thức. Reviewer học được cách author giải quyết vấn đề; author học được góc nhìn, kỹ thuật, hoặc bối cảnh mà reviewer biết. Đây là cơ chế lan truyền tri thức mạnh nhất trong một đội kỹ thuật — mạnh hơn cả tài liệu, vì nó diễn ra ngay trên code thật, đúng lúc. Một team có review tốt sẽ không bao giờ có tình trạng "chỉ một người biết module thanh toán".
  • Giữ codebase nhất quán. Khi mười người viết code, nếu không có review, bạn sẽ có mười phong cách, mười cách đặt tên, mười cách xử lý lỗi. Review là nơi codebase được "hội tụ" về một giọng chung, giúp người đọc sau này — kể cả chính tác giả sáu tháng sau — hiểu code nhanh hơn.
Khi bạn nói rõ ba mục đích này với đội, tự nhiên hành vi review sẽ đổi. Nếu mục tiêu chỉ là "bắt bug", người ta sẽ approve ngay khi code chạy được. Nếu mục tiêu bao gồm chia sẻ và nhất quán, người ta sẽ đọc kỹ hơn và đặt câu hỏi.

Build thay vì impose: sự khác biệt cốt lõi

Impose là khi Tech Lead ra thông báo: "Từ nay mọi PR phải có ít nhất 2 approval, phải kèm test, phải qua checklist 15 mục." Nghe rất chỉn chu, nhưng nó tạo ra sự tuân thủ hình thức (compliance) chứ không tạo ra sự cam kết (commitment). Người ta sẽ tìm cách lách: approve chéo cho nhau, viết test rỗng cho đủ chỉ tiêu.

Build là khi bạn giúp đội tự thấy giá trị, cùng nhau thống nhất chuẩn mực, và biến review thành một thói quen tự nhiên. Bạn không bắt đầu bằng luật; bạn bắt đầu bằng cách làm gương và bằng những cuộc thảo luận nhỏ.

Sự khác biệt nằm ở câu hỏi: khi bạn vắng mặt hai tuần đi nghỉ, văn hóa review có tự vận hành không? Nếu có, bạn đã build được. Nếu không, bạn chỉ đang impose và làm cảnh sát.

Review là hành vi xã hội, không chỉ kỹ thuật

Đây là điều nhiều Tech Lead giỏi kỹ thuật hay bỏ qua. Một comment review không chỉ truyền tải thông tin kỹ thuật; nó truyền tải cả thái độ. Câu "Cái này sai rồi, sửa đi" và câu "Chỗ này mình lo là khi input null sẽ crash, thử thêm guard clause xem sao?" có cùng nội dung kỹ thuật nhưng tạo ra hai bầu không khí hoàn toàn khác.

Trong bối cảnh Việt Nam, yếu tố thể diện (face) lại càng nặng. Một junior bị senior comment gay gắt công khai trên PR có thể mất tự tin nhiều tuần, thậm chí âm thầm tìm việc mới. Văn hóa review lành mạnh phải tách bạch rõ: ta review code, không review con người. Comment nhắm vào dòng code, không nhắm vào người viết.

Bốn nguyên tắc nền tảng của một văn hóa review tốt

  • Tốc độ phản hồi quan trọng hơn sự hoàn hảo. Một review chậm ba ngày làm hỏng dòng chảy công việc nhiều hơn là một review sót một lỗi nhỏ. Đội nên đặt kỳ vọng: phản hồi PR trong vòng một buổi làm việc (business day).
  • Author và reviewer là cùng một phe. Cả hai cùng muốn code tốt lên. Reviewer không phải giám khảo; author không phải bị cáo.
  • Ngưỡng approve là "code này làm codebase tốt hơn", không phải "code này hoàn hảo". Đây là nguyên tắc Google gọi là "improvement over perfection". Nếu cứ chờ hoàn hảo, không PR nào được merge.
  • Bất đồng được giải quyết bằng lý lẽ và dữ liệu, không bằng thâm niên. "Vì anh là senior nên nghe anh" là dấu hiệu văn hóa đã hỏng.

Tình huống thực tế

Tình huống 1 — Startup fintech ở TP.HCM và cái phễu review 3 ngày

Một startup fintech khoảng 18 kỹ sư ở Quận 1 gặp vấn đề: thời gian trung bình để một PR được merge là 3,5 ngày. Kỹ sư bực bội vì code viết xong nằm chờ; sản phẩm bị chậm; và tệ hơn, để lách sự chậm trễ, nhiều người bắt đầu gom công việc vào những PR khổng lồ 2.000 dòng — mà PR càng to thì reviewer càng ngại đọc, càng để lâu, tạo thành vòng luẩn quẩn.

Tech Lead ban đầu phản ứng bằng cách impose: ra quy định "mọi PR phải được review trong 24 giờ". Kết quả? Người ta approve vội để khỏi vi phạm luật, chất lượng review tụt thảm hại, bug lọt ra production tăng lên.

Sau đó anh đổi cách tiếp cận sang build. Anh làm ba việc: (1) cùng đội thống nhất giới hạn PR tối đa khoảng 400 dòng, chia nhỏ công việc — PR nhỏ thì review nhanh và kỹ hơn; (2) đặt "giờ review" cố định hai lần mỗi ngày (10h và 15h) để mọi người biết khi nào có phản hồi, thay vì ép deadline cứng; (3) công khai chỉ số thời gian review trên dashboard nhưng đóng khung nó là "sức khỏe của cả đội", không phải để chỉ trích cá nhân.

Sau sáu tuần, thời gian merge trung bình xuống còn khoảng 6 giờ, và số bug lọt production giảm rõ. Bài học: vấn đề không phải là thiếu luật, mà là quy trình chưa được thiết kế cho con người. Chia nhỏ PR và tạo nhịp review đều đặn giải quyết gốc rễ tốt hơn mọi mệnh lệnh về deadline.

Tình huống 2 — Senior "gác cổng" và junior mất tự tin

Ở một công ty sản phẩm khoảng 40 kỹ sư (giả định, kiểu công ty product tại Hà Nội), có một senior rất giỏi nhưng comment review theo phong cách gay gắt: "Code này không đạt", "Sao lại viết thế này?", "Đọc lại clean code đi". Về mặt kỹ thuật anh thường đúng, nhưng bầu không khí thì độc hại. Hai junior trong team gần như sợ mở PR; một người thú nhận đã viết lại code ba lần chỉ để "né" bị anh này review.

Tech Lead nhận ra đây là vấn đề văn hóa, không phải vấn đề kỹ thuật. Cô làm mấy việc: nói chuyện riêng (1:1) với senior đó, chỉ ra tác động của cách comment lên cả đội — không phủ nhận anh đúng về kỹ thuật, nhưng nhấn mạnh mục tiêu review là nâng cả đội lên, không phải chứng minh ai giỏi hơn. Cô cũng giới thiệu một quy ước comment nhẹ nhàng lấy cảm hứng từ "Conventional Comments": gắn nhãn mỗi comment là nit: (chuyện nhỏ, không chặn merge), suggestion: (gợi ý), hay blocking: (thật sự phải sửa). Nhờ đó author biết đâu là bắt buộc, đâu chỉ là ý kiến — và reviewer buộc phải phân loại mức độ nghiêm trọng thay vì phê phán tất tần tật cùng một giọng.

Ba tháng sau, chính senior đó trở thành một trong những reviewer được đánh giá cao nhất về mặt hướng dẫn. Bài học: người review gay gắt thường không cố ý làm tổn thương — họ chỉ chưa có công cụ ngôn ngữ để phân biệt sắc thái. Tech Lead build văn hóa bằng cách trang bị công cụ và làm rõ chuẩn mực, chứ không phải bằng cách "cấm anh comment".

Tình huống 3 — Google và triết lý "improvement over perfection"

Google có một tài liệu công khai về code review được nhiều công ty tham chiếu. Một trong những nguyên tắc nổi tiếng nhất của họ: reviewer nên approve khi PR cải thiện tổng thể codebase, ngay cả khi nó chưa hoàn hảo — miễn là không có lỗi nghiêm trọng. Lý do: nếu ai cũng chờ sự hoàn hảo, PR sẽ bị treo vô tận và tác giả nản lòng.

Kèm theo đó là quy ước dùng tiền tố Nit: cho những góp ý mang tính thẩm mỹ hoặc tùy chọn, để tác giả tự quyết có sửa hay không. Điều này giúp tách bạch rõ ràng giữa "phải sửa" và "tùy em" — giảm hẳn tranh cãi vô nghĩa về những thứ như dấu cách hay tên biến.

Bài học: một văn hóa review tốt cần một cái "ngưỡng" (bar) được định nghĩa rõ. Không có ngưỡng, mỗi reviewer tự đặt tiêu chuẩn của riêng mình, và tác giả không bao giờ biết bao giờ mới đủ. Đặt ngưỡng là "làm codebase tốt hơn" giúp mọi người có chung một đích đến.

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

Đây là lộ trình để một Tech Lead build văn hóa review từ con số không, hoặc chữa một văn hóa đang hỏng.

  • Bắt đầu bằng đối thoại về mục đích. Tổ chức một buổi 30 phút, hỏi cả đội: "Theo mọi người, code review để làm gì?" Bạn sẽ thấy các câu trả lời rất khác nhau. Từ đó cùng thống nhất ba mục đích (bắt bug, chia sẻ kiến thức, giữ nhất quán) và viết ra một trang guideline ngắn.
  • Làm gương trước — bạn review kiểu bạn muốn đội review. Không có bài giảng nào mạnh bằng việc đội thấy Tech Lead comment một cách tôn trọng, giải thích lý do, khen chỗ tốt, và tự nhận khi mình sai. Văn hóa lan xuống từ hành vi của người dẫn dắt.
  • Thiết lập kỳ vọng về tốc độ, không phải deadline cứng. Ví dụ: "phản hồi PR trong một buổi làm việc". Tạo nhịp review đều (giờ review cố định) để không ai bị treo.
  • Khuyến khích PR nhỏ. Đặt hướng dẫn (không phải luật cứng) rằng PR nên dưới 400 dòng. PR nhỏ được review nhanh hơn, kỹ hơn, và ít gây mệt mỏi hơn — đây là đòn bẩy quan trọng nhất cho chất lượng review.
  • Đưa vào quy ước comment có sắc thái. Dùng nhãn như nit:, suggestion:, question:, blocking:. Điều này giải quyết phần lớn hiểu lầm về mức độ nghiêm trọng.
  • Tách con người khỏi code trong ngôn ngữ. Dạy đội nói "hàm này" thay vì "anh viết", "chỗ này có thể null" thay vì "anh quên check null". Nghe nhỏ nhưng tác động lớn.
  • Onboard reviewer mới có chủ đích. Người mới nên được ghép review cùng một reviewer có kinh nghiệm vài tuần đầu, để họ học chuẩn mực của đội qua thực hành.
  • Định kỳ nhìn lại và điều chỉnh. Trong retro, hỏi: review đang nhanh hay chậm? Có ai thấy ngại mở PR không? Guideline có còn hợp lý không? Văn hóa là thứ sống, cần chăm.

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

  • Biến mình thành cảnh sát review. Nếu mọi PR đều phải qua tay bạn, bạn vừa là nút thắt cổ chai vừa giết chết cảm giác sở hữu của đội. Mẹo: phân tán quyền review, xoay vòng reviewer, để đội tự chịu trách nhiệm.
  • Bikeshedding — tranh cãi vô tận về chuyện nhỏ. Đội dành 30 comment cãi nhau về tên biến trong khi bỏ qua một lỗ hổng logic. Mẹo: dùng nhãn nit: cho chuyện thẩm mỹ và đẩy các quy tắc format cho công cụ tự động lo (sẽ bàn kỹ ở bài về tự động hóa).
  • "LGTM" rỗng. Approve mà không đọc là phản bội mục đích của review. Mẹo: nhấn mạnh rằng approve là bạn đang bảo chứng cho code này; xây văn hóa nơi review cẩu thả cũng đáng ngại như code cẩu thả.
  • Gộp phản hồi tiêu cực dồn dập, không có lời ghi nhận. Một PR toàn comment chê sẽ khiến author kiệt sức. Mẹo: khi thấy chỗ hay, hãy nói ra — "cách xử lý lỗi ở đây gọn đấy". Ghi nhận điều tốt giúp cân bằng và khiến người ta muốn review lẫn được review.
  • Để bất đồng leo thang trên comment. Khi hai người cãi qua lại quá ba lượt trên PR, văn bản dễ gây hiểu lầm. Mẹo: chuyển sang nói chuyện trực tiếp 5 phút rồi tóm tắt kết luận lại trên PR cho người sau đọc.
  • Áp guideline của công ty khác nguyên xi. Guideline của Google hợp với Google. Mẹo: lấy cảm hứng, nhưng cùng đội tự viết phiên bản của mình — thứ họ đồng thuận thì họ mới giữ.

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

  • Khảo sát mục đích. Hỏi ít nhất ba đồng nghiệp câu "theo bạn code review để làm gì?" và ghi lại câu trả lời. So sánh sự khác biệt. Đây là dữ liệu cho thấy đội bạn có đang chung một định nghĩa hay không.
  • Viết lại comment. Lấy ba comment review "thẳng thừng" (có thể từ PR cũ của chính bạn), viết lại theo hướng tách người khỏi code và thêm nhãn sắc thái (nit:, suggestion:, blocking:). So sánh cảm giác trước và sau.
  • Soạn guideline một trang. Viết bản nháp code review guideline cho đội bạn, gồm: ba mục đích, kỳ vọng tốc độ, giới hạn kích thước PR, và bộ nhãn comment. Giới hạn đúng một trang — nếu dài hơn, không ai đọc.
  • Đo baseline. Nếu có công cụ (GitHub, GitLab), tính thời gian trung bình từ lúc mở PR đến lúc merge trong hai tuần gần nhất. Con số này là điểm khởi đầu để bạn theo dõi liệu văn hóa có đang cải thiện.
  • Tự phản tư. Trong tuần tới, mỗi lần bạn review, tự hỏi: comment này đang giúp author lớn lên hay đang chứng minh mình đúng? Ghi lại và nhìn xu hướng của chính mình.

Tóm tắt

Code review không phải là một cánh cổng kiểm soát chất lượng để áp đặt lên đội; nó là một văn hóa cần được build từ mục đích chung, chuẩn mực đồng thuận, và hành vi làm gương của người dẫn dắt. Ba mục đích thật sự của nó là bắt bug, chia sẻ kiến thức, và giữ codebase nhất quán — trong đó hai điều sau thường quan trọng hơn điều đầu.

Khác biệt then chốt là build thay vì impose: mệnh lệnh tạo ra sự tuân thủ hình thức, còn văn hóa tạo ra cam kết tự nguyện vẫn vận hành cả khi bạn vắng mặt. Muốn build được, hãy đối thoại về mục đích, làm gương, đặt kỳ vọng tốc độ thay vì deadline cứng, khuyến khích PR nhỏ, dùng ngôn ngữ tách người khỏi code, và định kỳ nhìn lại để điều chỉnh.

Ba tình huống — cái phễu 3 ngày ở startup fintech, senior gác cổng làm junior mất tự tin, và triết lý "improvement over perfection" của Google — đều cho thấy một điều: khi bạn thiết kế review cho con người, chất lượng code sẽ theo sau. Còn khi bạn thiết kế review để làm cảnh sát, bạn chỉ nhận được sự đối phó. Với vai trò Tech Lead, nhiệm vụ của bạn là làm cho cả đội muốn review tốt — chứ không phải bị buộc phải review.