Nguyen Le PhongNguyen Le Phong

Ghi quyết định kiến trúc cho người đến sau

Code chỉ cho thấy hình dạng cuối cùng, không cho biết vì sao nó ra đời. Một ghi chú kiến trúc ngắn giữ lại trade-off, hướng đã bỏ và lúc nên xem lại để người đến sau thay đổi hệ thống an toàn hơn.

Hai tháng sau, một người mới mở codebase và gặp một đoạn kiến trúc hơi lạ. Code vẫn chạy, test vẫn xanh, nhưng không thứ gì nói cho họ biết vì sao cả đội từng chọn hình dạng này. Hôm thứ Sáu quyết định được đưa ra, mọi người còn nhớ rất rõ: một bên lo rủi ro sự cố, một bên nhìn tới roadmap dài hơn. Sang thứ Hai, phần bối cảnh ấy đã bắt đầu mỏng.

Chuỗi quyết định nối ngữ cảnh, lựa chọn, hệ quả và điều kiện cần xem lại.
Người đến sau cần biết vì sao đã chọn và khi nào nên mở lại quyết định, không chỉ biết kết quả cuối.

Quyết định kiến trúc thường hỏng ở vai trò trí nhớ trước khi hỏng ở vai trò thiết kế. Hệ thống vẫn vận hành, nhưng lý do đằng sau ranh giới và phụ thuộc không còn ai dễ dàng khôi phục. Từ đó, mỗi lần refactor lại mở đầu bằng một cuộc khai quật: chỗ này là chủ ý hay vô tình, thỏa hiệp cũ còn cần không, dependency kia là lỗi hay một phần lịch sử chưa được kể?

Không cần dựng một tài liệu đồ sộ. Đó có thể là ADR ngắn, một ghi chú thiết kế trong repo hay một đoạn trong spec. Phần cốt lõi khá ổn định: câu hỏi lúc ấy là gì, hướng nào được chọn, hướng nào bị bỏ, vì sao đội chọn như vậy, món nợ nào được chấp nhận và tín hiệu nào sẽ khiến quyết định cần được xem lại.

Các phương án bị loại đáng ghi hơn ta thường nghĩ. Thiếu chúng, người đọc sau này dễ lặp lại y nguyên cuộc tranh luận cũ nhưng có ít bối cảnh hơn. Vài dòng giải thích vì sao đội không dùng shared database, chưa đưa queue vào hay vẫn để module trong monolith có thể tiết kiệm nhiều giờ “tái khám phá”. Nó cũng giữ được sự thật rằng quyết định chỉ là đáp án phù hợp nhất với quy mô, lưu lượng, deadline và năng lực vận hành ở thời điểm đó.

Trí nhớ kiến trúc tốt bảo vệ con người chứ không riêng code. Người mới có thể đặt câu hỏi sâu mà không thấy mình đang thách thức cá nhân nào. Người bảo trì có thể thay quyết định mà không cần kết luận đội cũ làm ẩu. Người duyệt có một hiện vật chung để dựa vào, thay vì để người nói tự tin nhất trong phòng định nghĩa lại quá khứ.

Ghi chú có sức sống nhất khi được viết sát lúc công việc diễn ra. Đợi dự án kết thúc mới viết, ta dễ tạo ra một bản lịch sử đã đánh bóng. Viết lúc trade-off còn nóng mới giữ được những chi tiết nhỏ thường bay mất: deadline của khách hàng, sự cố khiến đội thận trọng, đường migration quá tốn kém hay khoảng trống kiểm thử khiến một lối tắt không thể chấp nhận.

Tôi thích khép một ADR bằng điều kiện xem lại. Lưu lượng vượt một ngưỡng thì mở lại quyết định. Hai đội bắt đầu sửa module độc lập thì mở lại. Phần tích hợp có thêm một nhà cung cấp nữa thì mở lại. Nhờ vậy, quyết định không hóa vĩnh viễn chỉ vì đã được ghi thành văn bản; nó đủ rõ để được thay một cách an toàn khi hoàn cảnh đổi.

Người đến sau không cần đọc toàn bộ dòng suy nghĩ của cuộc họp cũ. Họ chỉ cần đủ bối cảnh để codebase không biến thành câu đố. Một ghi chú kiến trúc nhỏ làm được việc rất thực tế: đổi một hình dạng lạ từ thứ gây ngờ vực thành một lựa chọn có thể hiểu, kiểm tra và tiếp tục cải thiện.

Bạn thấy bài viết thế nào?