From 48k lines of code to 10: the story of GitHub's JavaScript SDK

Bài tóm tắt GitHub 2020 4. Điều chỉnh Độ khó: Trung bình

GitHub · 2020 · 4. Điều chỉnh · Độ khó: Trung bình — bài gốc

Bối cảnh

  • @octokit/rest khởi đầu là package cộng đồng github (commit đầu 6/2010, thời Node v0.1). Năm 2017 GitHub nhận nó làm SDK chính thức cho REST API, chạy cả Node lẫn trình duyệt; lúc đó khoảng 16.000 dòng, lõi là routes.json gần 8.000 dòng viết tay định nghĩa mọi endpoint, endpoint chỉ được thêm/sửa khi có người phát hiện thiếu.

Thay đổi chính

  • Sinh định nghĩa từ tài liệu: một script cào tài liệu REST API mỗi đêm thành JSON máy đọc được (octokit/routes); có thay đổi thì tự mở PR cho SDK, merge xong tự release. Định nghĩa lên 10.275 dòng và đầy đủ, type definition hơn 26.700 dòng.
  • Tách lõi (1/2018 → 2020): kiến trúc plugin; tách dần @octokit/endpoint (option → request HTTP), @octokit/request, before-after-hook; dùng plugin nội bộ khoảng sáu tháng rồi mới công bố plugin API ở v16 (11/2018). Sau đó viết @octokit/core không mang tính năng deprecated, chưa dùng ngay trong @octokit/rest để tránh breaking change; mỗi cách xác thực thành một package riêng.
  • Plugin kiểm tham số phía client bị bỏ vì TypeScript đã kiểm lúc compile; định nghĩa một endpoint co từ vài chục dòng schema còn một dòng "POST /repos/{owner}/{repo}/check-runs". v17 của @octokit/rest còn 10 dòng ghép core với ba plugin.
  • Test làm lưới an toàn khi đổi mọi dòng: biến ví dụ sử dụng thành integration test; octokit/fixtures là bộ mock HTTP không phụ thuộc ngôn ngữ, tự cập nhật; giữ coverage 100% (test fail nếu tụt); chạy test của v16 trên v17 (trừ API deprecated), xong thì dời test về đúng package.

Vì sao

  • Mục tiêu đầu là bảo trì được (định nghĩa luôn đủ, không phụ thuộc người nhớ), sau là decomposable: trình duyệt quan tâm kích thước bundle nên người dùng phải chọn được thư viện cấp thấp thay vì một khối chứa mọi endpoint, mọi cách xác thực.

Bài học cho SWE

  • Thứ phải khớp với một nguồn sự thật (tài liệu API) thì sinh ra từ nguồn đó theo lịch, đừng bảo trì tay.
  • Tách thư viện nguyên khối theo đường: plugin nội bộ trước, dùng đủ lâu, rồi mới công bố API và tách package; lõi mới nằm cạnh cái cũ cho tới khi sẵn sàng.
  • Viết lại mọi dòng an toàn nhờ chạy test của bản cũ trên bản mới, rồi mới dọn test.

Liên quan