Từ Coder lên Architect: Khi code "chạy được" là chưa đủ
Mở đầu series "Architect & System Design: Từ Code Sạch đến Hệ Thống Chịu Tải Cao". Trong thời đại AI gen code "vèo vèo", giá trị của lập trình viên dời từ tốc độ gõ phím sang tư duy thiết kế.
Có một cảnh rất quen trong nghề: tháng thứ ba của một dự án, cả team không ai dám đụng vào file OrdersController nữa. Nó dài hơn nghìn dòng, mỗi lần sửa một logic nhỏ là ba chỗ khác hỏng theo. Tính năng vẫn “chạy được”, khách vẫn đặt hàng được, nhưng cả team thì nín thở mỗi lần deploy.
Đó là lúc người ta bắt đầu thấm thía:
“chạy được” và “bền vững” là hai thế giới khác nhau.
Và năm 2026, ranh giới này còn rõ hơn bao giờ hết. Khi AI đã sinh được phần lớn code khuôn mẫu, giá trị của kỹ sư không còn nằm ở tốc độ sản xuất ra dòng code. Nhìn vào thị trường tuyển dụng là thấy: những người biết thiết kế hệ thống, đánh giá code do AI tạo ra và điều phối các luồng tự động đang được săn đón hơn bao giờ hết, trong khi nhu cầu cho người chỉ giỏi viết code khuôn mẫu thì thu hẹp dần. Nghịch lý thú vị là chính các senior mới là người hưởng lợi nhiều nhất từ AI, vì họ biết dùng nó đúng chỗ và biết khi nào không nên tin nó.
Dưới đây là ba khác biệt lớn nhất về mặt tư duy giữa một thợ code và một kiến trúc sư.
1. Tổ chức mã nguồn: tách bạch “Lõi” và “Vỏ”
Khi mới vào nghề, ta chỉ quan tâm: input vào, output ra đúng là xong. Lấy ví dụ tính năng đặt mua e-book.
Một thợ code thường nhét tất cả vào thẳng controller: tính tiền, kiểm tra số lượng, gọi luôn Order.create để ghi xuống database, rồi lưu ID vào session.
def create
price = Ebook.find(params[:ebook_id]).price
total = price * params[:quantity].to_i
# ... vài dòng kiểm tra lặt vặt ...
order = Order.create!(
ebook_id: params[:ebook_id],
email: params[:email],
quantity: params[:quantity],
total: total
)
session[:order_id] = order.id
endLogic đúng, code “chạy được” ngay. Nhưng nó trộn lẫn logic nghiệp vụ (tính tiền, kiểm tra hợp lệ) với chi tiết hạ tầng (ActiveRecord, bảng orders, session).
Hậu quả: muốn test quy tắc tính tiền là phải dựng cả database, và logic bị đóng đinh vào ActiveRecord, đụng đâu hỏng đó.
Người có tư duy kiến trúc vẽ ranh giới rõ ràng. Quy tắc tính tiền, kiểm tra hợp lệ được gom vào một vùng lõi thuần nghiệp vụ, một object Ruby thuần (PORO) không dính một dòng ActiveRecord nào:
# Lõi - thuần nghiệp vụ, không biết database là gì
class Order
def initialize(ebook_id:, email:, quantity:, price:)
raise ArgumentError, "quantity phải > 0" if quantity <= 0
@ebook_id, @email, @quantity, @price = ebook_id, email, quantity, price
end
def total
@price * @quantity
end
endMột lưu ý nhỏ: xuyên suốt series mình dùng Ruby (trên Rails framework) làm ngôn ngữ minh họa, vì đó là nền mình vững nhất và cú pháp Rails đủ trong sáng để cả người không biết Ruby vẫn đọc hiểu ý. Bản chất các nguyên tắc ở đây độc lập với ngôn ngữ, bạn hoàn toàn áp được sang PHP (Laravel), Python (Django), Java (Spring) hay JavaScript/TypeScript (NestJS).
Việc nói chuyện với database thì đẩy ra một lớp riêng gọi là Repository. Controller trở lại đúng vai điều phối (orchestrator): lấy dữ liệu request, tạo Order, nhờ Repository lưu.
Cái lợi về lâu dài: nếu mai này bạn đổi chỗ lưu dữ liệu, từ MySQL sang PostgreSQL, hay thậm chí chuyển sang lưu qua API của một service khác, toàn bộ logic cốt lõi vẫn an toàn. Bạn chỉ viết lại cái adapter trong Repository, phần Order không đụng tới một dòng.
Đây là chỗ dễ gây tranh cãi, nên mình nói rõ: cộng đồng Rails phần lớn theo triết lý “The Rails Way”, ưa ActiveRecord hơn là tách lớp kiểu này, và với app nhỏ hoặc vừa thì ActiveRecord thuần thường là lựa chọn đúng vì nhanh và gọn. Điểm mấu chốt không phải “luôn luôn tách lớp”, mà là: thợ code biết một cách làm, còn architect biết cả một phổ các cách làm và chọn đúng nấc cho độ phức tạp của bài toán. Series này sẽ đi dần qua từng nấc đó.
Tóm gọn lại: lẫn lộn “nghiệp vụ là gì” với “lưu ở đâu” trong cùng một chỗ là mầm mống của technical debt (nợ kỹ thuật) mà đại đa số anh em engineers đều ngao ngán.
2. Tư duy mở rộng (Scalability)
Xây hệ thống cho 100 người rất khác xây cho 1 triệu người. Khi traffic tăng vọt, hệ thống sập thường không phải vì “code dở” mà vì sai chiến lược kiến trúc.
Hình dung bạn mở một quán phở. Ban đầu 5 bàn, phục vụ ngon lành. Khách đông gấp 10, bạn có hai cách:
Cách thứ nhất là mở rộng chiều dọc (vertical scaling): mua nồi to hơn, thuê đầu bếp xịn hơn. Tương đương nhồi thêm RAM, CPU cho một máy chủ duy nhất. Dễ làm, nhưng phần cứng nào cũng có giới hạn.
Cách thứ hai là mở rộng chiều ngang (horizontal scaling): mở thêm nhiều chi nhánh chạy song song. Trong hệ thống, đây là xây ứng dụng phi trạng thái (stateless), chạy trên nhiều máy cùng lúc, đặt một người điều phối giao thông tên là Load Balancer ở phía trước.
Kiến trúc sư luôn chừa đường lùi: thiết kế sẵn sàng scale ngang ngay từ đầu, dù hôm nay quán mới chỉ có 5 bàn.
3. Tư duy đánh đổi (Trade-off)
Kỹ sư non kinh nghiệm thường đi tìm “giải pháp hoàn hảo”. Ở tầm architect, bạn hiểu rằng mọi quyết định kiến trúc đều là một sự đánh đổi, và việc của bạn là chọn cái đánh đổi đúng với bối cảnh. Đánh đổi có nhiều dạng: hiệu năng đổi lấy chi phí, tốc độ phát triển đổi lấy khả năng mở rộng, đơn giản đổi lấy linh hoạt. Dưới đây là cặp dễ hình dung nhất: tính nhất quán (Consistency) và tính khả dụng (Availability).
Nếu bạn thiết kế hệ thống đặt vé máy bay, còn đúng một ghế, hai đại lý cùng bấm đặt một lúc. Bạn bắt buộc chọn nhất quán mạnh (strong consistency). Hệ thống thà chậm vài giây để khóa dữ liệu, còn hơn bán trùng một ghế cho hai người.
Nhưng nếu bạn thiết kế tính năng đổi ảnh đại diện cho mạng xã hội, bạn bè thấy ảnh cũ trễ vài giây thì hoàn toàn không sao. Lúc này architect chọn nhất quán cuối cùng (eventual consistency) để hệ thống phản hồi cực nhanh và không bao giờ nghẽn.
Cùng một bộ công cụ, hai bài toán, hai lựa chọn ngược nhau. Đó chính là bản chất của trade-off.
Và đây là lý do tất cả những điều trên quan trọng hơn bao giờ hết trong 2026
AI gen code nhanh, nhưng nó tạo ra một cái bẫy mới mà giới trong nghề gọi là “Uncanny Valley of Code”. Code nhìn đúng cú pháp và hợp lý về mặt kiến trúc, nhưng giấu những lỗi chức năng tinh vi mà chỉ chuyên môn sâu mới soi ra, buộc lập trình viên chuyển từ vai "người viết code" sang vai "người thẩm định code". Con số đi kèm đủ làm bạn giật mình: khoảng 45% code do AI sinh ra chứa lỗ hổng thuộc nhóm OWASP Top 10.
Mà để thẩm định được, bạn phải có tư duy kiến trúc làm hệ quy chiếu. Bạn không thể đánh giá một thiết kế nếu chính bạn không biết một thiết kế tốt trông như thế nào. Thiết kế hệ thống và kiến trúc vẫn nằm chắc trong địa hạt của con người, chưa có công cụ AI nào đủ tin cậy để đưa ra các quyết định đánh đổi cấp cao định hình nên một hệ thống thành công.
Lời kết
Kiến trúc phần mềm không phải thứ gì xa vời. Nó là công cụ để kéo dài tuổi thọ dự án và giúp hệ thống sống dai, sống khỏe. Trong thời đại AI, nó còn là thứ phân định ai điều khiển được cỗ máy và ai bị cỗ máy dắt mũi.
Bài tiếp theo, mình sẽ trải ra bản đồ các khái niệm System Design cốt lõi nhất, một cuốn từ điển bỏ túi để anh em có cái nhìn tổng quan trước khi đi sâu. Nếu thấy series này hữu ích, subscribe để không lỡ bài nhé. Còn bây giờ thì mình tò mò: bạn đã bao giờ gặp cái file OrdersController nghìn dòng “không ai dám đụng” của riêng mình chưa?
Bài viết thuộc series “Architect & System Design: Từ Code Sạch đến Hệ Thống Chịu Tải Cao”


