Học kiến trúc phần mềm: Bài học từ thực tế và tầm quan trọng của yếu tố xã hội

Công nghệ12 tháng 5, 2026·8 phút đọc

Bài viết chia sẻ kinh nghiệm thực tế về việc học thiết kế và kiến trúc phần mềm, nhấn mạnh rằng kỹ năng này được rèn luyện tốt nhất qua quá trình làm việc thực tế. Tác giả phân tích tầm quan trọng của Định luật Conway, mối liên hệ giữa cấu trúc xã hội và cấu trúc phần mềm, cùng cách quản lý động lực đóng góp thông qua dự án rust-analyzer.

Trong một bức thư trả lời cho một nhà vật lý nghiên cứu hỏi về cách học kỹ năng thiết kế phần mềm, tác giả đã chia sẻ những góc nhìn sâu sắc về bản chất của "mã nguồn khoa học" (scientific code) và con đường trở thành một kiến trúc sư phần mềm thực thụ.

Học qua hành động

Quan sát đầu tiên là "thiết kế phần mềm" là thứ tốt nhất nên học bằng cách làm. Mặc dù tác giả đã từng tham gia các khóa học "thiết kế" chính quy tại đại học và từng đóng vai trò là "kiến trúc sư" cho dự án môn học, nhưng những thứ đó phần lớn chỉ là giả tạo, giống như trẻ con chơi đóng vai lính cứu hỏa. Điều thực sự dạy cho tác giả cách làm việc là một sự ngẫu nhiên trong sự nghiệp, khi dự án thực tế thứ hai (IntelliJ Rust) đã đẩy anh ấy vào vị trí lãnh đạo phần mềm, biến việc thiết kế trở thành vấn đề của chính mình. Anh ấy đã mắc một số sai lầm trong IntelliJ Rust, nhưng không có gì quá tồi tệ và đã học được rất nhiều điều từ đó.

Đây là một tin tốt: kỹ thuật phần mềm đủ đơn giản để một bộ óc tò mò có thể tự tìm ra từ những nguyên lý cơ bản (và đọc các bài viết blog ngẫu nhiên).

Định luật Conway và các vấn đề xã hội

Quan sát thứ hai mang tính tổng quát hơn, và là một tin xấu: Định luật Conway (Conway's Law) là rất quan trọng. Sự hình thành của phần mềm lặp lại cấu trúc xã hội của tổ chức sản xuất ra nó. Hoặc như được diễn đạt một cách hùng hồn bởi neugierig:

Nếu tôi phải tóm tắt những gì mình đã học được trong một câu, nó sẽ là: chúng ta nói về lập trình như thể nó là về viết code, nhưng code cuối cùng lại kém quan trọng hơn kiến trúc, và kiến trúc lại kém quan trọng hơn các vấn đề xã hội.

Sự khác biệt mà bạn nhận thấy giữa phần mềm công nghiệp và phần mềm khoa học có lẽ không nằm nhiều ở kiến thức xây dựng phần mềm, mà nằm ở lĩnh vực động lực thúc đẩy mọi người tạo ra phần mềm đó. Động lực kiểu "tiến sĩ của tôi cần công bố một bài báo trong ba tháng tới" có lẽ là một lời giải thích đáng kể.

Quản lý động lực và thích nghi

Bạn có thể làm hai việc ở đây. Một là, đôi khi bạn có cơ hội thiết kế hoặc điều chỉnh cấu trúc động lực cho một dự án. Điều này xảy ra rất hiếm gặp ("một lần xanh da trời"), nhưng lại có tác động rất lớn. Đây là "gia vị bí mật" đằng sau TIGER_STYLE, không phải là bộ quy tắc cụ thể, mà là bối cảnh xã hội khiến bộ quy tắc đó trở thành một ý tưởng hay.

Hai là, bạn có thể "tăng tốc" qua bốn giai đoạn đau buồn để chấp nhận thực tế. Cấu trúc động lực hầu như không bao giờ là như bạn mong muốn, nhưng nếu bạn không thể thay đổi nó, bạn có thể thích nghi với nó. Điều này cũng đúng với hầu hết các dự án phần mềm công nghiệp — không bao giờ có đủ thời gian để làm mọi thứ đúng đắn, bạn phải làm tốt nhất có thể trong các ràng buộc cho phép.

Bài học từ dự án rust-analyzer

Hãy lấy rust-analyzer làm ví dụ. Thực tế vật lý của dự án là nó vừa rất sâu (nó là một trình biên dịch!) lại vừa rất rộng (ngược lại với các LLM, một IDE cổ điển có rất nhiều tính năng đặc thù được xây dựng riêng). Thực tế xã hội là "trình biên dịch sâu" có thể thu hút một vài người đóng góp xuất sắc và tận tụy, trong khi "các tính năng rộng" lại phù hợp với một đội quân những "chiến binh cuối tuần" — những người đang học Rust, không có khả năng tham gia dự án bền bỉ, nhưng có thể dành một hoặc hai giờ để giải quyết vấn đề của riêng họ.

Sự kiên quyết của tác giả rằng rust-analyzer không yêu cầu xây dựng rustc, rằng nó xây dựng trên bản stable, không có bất kỳ phụ thuộc C nào, và toàn bộ bộ kiểm thử (test suite) chỉ mất vài giây, đều nhằm phục vụ mục tiêu thu hút những người đóng góp có tác động cao. Tác giả đã điều chỉnh hệ thống build để đảm bảo mọi người có thể làm việc trên bộ kiểm tra mượn (borrow checker) mà không cần nghĩ về bất cứ điều gì khác.

Để thu hút những "chiến binh cuối tuần", các nội bộ của rust-analyzer được chia thành nhiều tính năng độc lập, trong đó mỗi tính năng được bảo vệ bởi catch_unwind tại thời điểm chạy. Suy nghĩ là tác giả rõ ràng không muốn quá quan tâm đến chất lượng ở đây, tiêu chuẩn để một PR tính năng được chấp nhận là "trường hợp hợp lệ hoạt động & đã được kiểm thử". Không sao nếu code bị crash, nó thậm chí có thể thu hút thêm người đóng góp, miễn là:

  • Chất lượng bị cô lập trong một tính năng và không lan sang chỗ khác.
  • Tại thời điểm chạy, lỗi crash là vô hình với người dùng (rất quan trọng rằng các tính năng của rust-analyzer hoạt động với một snapshot bất biến và không thể làm hỏng dữ liệu).

Ngược lại, khi làm việc trên cốt lõi (spine) cung cấp hỗ trợ cho các tính năng, tác giả khá khó tính hơn về chất lượng.

Một lời cảnh báo về việc thích nghi thay vì sửa chữa cấu trúc động lực: tương lai là không chắc chắn và có xu hướng xảy ra theo cách kém thuận tiện nhất. Động lực ban đầu đằng sau thử nghiệm rust-analyzer là để tránh nhu cầu viết một trình biên dịch song song (cái trong IntelliJ Rust) và để tạo mẫu một kiến trúc tốt hơn cho LSP, để các bài học có thể được đưa trở lại rustc. Vì vậy, ngay cả ở cốt lõi (đặc biệt là ở cốt lõi), code ban đầu rất mang tính thử nghiệm. À well. Giờ thì lại mắc kẹt với thêm một trình biên dịch nữa rồi, nhỉ?

Tôi có thể đoán rằng điều tương tự cũng đã xảy ra với dự án uutils, vốn bắt đầu là điểm đến chính cho những người học Rust, và cuối cùng trở thành implementation của coreutils cho Ubuntu.

Các tài liệu tham khảo hữu ích

Cuối cùng, đến với một số lời khuyên cụ thể. Đáng buồn là tôi không biết một cuốn sách nào duy nhất có thể giới thiệu chứa đựng những sự thật này. Tôi nghi ngờ rằng người ta chỉ có thể tìm thấy một cuốn sách như vậy trong một câu chuyện ngắn khuyết danh của Borges: thực hành dường như là một yếu tố thiết yếu ở đây. Nhưng đây là một số thứ đáng để chú ý:

  • Bài nói Boundaries của Gary Bernhardt là yêu thích mọi thời đại. Nó chứa đựng những lời khuyên cấp độ đối tượng vững chắc, và đối với tôi, nó đã kích hoạt sự điều tra cấp độ meta.
  • How to Test là thứ tôi ước mình có. Tôi đã ngay lập tức hiểu được tầm quan trọng của việc kiểm thử, nhưng mất rất lâu để tôi đủ kiêu ngạo thừa nhận rằng hầu hết lời khuyên về kiểm thử được trích dẫn rộng rãi chỉ là "thuốc rắn" mê tín dị đoan, và để hình dung những gì thực sự hiệu quả.
  • Hướng dẫn ∅MQ và nói chung là các bài viết của Pieter Hintjens đã giới thiệu cho tôi tư duy của Định luật Conway. Kiến trúc "phát triển tính năng" của rust-analyzer? — đó là optimistic merging (gộp lạc quan) được áp dụng.
  • Reflections on a decade of coding của Jamii là tuyệt vời và đi rất sâu vào khía cạnh meta. Nó cố tình là liên kết đầu tiên trong danh sách của tôi.
  • Blog của Ted Kaminski là thứ gần giống nhất một lý thuyết mạch lạc của phát triển phần mềm, được khung hình phù hợp như một tập hợp các ghi chú cho một cuốn sách không tồn tại!

Về các sách thực tế, Software Engineering at GoogleThe Philosophy of Software Design của Ousterhout thường được giới thiệu. Chúng rất tốt. SWE, đặc biệt, đã giúp tôi với một vài tên gọi quan trọng. Nhưng chúng không phải là mang tính cách mạng đối với tôi.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗