Vì sao nên viết ADR
(github.blog)ADR = Architecture Decision Records
Ghi lại trong codebase lý do vì sao các quyết định về kiến trúc lại được đưa ra như vậy.
GitHub đang áp dụng cách này trong các nhóm mobile iOS/Android và đây là bài viết giải thích vì sao nó cần thiết.
Không phải cho bạn của hiện tại, mà cho bạn trong tương lai
ADR không phải là quá trình tự nhìn lại các quyết định mà tôi đã đưa ra, mà là thứ giúp nhớ lại mindset vào thời điểm đã quyết định kiến trúc này sau 6~12 tháng nữa.
ADR ghi lại đúng thời điểm quyết định được đưa ra, bao gồm cả PoC đã được bàn đến trong họp hành/Zoom meeting/Slack/code.
Nó là cách kéo phần ngữ cảnh đang ở trong đầu ra thành lời, để sau này khi xem lại kiến trúc đó có thể nạp lại đúng ngữ cảnh ấy vào đầu.
Phần thưởng thực sự xuất hiện khi vài tháng sau có ai đó chất vấn bạn rằng vì sao module GitHubAPIClient lại hoạt động theo cách này.
Thay vì pair 30 phút để giải thích code, bạn có thể đưa ADR này cho họ và giải thích được những quyết định đã được đưa ra trong lúc xây dựng module đó.
Không phải cho bạn, mà cho đồng nghiệp của bạn
ADR nên viết dài hơn một câu kiểu như "Tính năng này là phần triển khai của feature-#3128".
Đây là một dạng mô tả dài hơn giúp đồng nghiệp hiểu vì sao tính năng này được làm theo cách này chứ không phải cách khác.
(Trong ADR có thể thể hiện bằng các mục như "Các phương án đã cân nhắc", "Ưu điểm và nhược điểm" v.v.)
Điều đơn giản với bạn có thể lại phức tạp với đồng nghiệp.
Nếu dành chút thời gian để viết lại quá trình suy nghĩ khi đưa ra quyết định, bạn sẽ cho các thành viên trong nhóm cơ hội bước vào trong đầu mình.
Viết ADR giúp thực hiện được "Decision Socialization (xã hội hóa quyết định)".
Nhờ vậy, thay vì mỗi cá nhân tự đưa ra quyết định, cả nhóm sẽ cùng đưa ra những quyết định mà họ có trách nhiệm duy trì.
Nếu viết ADR trước khi mở pull request, bạn có thể nhận được review PR tốt hơn từ nhóm xem xét nó.
Không phải cho bạn, mà cho các đồng nghiệp trong tương lai
ADR không phải để phô diễn bạn thông minh đến đâu hay khiến người khác bối rối khi nhìn vào kiến trúc bạn tạo ra.
ADR giúp các thành viên mới hiểu codebase hiện tại và cách codebase đó đã phát triển theo thời gian.
Khi đội ngũ mở rộng và phát triển, số lượng kênh giao tiếp giữa các thành viên cũng tăng lên.
Việc ghi lại những quyết định đã được đưa ra như thế này sẽ giúp giao tiếp với cả những người mới gia nhập khi nhóm phát triển lớn hơn.
Kịch bản tốt nhất là một thành viên trong nhóm viết ADR mới để thay thế quyết định bạn từng đưa ra, và trong tương lai bạn lại có thể học từ đồng nghiệp của mình.
"Hãy viết nhiều ADR hơn. Mỗi khi đội ngũ của chúng ta lớn lên và codebase trở nên phức tạp hơn, ADR là một cách tuyệt vời để giúp ích cho chúng ta trong tương lai, cho các thành viên hiện tại của đội và cho các thành viên trong tương lai."
3 bình luận
Trong số các ví dụ về chính phủ điện tử, Gov.UK nổi tiếng cũng có một repository tổng hợp các ADR liên quan đến kiến trúc đám mây AWS của họ.
https://github.com/alphagov/govuk-aws/…
Đây là một tài liệu tham khảo hữu ích.
Một số ví dụ về ADR
Quyết định framework CSS
https://github.com/joelparkerhenderson/architecture_decision_record/…
Tiền đề: Vì muốn tạo một web app hiện đại, nhanh và responsive nên không muốn dùng jQuery
Ràng buộc: Framework phải là loại không cần dùng jQuery
Cân nhắc: Không dùng gì cả, hoặc Bootstrap/Bulma/Foundation/Materialize/Semantic UI, trong đó đã cân nhắc kỹ Bulma và Semantic UI
Monorepo vs Multirepo
https://github.com/joelparkerhenderson/architecture_decision_record/…
→ Đang dùng git làm SCM, nên cần quyết định giữa monorepo vs polyrepo vs hybrid
→ Khi tổ chức/đội ngũ/dự án nhỏ và cần lặp nhanh thì Monorepo
→ Khi tổ chức/đội ngũ/dự án lớn và tính ổn định quan trọng hơn thì Polyrepo
Quyết định ngôn ngữ lập trình
https://github.com/joelparkerhenderson/architecture_decision_record/…
→ Frontend là TypeScript
→ Backend là Rust
→ Frontend tuy phổ thông nhưng phải hỗ trợ phát triển, triển khai và lặp nhanh. Không cần tương thích legacy
→ Backend có yêu cầu cao hơn mức thông thường một chút. Cần cân nhắc chất lượng, độ ổn định và bảo mật. Gần như cần mức gần realtime (không được dừng do GC). Functional programming / xử lý song song và multicore processing, memory safety cũng rất quan trọng
Hạn chế: Bắt buộc phải chạy được trên serverless của major cloud service (Amazon Lamba)
Cân nhắc: C/C++/Clojure/Elixir/Erlang/Elm/Flow/Go/Haskell/Java/Javascript/Kotlin/Python/Ruby/Rust/TypeScript
Tranh luận:
→ C: Loại vì độ an toàn thấp; Rust có thể làm tốt hơn hầu hết mọi thứ
→ C++: Loại vì quá lộn xộn; Rust có thể làm tốt hơn hầu hết mọi thứ
→ Clojure: Mô hình hóa xuất sắc; giống Lisp nhất; runtime rất tốt trên JVM
→ Elixir: Runtime rất mạnh về triển khai và concurrency; trải nghiệm phát triển rất tốt; ecosystem tương đối nhỏ
→ Erlang: Runtime rất mạnh về triển khai và concurrency; trải nghiệm phát triển hơi thử thách; ecosystem tương đối nhỏ
→ Elm: Rất triển vọng; IBM đang chia sẻ các case tốt; ecosystem nhỏ
→ Flow: Một cải tiến thú vị cho JS; nhưng các developer đang dần rời bỏ nó
→ Go: Trải nghiệm phát triển rất tốt; concurrency rất tốt; đã có một số quyết định tệ khiến ngôn ngữ trở nên kỳ quặc
→ Haskell: Ngôn ngữ hàm tốt nhất; cộng đồng developer nhỏ; chưa có nhiều case thành công trong production
→ Java: Runtime tốt nhất; ecosystem rất mạnh; trải nghiệm phát triển chỉ ở mức tạm được
→ JavaScript: Ngôn ngữ phổ biến nhất; ecosystem rộng nhất
→ Kotlin: Cải thiện được nhiều điểm của Java; được JetBrains hậu thuẫn rất tốt; có nhiều case thành công khi chuyển từ Java sang Kotlin
→ Python: Ngôn ngữ phổ biến nhất trong mảng quản trị hệ thống; công cụ phân tích tốt; web framework tốt; bị bỏ lại khi Google chọn Go
→ Ruby: Trải nghiệm phát triển tốt nhất; web framework tốt nhất; cộng đồng tuyệt vời; cực kỳ chậm; khó đóng gói
→ Rust: Ngôn ngữ mới tốt nhất; nhấn mạnh Zero-cost abstractions (trừu tượng hóa mà không làm chậm tốc độ); nhấn mạnh concurrency; ecosystem tương đối nhỏ; có giới hạn ở một số tối ưu hóa compiler (ví dụ truy cập bộ nhớ trực tiếp phải là unsafe)
→ TypeScript: Thêm Type vào JavaScript; transpiler rất tốt; developer ngày càng chuyển từ JS sang TS; được Microsoft hậu thuẫn mạnh mẽ
Quyết định không chọn nền tảng dựa trên VM (vì làm tăng độ phức tạp)
Để có runtime nhanh nhất thì chọn JS và C
Để có runtime gần như nhanh nhất thì chọn TypeScript và Rust
Nếu đã chọn VM và web framework thì
→ Closer và Luminous
→ Java và Spring
→ Elixir và Phoenix