5 Năm Trước: Sự Ngỡ Ngàng Của Một Mid-Level Khi Nhận "Cục Tạ" Monorepo... Chạy Bằng Bazel

Năm năm trước, khi tôi còn là một Mid-level đang quen với những dự án Simple Repo (Polyrepo) cứ npm run dev hay go run main.go là chạy, thì team tôi nhận bàn giao một cụm dự án khổng lồ.
Anh Tech Lead team bạn gửi repo kèm một câu dặn dò mà lúc đó tôi chưa hiểu hết độ "nặng đô" của nó: "Code chung một repo hết nhé, bọn anh dùng Bazel để build".
Tôi hí hửng git clone về, hí hửng mở code lên và... hoàn toàn đứng hình. Không có những file script quen thuộc. Đập vào mắt tôi là hàng chục file mang tên WORKSPACE và BUILD.bazel rải rác khắp các thư mục. Đó là khởi đầu cho chuỗi ngày "vỡ mật" nhưng đáng giá nhất trong sự nghiệp của tôi.
1. Cú Sốc Mang Tên "Cái Gì Cũng Phải Khai Báo" (Explicit Dependencies)
Với một Mid-level thời đó, tư duy của tôi là: muốn dùng thư viện gì thì cứ import, thiếu thì cài thêm vào package.json hoặc go.mod. Nhưng bước vào thế giới của Bazel, quy luật đó hoàn toàn bị phá vỡ.
Bazel hoạt động theo triết lý: Hermetic Computing (Tính toán khép kín). Nghĩa là nó không tin tưởng bất cứ thứ gì có sẵn trên máy của bạn.
Một file code ở
service-amuốn gọi một hàm helper ởshared-lib? Không đơn giản là gõ đường dẫn tương đối. Tôi phải vào fileBUILD.bazelcủaservice-a, khai báo tường minh rằng: "Tôi chuẩn bị phụ thuộc vào cái target//packages/shared-libnày đây".Quên khai báo? Bazel sẽ lập tức báo lỗi ngay khi build, dù cho IDE của bạn có nhận được code đi chăng nữa.
Tuần đầu tiên tiếp quản, tôi dành một nửa thời gian chỉ để... học cú pháp Starlark (một dạng của Python) để viết các file BUILD. Cảm giác lúc đó vừa ức chế, vừa tự hỏi: "Tại sao người ta lại tự làm khó mình thế này?"
2. Và Rồi... "Phép Màu" Xuất Hiện Khi Hệ Thống Phình To
Sau khi vượt qua được rào cản cấu hình, bắt đầu vào guồng fix bug và tính năng mới, tôi mới nhận ra Bazel không phải là một công cụ "hành xác", mà nó là một kiệt tác kỹ thuật dành cho Monorepo quy mô lớn.
Hệ thống bàn giao về có tới gần chục service lớn nhỏ. Nếu chạy CI/CD thông thường cho một Monorepo, mỗi lần tôi push code, hệ thống sẽ mất cả tiếng đồng hồ để test và build lại mọi thứ. Nhưng với Bazel, câu chuyện hoàn toàn khác:
"Affected Build" và "Caching" ở đẳng cấp tối thượng
Bazel hiểu rõ sơ đồ phụ thuộc (Dependency Graph) của toàn bộ repo như lòng bàn tay. Khi tôi sửa một dòng code trong service-frontend-a:
Bazel thừa biết thay đổi này chẳng liên quan gì đến
service-backend-bhayservice-mobile.Khi chạy lệnh build, nó chỉ build đúng
service-frontend-a.Còn đống service còn lại? Bazel lôi từ trong Cache ra (thậm chí là Remote Cache chia sẻ giữa máy tôi và Server CI/CD) với tốc độ tính bằng mili-giây.
Slogan của Bazel: "Correct, Choose two: Fast or Reproducible."(Với Bazel, bạn có cả hai. Build một lần là chuẩn cả đời, không bao giờ có chuyện "Code chạy trên máy em nhưng lỗi trên server").
Lần đầu tiên trải nghiệm Monorepo đa ngôn ngữ (Polyglot)
Dự án bàn giao về không chỉ dùng một ngôn ngữ. Nó có Frontend bằng TypeScript, một service core bằng Go, và vài script automation bằng Python. Nếu không có Bazel, team tôi sẽ phải cài đủ thứ runtime (Node, Go, Python) trên máy local và cấu hình quyền chạy rất phức tạp. Với Bazel, nó tự động tải đúng phiên bản Go, đúng phiên bản Node biệt lập về một thư mục ẩn và tự chạy. Tôi chỉ cần gõ đúng một lệnh duy nhất: bazel test //... là toàn bộ test case của cả ba ngôn ngữ cùng chạy song song, mượt mà.
Lời Kết
Năm năm trước, việc tiếp quản một Monorepo chạy Bazel giống như việc một tài xế đang quen lái xe số sàn phân khối nhỏ bỗng nhiên bị đẩy lên buồng lái của một chiếc Boeing 747. Cực kỳ ngợp, bảng điều khiển dày đặc nút bấm, và chỉ một sai sót nhỏ trong file cấu hình cũng khiến "máy bay" không thể cất cánh.
Nhưng chính cú va chạm nảy lửa với Bazel năm đó đã rèn cho một Mid-level như tôi một tư duy cực kỳ khắt khe về Dependency Management (Quản lý phụ thuộc) và Build System. Nó buộc tôi phải hiểu sâu xuống tận tầng kiến trúc: Code của mình thực sự được biên dịch như thế nào, hệ thống CI/CD vận hành ra sao. Đó là bước đệm vô giá để tôi không còn sợ bất kỳ hệ thống quy mô lớn (Enterprise) nào sau này.
Bài viết liên quan
Phát triển phần mềmGóc Nhìn "Reverse LSP": Khi Bản Năng Sinh Tồn Buộc Bạn Phải Vi Phạm Nguyên Tắc
SOLID không phải là một tôn giáo, và các nguyên tắc thiết kế không phải là những điều răn bất di bất dịch. Đứng ở góc độ một Tech Lead thực chiến, đôi khi quyết định bẻ gãy nguyên tắc Liskov Substitution Principle (LSP) lại là lựa chọn trưởng thành để cứu sống hệ thống. Hãy cùng phân tích 4 kịch bản trade-off kinh điển và nghệ thuật khoanh vùng 'mã độc' an toàn.
Phát triển phần mềmBản Hiến Chương Đen Của Ngành Dầu Khí: Khi Kiến Trúc Code Quyết Định Sự Sống Còn
"Chuyện gì sẽ xảy ra nếu một lỗi thiết kế kiến trúc không chỉ tạo ra vài dòng bug, mà phải trả giá bằng mạng người? Hãy bước lên một giàn khoan bán chìm để hiểu vì sao Nguyên lý OCP và Dagger 2 không phải lý thuyết sách vở — chúng là bản hiến chương sinh tử của những hệ thống lõi." Độ dài: 247 ký tự (đã tính cả khoảng trắng). Phù hợp nhất cho: Thẻ mô tả (Meta Description) khi chia sẻ lên Viblo, Facebook, hoặc LinkedIn để kích thích người đọc click vào bài viết ngay lập thể.
Phát triển phần mềm
Thảo luận
0 bình luận
Hãy là người đầu tiên thảo luận.