Hồi mới đi làm, mình từng ngồi cả buổi chiều để deploy một bản build lên server. Mở terminal, gõ tay từng lệnh, copy file, sửa config, restart service — xong thì thở phào. Đến lần deploy sau, mình quên mất một bước, và cả team ngồi chờ hệ thống sập để tìm ra chỗ sai. Lúc đó mình mới thấm: nếu một việc lặp lại nhiều lần mà vẫn phải làm bằng tay, sớm muộn nó cũng sẽ sai.

Topic 51 của The Pragmatic Programmer gọi đó là Pragmatic Starter Kit — bộ ba nền tảng mà mọi dự án đều cần, bất kể dùng ngôn ngữ hay framework gì.

Ba chân ghế của mọi dự án

Tác giả ví bộ ba này như ba chân của một cái ghế: thiếu một chân thì ngồi kiểu gì cũng chông chênh.

  • Version Control — mọi thứ cần để build dự án đều nằm trong version control.
  • Regression Testing — test tự động, chạy liên tục, không khoan nhượng.
  • Full Automation — biến mọi quy trình lặp lại thành tự động, chạy được trên bất kỳ máy nào.

Nghe thì đơn giản, nhưng cái khó nằm ở chỗ biến nó thành phản xạ hằng ngày chứ không phải checklist để cuối dự án mới mang ra xem.

Version control không chỉ để lưu code

Phần lớn mọi người nghĩ Git là chỗ cất code, hết. Nhưng trong starter kit này, version control còn điều khiển cả build, test và release.

Ý tưởng cốt lõi: build machine phải là thứ dùng xong vứt được. Không cần một con server cũ kỹ nằm góc văn phòng mà ai cũng sợ chạm vào. Máy build cứ tạo theo nhu cầu, chạy xong thì hủy. Deployment config cũng nằm trong version control, nên release lên production chạy hoàn toàn tự động.

Nghe quen không? Đây chính là nền tảng của CI/CD hiện đại. Push một commit, pipeline tự build trong container, test xong thì tag một cái để release. Release thành việc bình thường hằng ngày, không còn là nghi lễ nín thở nửa đêm.

Dây chuyền robot tự động trong nhà máy Ảnh: Pexels

Test sớm, test nhiều, test tự động

Nhiều dev test một cách nhẹ nhàng, trong tiềm thức biết chỗ nào dễ vỡ thì né ra. Pragmatic Programmer thì ngược lại: tìm bug ngay bây giờ, để không phải chịu cảnh người khác tìm ra bug của mình sau này.

Tác giả so việc bắt bug như đi đánh cá bằng lưới. Lưới nhỏ (unit test) bắt cá con, lưới lớn (integration test) bắt cá mập. Cá lọt lưới thì vá lại chỗ rách.

Một điểm đáng chú ý: dự án tốt có thể có lượng code test nhiều hơn code production. Nghe tốn công, nhưng lâu dài lại rẻ hơn, và quan trọng hơn là mình có niềm tin thật sự khi nói một đoạn code đã "xong". Không có test thì "xong" chỉ là cảm giác.

Sách liệt kê bốn nhóm test chính mà một build tự động nên cover:

  • Unit test — test từng module riêng lẻ. Các phần không tự chạy đúng thì ghép lại cũng không đúng.
  • Integration test — xem các subsystem có ăn khớp không. Sách nói thẳng: đây thường là nguồn bug lớn nhất.
  • Validation & Verification — user nói họ muốn cái này, nhưng đó có phải cái họ cần? Hệ thống không bug mà giải sai bài toán thì vẫn vô dụng.
  • Performance test — có đáp ứng được yêu cầu khi chạy thật không, với đủ số user, connection, transaction mỗi giây?

Lập trình viên làm việc với code trên màn hình Ảnh: Pexels

Chỗ khó khi áp dụng: môi trường test vẫn khác production

Sách nhấn mạnh phải "test cho thật" — test environment càng giống production càng tốt, vì mọi khoảng cách giữa hai môi trường đều là chỗ bug sinh sôi.

Nhưng đây cũng là chỗ khó nhất. Container ở máy dev chỉ giống production được đến một mức nào đó. Production còn có load balancer thật, network latency thật, dữ liệu thật với đủ trường hợp kỳ cục mà dữ liệu seed không bao giờ mô phỏng hết. Rồi chi phí nữa — dựng staging đủ giống production tốn tiền thật, team nhỏ thường phải nhắm mắt chấp nhận khoảng cách đó.

Cách mình chọn: thay vì cố làm cho giống bằng mọi giá, mình xác định rõ khác biệt nào chấp nhận được và ghi lại. Biết mình đang mù chỗ nào quan trọng hơn là tưởng mình thấy hết.

Bài học rút ra

  • Việc gì phải làm lại lần thứ ba bằng tay thì đưa vào script. Quy trình thủ công để tính nhất quán cho may rủi, nhất là khi mỗi người hiểu một kiểu.
  • Version control nên điều khiển build, test và release — build machine dùng xong vứt được, release chỉ là một cái tag.
  • Viết test ngay khi có code. Cá con lớn thành cá mập rất nhanh, bắt cá mập khó hơn nhiều.
  • "Xong" chỉ có nghĩa khi tất cả test đã chạy qua. Cảm giác code chạy được không phải bằng chứng.
  • Integration test thường là nơi bug tập trung nhiều nhất — hợp đồng giữa các subsystem phải rõ và được test nghiêm túc.

Ba chân ghế này không phải thứ đọc rồi gật gù, mà phải dựng trước khi viết dòng code nghiệp vụ đầu tiên. Dựng sớm thì nhẹ; dựng muộn thì mỗi lần release lại là một lần nín thở.

Vậy còn bạn — trong ba chân ghế này, chân nào dự án của bạn đang yếu nhất?

Xem các bài viết khác