VPS

Monorepo: khi nào đáng gộp, khi nào nên tách

Thanh Nguyễn Đăng 9 phút đọc 2 khối lệnh

Monorepo: khi nào đáng gộp, khi nào nên tách
Mục lục bài viết
  1. Bốn dấu hiệu nên gộp
  2. Ba dấu hiệu nên tách
  3. Chi phí thật của mỗi hướng
  4. Cấu trúc monorepo hợp lý
  5. Đây là quyết định đảo ngược được
  6. Chi phí thật của mỗi hướng, nhìn theo đầu việc
  7. Câu hỏi phân biệt rõ nhất
  8. Nếu gộp thì phải chuẩn bị gì
  9. Vì sao đây là quyết định đảo ngược được
  10. Câu hỏi thường gặp
  11. Bài viết liên quan

Trả lời nhanh: Chọn monorepo hay tách nhiều repo không phải câu hỏi kỹ thuật mà là câu hỏi về cách đội làm việc. Nên gộp khi các phần thay đổi cùng nhau: sửa một tính năng phải đụng cả giao diện lẫn API, hoặc nhiều ứng dụng dùng chung một thư viện nội bộ. Nên tách khi các phần có vòng đời độc lập: khác đội sở hữu, khác nhịp phát hành, khác quyền truy cập. Chi phí của monorepo là công cụ; chi phí của tách repo là sự đồng bộ.

Chủ đề này hay bị tranh luận theo kiểu chọn phe, trong khi câu trả lời đúng phụ thuộc vào việc các phần trong hệ thống của bạn có thay đổi cùng nhau hay không. Bài này đưa ra các dấu hiệu cụ thể thay vì nguyên tắc chung chung.

Bốn dấu hiệu nên gộp

  • Một thay đổi thường đụng nhiều phần. Thêm một trường vào đơn hàng phải sửa API, giao diện web và ứng dụng di động. Với repo tách, đó là ba pull request phải phối hợp thứ tự phát hành.
  • Có thư viện dùng chung. Các kiểu dữ liệu, hàm tiện ích, thành phần giao diện. Với repo tách, mỗi lần sửa thư viện là một vòng phát hành nội bộ rồi mới cập nhật ở nơi dùng.
  • Đội nhỏ, ai cũng chạm mọi phần. Khi đó việc phải mở năm repo để làm một việc là phiền phức thuần túy.
  • Muốn đổi tên hoặc cấu trúc lại xuyên suốt. Với monorepo là một lần sửa, với repo tách là một dự án nhỏ.

Dấu hiệu đầu tiên quan trọng nhất. Nếu bạn thường xuyên phải phối hợp thời điểm phát hành giữa các repo, đó là tín hiệu rõ ràng rằng chúng vốn thuộc về nhau.

Ba dấu hiệu nên tách

  • Chủ sở hữu khác nhau. Hai đội độc lập, nhịp làm việc khác nhau, không muốn phụ thuộc vào nhau khi phát hành.
  • Quyền truy cập khác nhau. Một phần chứa mã nguồn nhạy cảm mà không phải ai cũng nên đọc. Với monorepo, ai đọc được repo là đọc được tất cả.
  • Vòng đời khác hẳn. Một dịch vụ ổn định sửa vài lần mỗi năm nằm chung với một ứng dụng thay đổi hằng ngày thì lịch sử thay đổi trở nên khó theo dõi.

Ngoài ra còn một lý do thực dụng: repo quá lớn làm chậm mọi thao tác. Nhưng ngưỡng đó rất cao, và phần lớn đội ở Việt Nam sẽ không chạm tới nó.

Chi phí thật của mỗi hướng

Monorepo tốn công cụ. Bạn cần cách chạy tác vụ chỉ cho phần thay đổi, nếu không mỗi lần sửa một dòng là chạy lại toàn bộ kiểm thử. Đó là lý do các công cụ điều phối tồn tại, xem bài về Turborepo. Cộng thêm cách quản lý gói phù hợp, xem bài về pnpm.

Repo tách tốn công đồng bộ. Mỗi thay đổi xuyên nhiều phần là nhiều pull request phải phối hợp. Thư viện dùng chung phải phát hành phiên bản rồi cập nhật ở nơi dùng. Và khi có sự cố, việc lần theo một luồng đi qua ba repo mất thời gian hơn hẳn.

Cách so đơn giản: đếm số lần trong tháng vừa rồi bạn phải sửa nhiều repo cho một việc. Con số cao nghĩa là chi phí đồng bộ đang lớn hơn chi phí công cụ.

Cấu trúc monorepo hợp lý

TerminalCấu trúc monorepo hợp lýbash
repo/  apps/    web/            # ung dung web    mobile/         # ung dung di dong    api/            # dich vu backend  packages/    types/          # kieu du lieu dung chung    ui/             # thanh phan giao dien dung chung    config/         # cau hinh dung chung

Hai quy tắc giữ cho nó không rối:

  • Gói dùng chung không được phụ thuộc ngược vào ứng dụng. Chiều phụ thuộc luôn đi một hướng, nếu không bạn tạo ra vòng lặp và công cụ không tính được thứ tự chạy.
  • Mỗi gói có chủ sở hữu rõ ràng, khai báo trong file quy định người xem lại. Không có nó thì mọi thay đổi đều làm phiền cả đội.

Đây là quyết định đảo ngược được

Điểm cuối và cũng là điểm đáng nhớ nhất: bạn tách một gói ra khỏi monorepo được, và gộp nhiều repo lại được. Cả hai đều tốn công nhưng không phải là ngõ cụt.

Vì vậy đừng dành hai tuần tranh luận. Với đội nhỏ dưới mười người và các phần thường thay đổi cùng nhau, bắt đầu bằng monorepo là mặc định hợp lý. Khi một phần thật sự cần vòng đời độc lập, tách nó ra lúc đó.

Về hạ tầng, monorepo cần máy CI với dung lượng rộng hơn vì bạn giữ bộ nhớ đệm cho nhiều gói, và ổ đĩa nhanh vì các thao tác đụng tới rất nhiều file. Cách bố trí nằm ở bài về cache dùng chung.

Chi phí thật của mỗi hướng, nhìn theo đầu việc

Đầu việcKho gộpKho tách
Đổi một giao diện dùng chungMột lần sửa, mọi nơi cùng cập nhậtSửa ở gốc, phát hành, rồi nâng phiên bản ở từng nơi
Chạy kiểm thử khi có thay đổi nhỏCần công cụ lọc, nếu không thì chạy thừa rất nhiềuChỉ chạy đúng kho bị đổi
Phân quyền theo nhómKhó, thường phải dùng cơ chế chủ sở hữu theo thư mụcDễ, quyền đặt ở mức kho
Người mới vào việcMột lần tải, thấy toàn cảnhPhải dựng nhiều kho và hiểu cách chúng nối nhau
Quay lui khi phát hành hỏngMột lần quay lui cho mọi phầnPhải xác định đúng kho nào cần quay lui

Câu hỏi phân biệt rõ nhất

Hãy hỏi: trong ba tháng qua, bao nhiêu phần trăm số thay đổi phải chạm vào hơn một dự án cùng lúc? Nếu con số đó trên ba mươi phần trăm, chi phí điều phối giữa các kho đang lớn hơn chi phí quản lý một kho gộp. Nếu dưới mười phần trăm, gộp lại chỉ tạo thêm việc mà không giải quyết vấn đề nào có thật.

Nếu gộp thì phải chuẩn bị gì

TerminalNếu gộp thì phải chuẩn bị gìbash
# Ba thu bat buoc phai co truoc khi gop, khong phai sau: # 1. Cong cu chi chay lai phan bi anh huong#    Khong co no, moi thay doi nho deu chay het toan bo, doi rat lau # 2. Quy tac chu so huu theo thu muc#    De yeu cau gop ma tu dong den dung nguoi can xem # 3. Quy uoc ranh gioi giua cac goi con#    Goi con nao duoc phu thuoc vao goi con nao, viet ra va kiem tu dong # Kiem tra lich su duoc giu lai sau khi gop:git log --follow duong/dan/tep-cu.ts

Vì sao đây là quyết định đảo ngược được

Tách một kho gộp ra thành nhiều kho, hoặc ngược lại, đều làm được và giữ được lịch sử thay đổi. Điều đó có nghĩa là bạn không cần bàn ba tháng để chọn. Chọn hướng phù hợp với cách đội đang làm việc hôm nay, đặt lịch xem lại sau sáu tháng. Cái đắt không phải là chọn sai, mà là để tình trạng nửa vời kéo dài: vài phần đã gộp, vài phần còn tách, không ai biết quy tắc là gì.

Câu hỏi thường gặp

Monorepo có làm mọi thứ chậm hơn không?

Chỉ khi bạn chưa có công cụ chạy tác vụ theo phần thay đổi. Với công cụ điều phối và bộ nhớ đệm đúng cách, sửa một gói chỉ chạy lại gói đó và những gói phụ thuộc, nên thường nhanh hơn.

Đội nhỏ nên chọn hướng nào?

Thường là gộp, vì đội nhỏ ai cũng chạm mọi phần và các thay đổi hay đụng nhiều nơi cùng lúc. Chi phí công cụ của monorepo nhỏ hơn nhiều so với công phối hợp giữa nhiều repo.

Có thể tách ra sau không?

Được. Tách một gói khỏi monorepo là việc tốn công nhưng làm được, và Git có công cụ giữ lại lịch sử của phần được tách. Đừng coi quyết định này là vĩnh viễn.

Monorepo cần máy CI thế nào?

Dung lượng rộng hơn vì giữ bộ nhớ đệm cho nhiều gói, và ổ đĩa nhanh vì mọi thao tác đụng tới rất nhiều file. RAM thì tùy vào việc bạn chạy song song bao nhiêu tác vụ.

Chia sẻ:Facebook

Thanh Nguyễn

TND

Tư vấn bản quyền, VPS và máy chủ kèm hóa đơn VAT, hợp đồng đầy đủ cho doanh nghiệp.