Bỏ qua tới nội dung
Kiên

Một integration, nhiều supplier code

· 3 phút đọc

75 code · 31 module

Cùng một integration supplier được bán lại dưới nhiều brand code — riêng mảng hotel là 75 code chạy trên 31 module. Nước đi cám dỗ là copy module theo từng brand; cái bọn mình chạy thay vào đó là alias đăng ký theo code cộng một bảng settings thưa, kèm đúng cái failure mode mà lựa chọn này mua về.

  • config
  • white-label
  • supplier
  • dữ liệu
Nội dung
  1. Con số trước đã
  2. Nước đi cám dỗ
  3. Cái đang chạy thay vào đó
  4. Mặt trái, nói cho thẳng
  5. Cái luật

Con số trước đã

Riêng mảng hotel của gateway bọn mình, 75 supplier code chạy trên 31 module. Tính cả năm dòng sản phẩm thì cỡ 150 code trên khoảng 90 integration riêng biệt. Khoảng cách giữa hai con số đó chính là chủ đề của bài này: cùng một integration, được bán lại dưới nhiều brand code.

Đây là white-label kiểu kinh điển. Kho phòng của một wholesaler được bán dưới thương hiệu của đối tác: credentials khác, markup khác, có khi catalogue còn khoá theo một hệ ID khách sạn khác — nhưng giao thức, hình dạng request, các tật riêng, tất cả y hệt nhau, vì đứng sau từng ấy code vẫn là đúng một hệ thống supplier.

Nước đi cám dỗ

Lúc brand thứ hai xuất hiện, việc nhanh nhất trên đời là copy cái module. Nhân đôi folder, đổi tên class, thay credentials, ship. Nó chạy, ship được ngay hôm nay, và cái diff review dễ ợt vì toàn file mới.

Cái giá đến sau, và đến theo cấp số nhân. Mỗi bản fix tương lai giờ phải đáp xuống N chỗ — tìm ra bug timeout ở một bản copy, rồi nhớ, hoặc quên, các bản còn lại. Tệ hơn phép nhân là sự trôi dạt: các bản copy lệch nhau trong im lặng, vì không có gì bắt chúng phải lệch nhau thành tiếng. Bản copy số ba nhận được bản fix retry còn bản số năm thì không, và không compiler, không test, không diff nào sẽ đặt hai file đó cạnh nhau mà phản đối. Ở mức 75 code, chiến lược copy theo brand nghĩa là một bug phải sửa tới 75 lần. Còn trên thực tế nó sẽ tốn của bọn mình bao nhiêu bản fix thì mình không đếm được — bọn mình chưa bao giờ chạy theo kiểu đó, và đấy chính là cái ý.

Cái đang chạy thay vào đó

Mỗi hệ thống supplier một module, viết theo cái contract cố định mà module nào cũng phải implement, và đăng ký vào registry duy nhất theo từng code — alias là một dòng đăng ký, không phải một nhánh fork. Bảy mươi lăm cái tên, ba mươi mốt bản cài đặt.

Khác biệt giữa các brand sống trong dữ liệu. Một bảng settings thưa giữ, theo từng supplier code, chỉ những key khác với default — credentials, endpoint, dăm ba công tắc hành vi mà brand đó thật sự cần. "Thưa" là chữ gánh lực: một row không chép lại default, nên đọc một row là thấy đúng và chỉ những gì làm brand này đặc biệt. Thêm một cái map ghi lại catalogue của từng supplier code khoá theo cột hotel-ID nào, vì cùng một toà nhà mang một ID khác nhau ở mỗi supplier, và một brand có thể bán lại catalogue dưới thêm một hệ ID nữa.

Hành vi của brand trở thành dữ liệu. Thêm brand thứ bảy mươi sáu là một dòng registry cộng một row settings, không phải một buổi code review.

Mặt trái, nói cho thẳng

Lựa chọn này có một failure mode, mà là loại khó chịu: một row settings sai giờ là một bug production mà không code diff nào sẽ cho thấy. Module thì đúng. Test thì pass, vì test chạy trên module. Cái MR làm hỏng brand đó không tồn tại, vì chẳng có gì được merge cả — có người viết một row, và row đó sai.

Phòng thủ duy nhất là đối xử với dữ liệu bằng đúng cái kỷ luật mà diff từng cho không bạn: ghi xong một row settings thì đọc ngược nó lại, xem cấu hình sau khi merge default vào thực sự nói gì, rồi mới cho brand đó lên sóng. Công cụ chuẩn để với tới database này là một script query nhỏ chứ không phải mysql client thường, và chạy bước đọc ngược qua nó tốn đúng một câu SELECT. Thói quen chính là bản fix; không có gì về mặt cấu trúc ép được nó.

Cái luật

Khi các biến thể của cùng một thứ sinh sôi, hãy đưa phần biến thiên vào dữ liệu và giữ bộ máy là một — một module, nhiều code, khác biệt nằm ở row. Nhưng phải nói to cái bạn vừa đánh đổi: bạn đã dời bề mặt bug ra khỏi code diff, nơi review và test đang sống, sang các row, nơi chẳng có gì sống cả trừ khi bạn tự xây thói quen đọc ngược chúng. Phép nhân bạn né được là có thật. Cái chỗ trốn mới của bug cũng có thật.