Supplier vẫn đang nói XML
Một phần lớn API supplier đứng sau gateway của bọn mình là SOAP/XML, nằm cạnh đám JSON cứ như thể REST chưa từng được phát minh ra. Bạn không được chọn; contract của supplier là contract của supplier.
Mà response thì không hề nhỏ. Tài liệu tích hợp của bọn mình gọi tên hai pattern offer: pattern A — supplier trả một token duy nhất book cả N phòng, và pattern B — giá của từng phòng độc lập với nhau, và danh sách offer chính là cái ma trận đã vật chất hoá của mọi tổ hợp phòng-giá hợp lệ. Dưới pattern B, một response search có thể chở hàng nghìn tổ hợp giá. Việc parse thôi không còn là chú thích cuối trang, mà thành một thao tác khối lượng lớn chạy trên mỗi lượt search.
Hai cách đọc
Cách hiển nhiên là DOM walk: parse nguyên document thành một cái cây trong bộ nhớ, rồi viết code tay đi dạo trên cây, nhặt giá trị và ráp thành JSON. Ở cỡ nhỏ thì cách này ổn, tutorial nào cũng làm vậy. Ở cỡ hàng nghìn tổ hợp, bạn đang giữ hai bản sao của mọi thứ cùng lúc — cả cái DOM đầy đủ lẫn đám object đang ráp từ nó — bên trong một worker đang làm việc này cho nhiều supplier song song.
Cách bọn mình chọn là mapping khai báo: camaro để đọc response, xmlbuilder để viết request. Với camaro, mapping là một template — field JSON này lấy từ path này, mảng này lấy từ những node kia — còn việc duyệt cây là của thư viện. Cái transform bạn bảo trì là dữ liệu, không phải code.
Nói thẳng cái chưa đo: không có con số bộ nhớ trước/sau nào được ghi lại cho lựa chọn này, nên mình không nói được cú DOM walk sẽ tốn bao nhiêu ở đây. Chỗ duy nhất trên site này có một phép đo bộ nhớ thật là bài học về Redis, và bài này không phải chỗ đó. Lý lẽ cho cái template đứng trên những chân khác.
Cái gì làm XML của supplier khó, ngoài kích thước
Kích thước là vấn đề ít thú vị nhất. Ba thứ này cắn đau hơn.
Node tuỳ chọn. Một element chính sách huỷ có ở offer này mà vắng ở offer kia. Cú DOM walk với tay xuyên qua nó sẽ crash đúng ở cái response thiếu nó — thường là trên production, ở đúng cái supplier hay bỏ trống.
Một element ở chỗ bạn tưởng là mảng. XML không có khái niệm mảng. Hai phòng đứng cạnh nhau trông như một list; một phòng trông như một object đơn. Cú walk viết theo mẫu hai phòng sẽ vỡ trên response một phòng, mà response một phòng lại đúng là ca test data của bạn chưa từng có. Template cho bạn khai báo "chỗ này luôn là mảng" đúng một lần, và hình dạng dữ liệu thôi phụ thuộc vào số đếm.
Namespace mỗi supplier một kiểu. Cùng một document về mặt logic nhưng đến từ các supplier với prefix khác nhau, có khi khác cả giữa các endpoint của cùng một supplier. Trong cú walk, cái hiểu biết đó bị trét mỏng ra khắp mọi lần truy cập node. Trong template, nó được khai báo ở đầu, một lần.
Lý lẽ về review
Cái thắng lợi lặng lẽ nhất không nằm trong đám trên. Một mapping viết thành template thì người chưa từng đọc parser cũng review được. Trong merge request, template đọc như một cuốn từ điển dữ liệu: field, path, kiểu. Reviewer mở response mẫu của supplier ở một cửa sổ, template ở cửa sổ kia, và soát từng dòng đối từng dòng. Còn DOM walk thì chỉ có thể debug — không thể xác minh nó bằng cách đọc, chỉ có thể chạy rồi xem.
Với khoảng 90 integration riêng biệt đứng sau cỡ 150 supplier code, viết mapping mới và sửa mapping cũ là việc thường nhật, ai nhận ticket thì người đó làm. Cái template là thứ khiến chuyện đó thường nhật được.
Cái luật
Dưới một ngưỡng khối lượng nào đó, chọn parser là khẩu vị. Trên ngưỡng đó, nó là kiến trúc: hình dạng bộ nhớ, hình dạng lỗi, và — phần cộng dồn theo thời gian — hình dạng review. Hãy ưu tiên cách biểu diễn transform mà đồng nghiệp kiểm tra được không cần chạy nó. Template viết lần đầu chậm hơn. Nhưng nhanh hơn ở mọi lần sau, và nó là phiên bản duy nhất của cái transform mà một buổi code review thật sự đọc được.