KoderKoder.ai
Bảng giáDoanh nghiệpGiáo dụcDành cho nhà đầu tư
Đăng nhậpBắt đầu

Sản phẩm

Bảng giáDoanh nghiệpDành cho nhà đầu tư

Tài nguyên

Liên hệHỗ trợGiáo dụcBlog

Pháp lý

Chính sách bảo mậtĐiều khoản sử dụngBảo mậtChính sách sử dụng chấp nhận đượcBáo cáo vi phạm

Mạng xã hội

LinkedInTwitter
Koder.ai
Ngôn ngữ

© 2026 Koder.ai. Bảo lưu mọi quyền.

Trang chủ›Blog›Quan điểm của Martin Fowler: Kiến trúc bền vững hơn các stack thịnh hành
19 thg 11, 2025·5 phút

Quan điểm của Martin Fowler: Kiến trúc bền vững hơn các stack thịnh hành

Khám phá góc nhìn thực dụng của Martin Fowler về kiến trúc: mẫu, tái cấu trúc và kiến trúc tiến hóa giúp vượt qua các stack thịnh hành và giảm rủi ro dài hạn.

Quan điểm của Martin Fowler: Kiến trúc bền vững hơn các stack thịnh hành

Tại sao các stack công nghệ thịnh hành không đảm bảo kiến trúc tốt

Một framework mới, một dịch vụ đám mây bóng bẩy, hoặc “stack chuẩn” ở một công ty hot có thể khiến bạn tưởng là đường tắt đến chất lượng. Nhưng cách nghĩ chọn stack trước thường nhầm lẫn công cụ với cấu trúc. Bạn có thể xây một hệ thống lộn xộn, khó thay đổi với công nghệ hiện đại nhất — hoặc một hệ thống sạch, dễ thích nghi với những lựa chọn cũ, quen thuộc.

Vấn đề của lối tư duy “chọn stack trước”

Quyết định chọn stack trước đẩy các đội vào những lựa chọn trông ấn tượng trên slide nhưng không trả lời các câu hỏi thực sự:

  • Ranh giới ở đâu?
  • Cái gì cần thay đổi thường xuyên?
  • Cái gì phải giữ ổn định?

Khi lựa chọn công nghệ dẫn dắt, kiến trúc trở thành hệ quả ngẫu nhiên — dẫn tới coupling chặt, logic bị nhân bản, và các phụ thuộc khiến thay đổi đơn giản trở nên tốn kém.

Chính vì vậy “chúng tôi dùng microservices” (hoặc “chúng tôi serverless rồi”) không phải là kiến trúc. Đó là hướng triển khai và công cụ. Kiến trúc là cách các phần của hệ thống hợp tác, cách các quyết định ràng buộc công việc tương lai, và mức độ dễ dàng để sản phẩm tiến hóa.

Một hệ quả thực tế: công cụ có thể tăng tốc giao hàng, nhưng không thay thế tư duy kiến trúc. Ngay cả với các phương pháp “vibe-coding” hiện đại — nơi bạn sinh và lặp nhanh qua chat — những câu hỏi này vẫn còn nguyên giá trị. Các nền tảng như Koder.ai có thể đẩy nhanh việc xây dựng web, backend và ứng dụng di động, nhưng những đội đạt hiệu quả nhất vẫn coi ranh giới, quyền sở hữu và khả năng thay đổi là mối quan tâm hàng đầu (không phải thứ framework sẽ tự động giải quyết).

Ảnh hưởng của Fowler: rõ ràng, thực dụng và tiến hóa theo thời gian

Viết của Martin Fowler luôn kéo sự chú ý trở lại điều quan trọng: thiết kế rõ ràng hơn các thành phần thời thượng, đánh đổi thực tế hơn tư tưởng hệ thống, và khả năng tiến hóa hệ thống khi bạn học được. Công trình của ông xem kiến trúc là thứ bạn cải thiện liên tục — không phải mốc “thiết kế lớn” một lần.

Bài viết này tập trung vào gì

Kỳ vọng ba chủ đề lặp lại: dùng mẫu như công cụ tùy ý (không phải luật), tái cấu trúc như thói quen thường xuyên, và kiến trúc tiến hóa — xây để thay đổi chứ không phải cho sự chắc chắn.

Dành cho ai

Nếu bạn là người lãnh đạo kỹ thuật, tech lead, hoặc nhóm sản phẩm muốn phát hành nhanh hơn mà không làm sụp chất lượng, bài này dành cho bạn. Mục tiêu không phải chọn stack “hoàn hảo” — mà là đưa ra quyết định giúp phần mềm dễ thay đổi khi lộ trình tất yếu thay đổi.

“Kiến trúc phần mềm” thực sự nghĩa là gì (không dùng từ chuyên môn)

Kiến trúc phần mềm là tập hợp các quyết định định hình hệ thống theo những cách mà về sau khó (và tốn) để thay đổi.

Định nghĩa này cố tình đơn giản. Nó không đòi hỏi sơ đồ đặc biệt hay danh hiệu “architect”. Nó là về những lựa chọn quyết định phần mềm có thể phát triển thế nào, đội ngũ làm việc ra sao, và chi phí vận hành là bao nhiêu.

Kiến trúc không phải là tech stack của bạn

Framework, công cụ và phong cách code quan trọng — nhưng hầu hết chúng dễ thay thế so với các quyết định kiến trúc thực sự.

  • Chọn React hay Vue thường có thể đảo ngược.
  • Quyết định “tất cả ghi phải đi qua một service duy nhất” thì khó đảo ngược hơn nhiều.

Kiến trúc sát hơn với cấu trúc và ranh giới: cách các phần giao tiếp, dữ liệu nằm ở đâu, cách xử lý lỗi, và thay đổi nào đòi hỏi phối hợp giữa các đội.

Kiến trúc là tập hợp các đánh đổi

Không có kiến trúc “tốt nhất” phổ quát. Mỗi quyết định lớn tối ưu cho vài mục tiêu và gây thiệt thòi cho các mục tiêu khác:

  • Hiệu năng vs đơn giản: lớp cache tăng tốc nhưng thêm phức tạp và các trường hợp biên khó xử lý.
  • Tốc độ đội vs độ tin cậy: phát hành nhanh giúp học hỏi, nhưng cần test và quy trình rollout chắc hơn.
  • Chi phí vs độ chịu lỗi: dự phòng cải thiện thời gian hoạt động nhưng tăng chi phí hạ tầng và bảo trì.

Kiến trúc tốt làm cho các đánh đổi này rõ ràng thay vì vô tình.

Ví dụ nhanh: quyết định kiến trúc vs chọn thư viện

  • Quyết định kiến trúc: “Chúng ta tách billing thành service có thể deploy riêng với database riêng, phần còn lại tích hợp qua sự kiện bất đồng bộ.”

    Điều này ảnh hưởng tới triển khai, quyền sở hữu dữ liệu, chế độ lỗi, giám sát và phối hợp đội.

  • Chọn thư viện: “Chúng ta sẽ dùng Thư viện X để sinh PDF.”

    Hữu ích, nhưng thường có thể thay bằng tác động vùng ảnh hưởng hạn chế.

Nếu hoàn tác một quyết định cần vài tuần phối hợp, rất có thể đó là kiến trúc.

Mẫu thiết kế như công cụ: hữu ích, tùy ý, và đôi khi bị lạm dụng

Mẫu thiết kế tốt nhất được hiểu là giải pháp tái sử dụng cho vấn đề lặp lại, không phải là điều răn. Quan điểm chung của Fowler là thực dụng: mẫu hữu dụng khi làm rõ thiết kế, có hại khi thay thế tư duy.

Khi nào mẫu có ích

Dùng đúng, mẫu cho đội ngôn ngữ chung. Nói “strategy” hay “repository” có thể nén một giải thích dài thành một thuật ngữ, giúp review nhanh hơn và giảm hiểu lầm.

Mẫu cũng làm hành vi hệ thống dự đoán hơn. Một mẫu quen thuộc thiết lập kỳ vọng nơi logic nằm, cách các đối tượng hợp tác, và thay đổi nào có khả năng lan tỏa. Sự dự đoán này giảm bất ngờ trong production và giảm câu hỏi “cái này hoạt động thế nào?” cho thành viên mới.

Khi nào mẫu gây hại

Hỏng hóc là cargo-culting: áp dụng mẫu vì nó phổ biến, vì sách đề cập, hoặc vì “đó là cách ta làm ở đây.” Điều này thường dẫn tới over-engineering — lớp thừa, sự gián tiếp, và các abstraction không đem lại lợi ích tương xứng.

Một bẫy khác là “mẫu cho mọi thứ.” Khi mọi vấn đề nhỏ đều có tên gọi, codebase có thể biến thành bảo tàng của sự tinh tế thay vì công cụ để giao hàng và bảo trì phần mềm.

Cách thực tế để chọn

Bắt đầu từ vấn đề, không phải từ mẫu.

Hỏi:

  • Chúng ta muốn làm thay đổi nào dễ hơn?
  • Chúng ta giảm rủi ro nào?
  • Chúng ta đang thêm bao nhiêu độ phức tạp?

Rồi chọn mẫu đơn giản nhất phù hợp và giữ mở các tùy chọn. Nếu cần thêm cấu trúc sau này, bạn có thể bổ sung từng bước — thường được dẫn dắt bởi nỗi đau thực tế và xác nhận bằng tái cấu trúc, thay vì phỏng đoán trước.

Tái cấu trúc: Thói quen giữ kiến trúc khỏe mạnh

Tái cấu trúc là thực hành cải thiện thiết kế nội bộ của phần mềm mà không thay đổi hành vi bên ngoài. Người dùng không nên nhận thấy gì khác sau refactor — ngoại trừ việc các thay đổi trong tương lai dễ dàng, an toàn và nhanh hơn.

Quan điểm của Martin Fowler không phải “giữ mã đẹp.” Mà là kiến trúc không phải sơ đồ một lần ở đầu. Kiến trúc là các quyết định quyết định mức độ dễ thay đổi của hệ thống. Tái cấu trúc là cách bạn ngăn các quyết định đó đóng băng thành ràng buộc.

Tại sao tái cấu trúc là hoạt động kiến trúc

Theo thời gian, ngay cả hệ thống thiết kế tốt cũng bị trôi dạt. Tính năng mới được thêm dưới áp lực thời gian, sửa nhanh trở thành vĩnh viễn, và ranh giới mờ đi. Tái cấu trúc là cách bạn phục hồi sự tách bạch rõ ràng và giảm độ phức tạp tình cờ, để hệ thống luôn có thể thay đổi.

Một kiến trúc khỏe mạnh là nơi:

  • các quy tắc kinh doanh quan trọng không bị rối với chi tiết UI
  • module có trách nhiệm rõ ràng
  • phụ thuộc chỉ hướng theo cách hợp lý

Tái cấu trúc là công việc hàng ngày giữ gìn những chất lượng đó.

Các dấu hiệu thường gặp báo “đã đến lúc”

Bạn thường không lên lịch refactor bằng lịch. Bạn làm khi mã bắt đầu phản kháng:

  • Sao chép: cùng một quy tắc nằm ở ba chỗ, dần khác nhau
  • Ranh giới mơ hồ: “mọi thứ chạm vào mọi thứ,” làm thay đổi rủi ro
  • Giao hàng chậm: yêu cầu đơn giản kéo dài vì mỗi thay đổi gây bất ngờ

Khi những điều đó xuất hiện, kiến trúc đã bị ảnh hưởng — refactor là sửa chữa.

Cách tái cấu trúc an toàn (không làm vỡ thứ khác)

Tái cấu trúc an toàn dựa trên vài thói quen:

  • Tests bắt được thay đổi hành vi không mong muốn (đặc biệt quanh logic cốt lõi)
  • Bước nhỏ: nhiều sửa nhỏ có thể đảo ngược hơn là viết lại lớn một lần
  • Code review: thêm góc nhìn để phát hiện tác dụng phụ bị bỏ sót và scope bị mở rộng

Làm theo cách này, tái cấu trúc trở thành bảo trì thường xuyên — giữ hệ thống sẵn sàng cho thay đổi tiếp theo thay vì mong manh sau lần thay đổi trước.

Nợ kỹ thuật: cách nó tích lũy và cách trả

Tránh lo ngại bị khóa công cụ
Giữ lựa chọn mở bằng cách xuất mã nguồn khi bạn cần quy trình tùy chỉnh.
Xuất mã

Nợ kỹ thuật là chi phí tương lai do các đường tắt hôm nay tạo ra. Nó không phải “mã tồi” như một lỗi đạo đức; đó là đánh đổi bạn chấp nhận (đôi khi có chủ ý) khiến giá thay đổi tăng lên sau này. Cách nhìn của Martin Fowler hữu ích ở đây: nợ chỉ trở thành vấn đề khi bạn ngừng theo dõi nó và giả vờ như nó không tồn tại.

Nợ có chủ ý vs vô ý

Nợ có chủ ý là khi bạn chấp nhận rõ ràng: “Chúng ta sẽ giao phiên bản đơn giản bây giờ, rồi củng cố sprint sau.” Điều đó hợp lý — nếu bạn cũng có kế hoạch trả.

Nợ vô ý xảy ra khi đội không nhận ra họ đang vay: phụ thuộc lộn xộn len lỏi, mô hình miền mơ hồ lan rộng, hoặc sửa nhanh thành mặc định. Nợ vô ý thường đắt hơn vì không ai sở hữu nó.

Nợ tích tụ lặng lẽ như thế nào

Nợ tích tụ qua áp lực bình thường:

  • Deadline gấp buộc quyết định “chỉ cần chạy được”
  • Quyền sở hữu mơ hồ, nơi không ai chịu trách nhiệm cho sức khỏe module
  • Thiếu hoặc test mong manh, làm thay đổi trở nên đáng sợ và khuyến khích đường tắt

Kết quả dễ đoán: tính năng chậm lại, bug tăng, và tái cấu trúc trở nên rủi ro thay vì thường xuyên.

Cách nhẹ nhàng quản lý và trả dần

Bạn không cần chương trình lớn để bắt đầu trả nợ:

  • Dự trữ thời gian liên tục (ví dụ, một phần nhỏ mỗi iteration)
  • Theo dõi điểm nóng, không phải mọi thứ: tập trung vào mã bạn chạm thường và sợ nhất
  • Trả dần: kết hợp refactor với công việc tính năng để “lãi” ngừng cộng dồn

Nếu bạn cũng làm cho các quyết định liên quan nợ minh bạch (xem /blog/architecture-decision-records), bạn biến chi phí ẩn thành công việc có thể quản lý.

Câu hỏi thường gặp

What’s the difference between a tech stack and software architecture?

Kiến trúc là tập hợp các quyết định mà việc đảo ngược sau này sẽ tốn kém: ranh giới, quyền sở hữu dữ liệu, kiểu tích hợp và cách xử lý lỗi.

Một tech stack chủ yếu là các công cụ bạn dùng để thực hiện những quyết định đó (framework, thư viện, dịch vụ đám mây). Bạn có thể thay nhiều công cụ với ít tác động, nhưng thay ranh giới hoặc luồng dữ liệu thường đòi hỏi vài tuần phối hợp nhiều đội.

How can I tell whether a decision is “architecture” or just an implementation detail?

Một kiểm thử tốt là tính khả năng đảo ngược: nếu hoàn tác một quyết định mất vài tuần và cần nhiều đội phối hợp, đó là quyết định kiến trúc.

Ví dụ:

  • Kiến trúc: “Billing sở hữu dữ liệu của nó và tích hợp qua sự kiện bất đồng bộ.”
  • Không phải kiến trúc: “Dùng thư viện X để sinh PDF.”
When should we use design patterns, and when do they become over-engineering?

Dùng mẫu thiết kế để giải quyết một vấn đề lặp lại cụ thể, không phải để làm cho thiết kế trông “chuyên nghiệp”.

Checklist nhanh:

  • Chúng ta muốn làm cho thay đổi nào dễ hơn?
  • Chúng ta đang đưa vào bao nhiêu độ phức tạp mới (lớp, sự gián đoạn)?
  • Mẫu đơn giản nhất phù hợp cho hôm nay và vẫn giữ mở các tùy chọn là gì?

Nếu bạn không thể nêu rõ vấn đề, chưa vội áp dụng mẫu.

What are the most reliable signs that it’s time to refactor?

Xem tái cấu trúc như bảo trì thường xuyên gắn với mâu thuẫn thực tế, không phải dự án dọn dẹp hiếm hoi.

Dấu hiệu thường gặp:

  • Sao chép mã bắt đầu phân kỳ
  • Chuỗi phụ thuộc “mọi thứ chạm vào mọi thứ”
  • Thay đổi đơn giản gây ra lỗi bất ngờ

Giữ an toàn với tests, bước nhỏ và scope review hẹp.

How do we manage technical debt without slowing delivery to a crawl?

Theo dõi nợ kỹ thuật như một chi phí, không phải một bí mật xấu hổ.

Cách thực tế quản lý:

  • Dự trữ một phần nhỏ thời gian trong mỗi vòng lặp
  • Tập trung vào điểm nóng (mã thay đổi nhiều, vùng có nhiều sự cố)
  • Trả nợ cùng với công việc tính năng để giảm “lãi” compounding

Làm rõ các quyết định về nợ (ví dụ, với ADR nhẹ).

What does “evolutionary architecture” mean in practice?

Nó nghĩa là thiết kế sao cho bạn có thể đổi hướng an toàn khi học, thay vì đặt cược vào dự đoán dài hạn.

Thành phần điển hình:

  • Ranh giới và quyền sở hữu rõ ràng
  • Tests tự động giúp giảm rủi ro khi thay đổi
  • Thực hành phát hành hỗ trợ cập nhật nhỏ, thường xuyên

Mục tiêu là khả năng thích nghi, không phải bản thiết kế hoàn hảo từ đầu.

What are “fitness functions,” and which ones should we start with?

Fitness function là một hàng rào tự động bảo vệ một mục tiêu kiến trúc.

Ví dụ hữu ích:

  • Fail CI nếu thời gian build/test vượt ngưỡng
  • Chặn rollout nếu tỷ lệ lỗi vượt baseline
  • Quét bảo mật phụ thuộc để phát hiện lỗ hổng nghiêm trọng
  • Test hợp đồng để tránh phá vỡ client nội/ngoại bộ

Chọn vài cái phản ánh cam kết của bạn (tốc độ thay đổi, độ tin cậy, bảo mật) và chạy liên tục.

How do we choose between a monolith, modular monolith, and microservices?

Ưu tiên modular monolith trừ khi bạn có áp lực đã được đo lường và kéo dài đòi hỏi khả năng deploy độc lập.

Microservices có lợi khi:

  • Ranh giới rõ ràng và quyền sở hữu dữ liệu ổn định
  • Các đội có thể sở hữu dịch vụ end-to-end (build, deploy, operate)
  • Có observability và thực hành phát hành mạnh

Nếu bạn chưa thể chạy một service thoải mái trong production, tách thành mười thường nhân lên nhiều khó khăn.

What’s the fastest way to reduce coupling and dependency pain?

Bắt đầu bằng cách làm cho phụ thuộc trở nên hiển nhiên và có chủ ý.

Các bước hiệu quả:

  • Định nghĩa API/contract ổn định giữa module
  • Giao quyền rõ ràng (một team chịu trách nhiệm ranh giới và sự tiến hóa của nó)
  • Tránh database chung; ưu tiên quyền sở hữu dữ liệu qua API hoặc event

Database chung tạo “phụ thuộc bí mật”, buộc phải phát hành phối hợp dù hệ thống có vẻ tách rời.

Why should we write Architecture Decision Records (ADRs), and how detailed should they be?

Dùng ADR để ghi lại điều chúng ta quyết định và tại sao, khi ngữ cảnh còn rõ ràng.

Một ADR nhẹ gồm:

  • Quyết định, bối cảnh, các phương án, hệ quả
  • Ngày/trạng thái (accepted/superseded)
  • Người chịu trách nhiệm

Đặt gần mã (ví dụ, /docs/adr/) và liên kết hướng dẫn liên quan như /blog/architecture-decision-records.

Mục lục
Tại sao các stack công nghệ thịnh hành không đảm bảo kiến trúc tốt“Kiến trúc phần mềm” thực sự nghĩa là gì (không dùng từ chuyên môn)Mẫu thiết kế như công cụ: hữu ích, tùy ý, và đôi khi bị lạm dụngTái cấu trúc: Thói quen giữ kiến trúc khỏe mạnhNợ kỹ thuật: cách nó tích lũy và cách trảCâu hỏi thường gặp
Chia sẻ
Koder.ai
Build your own app with Koder today!

The best way to understand the power of Koder is to see it for yourself.

Start FreeBook a Demo