Speaker note: Bắt đầu bằng câu hỏi: "Khi chúng ta xây một tòa nhà, bản vẽ kiến trúc cho ta thấy điều gì?" Tương tự, kiến trúc phần mềm là bản vẽ tổng thể của hệ thống — không phải chi tiết từng dòng code, mà là cách các khối lớn được tổ chức và liên kết. Nhấn mạnh rằng kiến trúc phải thỏa mãn cả yêu cầu chức năng (hệ thống làm được gì) và phi chức năng (hệ thống hoạt động tốt như thế nào).
Speaker note: Kiến trúc sư phần mềm không chỉ là người code giỏi nhất — họ là người nhìn toàn cục. Họ phải hiểu yêu cầu nghiệp vụ, hiểu hạn chế kỹ thuật, và đưa ra các quyết định mà cả đội có thể thực thi. Một quyết định kiến trúc sai ở giai đoạn đầu có thể tốn rất nhiều chi phí để sửa về sau.
Speaker note: Nhiều sinh viên nhầm lẫn giữa hai khái niệm này. Hãy dùng phép so sánh: kiến trúc là quyết định xây nhà 3 tầng với tầng trệt là garage, còn thiết kế chi tiết là quyết định dùng loại gạch nào, cửa kiểu gì. Cả hai đều quan trọng, nhưng kiến trúc phải được quyết định trước và có tác động lâu dài hơn.
Speaker note: Phân loại phong cách kiến trúc giúp chúng ta có ngôn ngữ chung để thảo luận về thiết kế. Giống như trong văn học có các thể loại: tiểu thuyết, thơ, kịch — mỗi thể loại có quy tắc và đặc trưng riêng. Trong buổi học này chúng ta sẽ đi qua ba nhóm chính và xem xét từng phong cách cụ thể.
> [Image: 21:9 aspect ratio and white background of taxonomy tree diagram showing "Architectural Styles" as root node branching into three categories — "Data Flow" (with pipe icon), "Call and Return" (with call-stack icon), "Independent Components" (with event-bell icon) — each with two child nodes listing sub-styles; colorful 3d and clean academic vector, bold sans-serif labels, light color coding per branch]
Speaker note: Pipe-and-Filter là một trong những phong cách kiến trúc lâu đời và thanh lịch nhất. Hệ thống Unix là ví dụ kinh điển: lệnh "cat file.txt | grep error | sort | uniq" là một pipeline hoàn chỉnh. Mỗi lệnh là một filter, dấu | là pipe. Ưu điểm lớn nhất là tính tái sử dụng — bạn có thể ghép các filter theo thứ tự khác nhau để tạo ra hành vi mới.
> [Image: 21:9 aspect ratio and white background of data flow diagram showing a Pipe-and-Filter pipeline with five stages — Input Source (document icon) → Filter 1: Tokenizer (scissors icon) → Filter 2: Parser (tree icon) → Filter 3: Optimizer (gear icon) → Filter 4: Code Generator (chip icon) → Output (file icon) — connected by horizontal arrows labeled "pipe"; each filter shown as a rounded rectangle; colorful 3d and clean academic vector style, bold sans-serif labels, blue color scheme]
Speaker note: Nhìn vào sơ đồ này, các bạn thấy rõ đặc trưng của Pipe-and-Filter: dữ liệu chỉ chảy một chiều, từ trái sang phải. Mỗi filter hoàn toàn không biết nó đang nhận dữ liệu từ đâu hay gửi đến đâu — nó chỉ biết: nhận input, xử lý, trả output. Đây chính là lý do kiến trúc này dễ kiểm thử và tái sử dụng.
Speaker note: Batch Sequential là phong cách cổ điển nhất — xuất hiện từ thời mainframe. Hình dung như một dây chuyền sản xuất: công đoạn 1 hoàn thành toàn bộ sản phẩm rồi mới chuyển sang công đoạn 2. Tuy đơn giản nhưng vẫn rất phổ biến trong các hệ thống xử lý nghiệp vụ lớn như ngân hàng, kế toán — nơi tính chính xác quan trọng hơn tốc độ phản hồi tức thời.
> [Image: 21:9 aspect ratio and white background of batch sequential processing diagram showing four discrete processing stages arranged left to right — Stage 1: Thu thập dữ liệu (inbox-tray icon, blue) → Stage 2: Xác thực & Làm sạch (shield-check icon, orange) → Stage 3: Tính toán & Xử lý (calculator icon, green) → Stage 4: Xuất kết quả (file-export icon, purple) — each stage shown as a large rounded rectangle with a "WAIT" barrier between stages (hourglass icon); input dataset shown as a stack of documents entering Stage 1; output report exiting Stage 4; arrows between stages labeled "batch complete → next stage"; colorful 3d and clean academic vector style, bold sans-serif labels, muted color palette]
Speaker note: Điểm khác biệt then chốt so với Pipe-and-Filter là các rào cản "WAIT" giữa các giai đoạn. Trong Pipe-and-Filter, dữ liệu chảy liên tục — bản ghi đầu tiên có thể đang ở Filter 3 trong khi bản ghi mới vẫn vào Filter 1. Trong Batch Sequential, toàn bộ lô dữ liệu phải hoàn tất Stage 1 trước khi Stage 2 bắt đầu. Điều này đảm bảo tính nhất quán của dữ liệu tại mỗi checkpoint — rất quan trọng cho các nghiệp vụ tài chính.
Speaker note: Đây là phong cách lập trình mà hầu hết sinh viên đã quen khi học lập trình cơ bản. Hàm main() gọi các hàm con, các hàm con lại gọi hàm con khác — tạo ra một cây gọi hàm. Nhược điểm lớn nhất là khi hệ thống phức tạp, hàm main trở thành "thần" kiểm soát tất cả mọi thứ — vi phạm nguyên tắc Single Responsibility.
> [Image: 21:9 aspect ratio and white background of hierarchical call tree diagram showing Main Program (crown icon, large blue box at top center) with downward arrows to three Level-1 Subroutines (readInput, processData, writeOutput — medium green boxes); processData further branches down to two Level-2 Subroutines (validateRecord, calculateResult — small orange boxes); all arrows are directed downward labeled "call" and dashed arrows return upward labeled "return"; call stack panel on right side showing execution order 1→2→3→4→5; colorful 3d and clean academic vector style, bold sans-serif labels, structured tree layout]
Speaker note: Sơ đồ cây gọi hàm này cho thấy luồng điều khiển hoàn toàn xuất phát từ Main Program. Hãy chú ý stack panel bên phải — nó mô phỏng lại call stack thực tế trong bộ nhớ khi chương trình chạy. Khi main gọi processData, processData gọi validateRecord — validateRecord phải hoàn thành và trả về trước khi processData tiếp tục. Đây là "synchronous" và "blocking" hoàn toàn — đặc trưng của Call and Return style.
Speaker note: OO Systems là phong cách Call and Return nhưng phân tán trách nhiệm ra nhiều đối tượng thay vì tập trung vào main program. Mỗi đối tượng chịu trách nhiệm về một phần logic — đây là bước tiến lớn so với Main Program & Subroutine. Sinh viên cần lưu ý rằng OO là phong cách tổ chức code, không phải ngôn ngữ — bạn có thể viết OO bằng C nếu muốn.
> [Image: 21:9 aspect ratio and white background of UML object collaboration diagram showing four objects in a distributed layout — Client (user icon, blue box), OrderService (cart icon, green box), PaymentService (credit card icon, orange box), NotificationService (bell icon, purple box) — connected by directed arrows representing message passing; arrows labeled with method calls "placeOrder()", "charge(amount)", "sendConfirmation()"; each object box shows private state fields (e.g. "orderId, status") hidden behind a lock icon to illustrate encapsulation; a separate panel shows polymorphism: two classes Dog and Cat both implementing speak() with different outputs; colorful 3d and clean academic vector style, bold sans-serif labels]
Speaker note: Điểm mấu chốt của sơ đồ này là mỗi đối tượng có vùng trạng thái riêng được che giấu — không đối tượng nào truy cập trực tiếp vào dữ liệu nội tại của đối tượng khác. Mọi tương tác đều qua thông điệp (method calls). So sánh với Main Program & Subroutine: ở đó dữ liệu thường là biến global, bất kỳ subroutine nào cũng có thể đọc và ghi. OO đảo ngược điều này — đối tượng sở hữu dữ liệu và chỉ cung cấp giao diện có kiểm soát.
Speaker note: Layered Architecture là phong cách phổ biến nhất trong phát triển ứng dụng doanh nghiệp. Nguyên tắc cốt lõi là dependency chỉ đi một chiều: từ trên xuống. Lớp Presentation không bao giờ truy cập trực tiếp Database — nó phải đi qua Business Logic rồi Data Access. Điều này tạo ra sự tách biệt rõ ràng và dễ bảo trì. Chúng ta sẽ xem xét kiến trúc này kỹ hơn ở Phần 4.
> [Image: 21:9 aspect ratio and white background of layered architecture flow diagram showing four horizontal layers stacked top to bottom — Layer 1: Presentation (browser icon, blue) → Layer 2: Business Logic (gear icon, green) → Layer 3: Data Access (magnifier-database icon, orange) → Layer 4: Database (cylinder icon, gray); a user figure on the left sends a request arrow entering Layer 1; a single solid arrow flows straight down through all layers labeled "call path"; a dashed arrow flows straight up labeled "return path"; a red cross symbol on a diagonal arrow between Presentation and Database directly, labeled "vi phạm kiến trúc"; right panel shows a dependency rule: "Layer N depends only on Layer N+1"; colorful 3d and clean academic vector style, bold sans-serif labels]
Speaker note: Sơ đồ này có một chi tiết quan trọng: mũi tên đỏ chéo với nhãn "vi phạm kiến trúc". Đây là lỗi phổ biến nhất khi implement Layered — lập trình viên vì lười hoặc vì deadline, truy cập thẳng database từ Presentation layer. Về mặt kỹ thuật code vẫn chạy, nhưng bạn đã phá vỡ tính cô lập của các lớp. Hệ quả: khi cần thay đổi database, bạn phải sửa cả Presentation layer. Nhắc sinh viên: kiến trúc là kỷ luật, không phải gợi ý.
Speaker note: Đây là một sự thay đổi tư duy quan trọng. Trong Call and Return, component A biết rõ nó đang gọi component B. Trong Event-based, component A chỉ nói "có sự kiện X xảy ra" — và không biết ai sẽ phản ứng. Điều này tạo ra sự linh hoạt rất lớn nhưng cũng là thách thức khi debug: bạn cần theo dõi luồng sự kiện thay vì luồng gọi hàm.
> [Image: 21:9 aspect ratio and white background of side-by-side comparison diagram divided into two halves by a vertical divider; LEFT half labeled "Call and Return" (blue header): Component A (box) with a solid directed arrow pointing directly to Component B (box), labeled "explicit call — A knows B"; RIGHT half labeled "Event-based / Implicit Invocation" (green header): Component A (box) with an arrow pointing to a central Event Bus (lightning-bolt icon, circle), Event Bus with arrows fanning out to Component B, Component C, Component D (three boxes), arrow from A labeled "emit: UserRegistered", arrows to subscribers labeled "handle()"; a note below: "A does not know B, C, or D exist"; colorful 3d and clean academic vector style, bold sans-serif labels, strong visual contrast between halves]
Speaker note: Sơ đồ so sánh này là cốt lõi của việc hiểu Implicit Invocation. Ở vế trái, A và B bị buộc chặt — nếu bạn muốn thêm component C cũng xử lý event đó, bạn phải sửa code của A. Ở vế phải, bạn chỉ cần đăng ký C vào Event Bus — A không cần biết và không cần thay đổi. Đây là nguyên tắc Open/Closed: mở để mở rộng, đóng để sửa đổi. Event-based architecture thực thi nguyên tắc này ở cấp độ kiến trúc.
Speaker note: Khi một kiến trúc sư lựa chọn phong cách kiến trúc, họ không chỉ nhìn vào yêu cầu kỹ thuật. Họ phải hỏi: team có kinh nghiệm với phong cách này không? Có đủ thời gian để implement đúng cách không? Hệ thống sẽ phát triển theo hướng nào trong 3-5 năm tới? Một kiến trúc quá phức tạp so với nhu cầu thực tế cũng là một lỗi thiết kế.
Speaker note: Bảng này là công cụ tham khảo nhanh. Chú ý rằng trong thực tế, hầu hết hệ thống lớn kết hợp nhiều phong cách: ví dụ một ứng dụng thương mại điện tử có thể dùng Layered cho core business logic, Event-driven cho thông báo và tích hợp bên thứ ba, và Batch Sequential cho báo cáo định kỳ.
Speaker note: Layered Architecture là kiến trúc mà hầu hết sinh viên sẽ gặp ngay trong dự án thực tế đầu tiên. Nguyên tắc vàng là: dependency chỉ đi từ trên xuống dưới. Nếu bạn thấy lớp Business Logic đang import trực tiếp từ lớp Presentation, đó là dấu hiệu vi phạm kiến trúc. Lợi ích lớn nhất là khả năng thay thế: bạn có thể đổi từ REST API sang GraphQL mà không cần thay đổi Business Logic.
Speaker note: Nhược điểm "overhead" thường bị phóng đại. Với ứng dụng web thông thường, chi phí gọi hàm qua các lớp gần như không đáng kể so với chi phí network hay database. Vấn đề thực sự hơn là Anemic Domain Model — khi Business Logic Layer trở thành lớp truyền dữ liệu đơn giản mà không có logic nghiệp vụ thực sự, vi phạm mục đích ban đầu của kiến trúc này.
Speaker note: Client-Server là kiến trúc nền tảng của Internet. Mỗi khi bạn mở trình duyệt và truy cập một trang web, bạn đang thực hiện một giao dịch Client-Server. Điểm mạnh của mô hình này là server là nguồn sự thật duy nhất — dữ liệu không bị phân tán ra nhiều máy client. Điểm yếu là server là điểm tập trung, nếu server gặp sự cố thì tất cả client đều bị ảnh hưởng.
Speaker note: P2P là đối cực với Client-Server. Thay vì một server phục vụ nhiều client, mỗi máy vừa là client vừa là server. BitTorrent là ví dụ hoàn hảo: khi bạn download file, bạn cũng đồng thời upload phần đã download cho người khác. Blockchain là ví dụ hiện đại hơn: mỗi node lưu một bản sao đầy đủ của ledger và tham gia vào quá trình xác thực giao dịch.
Speaker note: Trong thực tế, nhiều hệ thống kết hợp cả hai mô hình. Skype ban đầu dùng P2P thuần túy — rất hiệu quả nhưng khó kiểm soát nội dung và bảo mật. Microsoft sau khi mua lại đã chuyển sang mô hình hybrid với super-nodes là server trung tâm. Đây là ví dụ điển hình của đánh đổi giữa hiệu năng và khả năng quản lý.
Speaker note: Event-driven Architecture thay đổi hoàn toàn cách các thành phần tương tác. Thay vì A gọi B trực tiếp, A chỉ nói "sự kiện X đã xảy ra" và không quan tâm ai xử lý. Điều này cho phép thêm tính năng mới (thêm consumer mới) mà không cần sửa code hiện tại — đây là sức mạnh thực sự của kiến trúc này. Kafka là công nghệ phổ biến nhất hiện nay đóng vai trò Event Broker.
Speaker note: SOA xuất hiện vào những năm 2000 như giải pháp cho bài toán tích hợp hệ thống doanh nghiệp. Ý tưởng là thay vì mỗi ứng dụng kết nối trực tiếp với nhau tạo ra "mạng nhện" phức tạp, tất cả giao tiếp đi qua Enterprise Service Bus. SOA là tiền thân trực tiếp của Microservices — phần lớn khái niệm giống nhau, nhưng Microservices đẩy xa hơn về mức độ tách biệt và triển khai độc lập.
Speaker note: Sơ đồ này minh họa rõ vai trò trung tâm của ESB trong SOA. ESB không chỉ là kênh truyền dữ liệu — nó còn xử lý routing (gửi request đến đúng service), transformation (chuyển đổi định dạng dữ liệu), và orchestration (điều phối quy trình nghiệp vụ phức tạp liên quan nhiều service). Đây là điểm khác biệt lớn với Microservices hiện đại, nơi logic orchestration được phân tán ra các service riêng lẻ.
Speaker note: Đây là bài tập nhận diện — sinh viên cần áp dụng kiến thức về đặc trưng của từng phong cách để phân loại. Gợi ý đáp án: A → Batch Sequential (xử lý theo lô, không tương tác người dùng, tuần tự từng bước); B → Layered Architecture (tách biệt rõ Presentation, Business Logic, Data Access); C → Event-based / Implicit Invocation (một sự kiện "UserRegistered" kích hoạt nhiều handler độc lập mà không cần module nào biết về nhau). Dành 5-7 phút cho nhóm thảo luận trước khi chốt đáp án.
Speaker note: Bài tập này không có đáp án tuyệt đối đúng — mục tiêu là buộc sinh viên suy nghĩ về trade-off thực tế. Client-Server: dễ kiểm soát nội dung, dễ enforce chính sách, nhưng chi phí server tăng theo số người dùng. P2P: tự mở rộng tự nhiên, chi phí thấp, nhưng cực kỳ khó kiểm soát nội dung và bảo mật. Trong bối cảnh trường đại học với yêu cầu compliance và quản lý, Client-Server thường là lựa chọn thực tế hơn — dù kém "cool" hơn về mặt kỹ thuật.
Speaker note: Bài tập thiết kế mở — không có một đáp án duy nhất. Một kiến trúc hợp lý cho bài này có thể kết hợp: Client-Server cho giao tiếp mobile app với backend; Event-driven cho luồng thông báo (đặt đơn → nhà hàng nhận, đơn sẵn sàng → tài xế nhận, giao xong → billing service và email service); Layered cho core business logic của từng service. Đây là bài tập giúp sinh viên nhận ra rằng hệ thống thực tế thường là hybrid của nhiều phong cách, không phải một phong cách thuần túy.