Software Design

Software Architecture

Kiến Trúc Phần Mềm

MSc. Ngô Ngọc Đăng Khoa
Software Design

Nội dung buổi học

  1. Kiến trúc Phần mềm
  2. Các Phong Cách Kiến Trúc Cổ điển
  3. Lựa chọn Phong cách Kiến trúc Phù hợp
  4. Các Phong Cách Kiến Trúc phổ biến
MSc. Ngô Ngọc Đăng Khoa
Software Design

Kiến trúc phần mềm

MSc. Ngô Ngọc Đăng Khoa
Software Design

Kiến Trúc Phần Mềm Là Gì?

Kiến trúc phần mềm là cấu trúc tổng thể của hệ thống — bao gồm các thành phần, quan hệ giữa chúng, và các nguyên tắc chi phối thiết kế.

  • Cấu trúc hệ thống: phân chia thành các thành phần (component) lớn
  • Quan hệ: cách các thành phần tương tác và phụ thuộc lẫn nhau
  • Nguyên tắc: quyết định về công nghệ, giao tiếp, và phân phối trách nhiệm
  • Mục tiêu: đáp ứng yêu cầu chức năng phi chức năng (hiệu năng, bảo mật, khả năng mở rộng)
MSc. Ngô Ngọc Đăng Khoa
Software Design

Vai Trò Của Kiến Trúc Sư Phần Mềm

Kiến trúc sư phần mềm (Software Architect) chịu trách nhiệm đưa ra các quyết định thiết kế cấp cao ảnh hưởng toàn bộ hệ thống.

  • Xác định phong cách kiến trúc phù hợp với yêu cầu
  • Định nghĩa giao diện giữa các thành phần lớn
  • Cân bằng các đánh đổi (trade-off): tốc độ, chi phí, độ phức tạp
  • Đảm bảo kiến trúc có thể mở rộng và bảo trì lâu dài
  • Hướng dẫn và đánh giá quyết định kỹ thuật của đội

MSc. Ngô Ngọc Đăng Khoa
Software Design

Kiến Trúc vs. Thiết Kế Chi Tiết

Kiến trúc định hình cái gìtại sao; thiết kế chi tiết trả lời như thế nào.

Kiến trúc (Architecture)

  • Phạm vi: toàn bộ hệ thống
  • Quyết định: chọn phong cách, phân chia module lớn
  • Người thực hiện: kiến trúc sư phần mềm
  • Thay đổi: tốn kém, ảnh hưởng rộng

Thiết kế Chi tiết (Detailed Design)

  • Phạm vi: từng module, class, hàm
  • Quyết định: thuật toán, cấu trúc dữ liệu, pattern
  • Người thực hiện: lập trình viên / tech lead
  • Thay đổi: linh hoạt hơn, ảnh hưởng cục bộ
MSc. Ngô Ngọc Đăng Khoa
Software Design

Các Phong Cách Kiến Trúc Cổ điển

MSc. Ngô Ngọc Đăng Khoa
Software Design

Phân Loại Phong Cách Kiến Trúc

Phong cách kiến trúc (Architectural Style) là một mẫu tổ chức hệ thống tổng quát — định nghĩa cách các thành phần tương tác và luồng dữ liệu chảy qua hệ thống.

  • Data Flow Styles: dữ liệu chảy qua chuỗi biến đổi tuần tự
  • Call and Return Styles: các thành phần gọi nhau theo cấu trúc phân cấp
  • Independent Components: các thành phần hoạt động độc lập, giao tiếp qua sự kiện
MSc. Ngô Ngọc Đăng Khoa
Software Design

MSc. Ngô Ngọc Đăng Khoa
Software Design

Data Flow — Pipe-and-Filter

Dữ liệu chảy qua một chuỗi bộ lọc (filter) kết nối bằng đường ống (pipe) — mỗi filter biến đổi dữ liệu đầu vào thành đầu ra.

  • Filter: thành phần xử lý độc lập, không biết filter nào đứng trước/sau
  • Pipe: kênh truyền dữ liệu một chiều giữa các filter
  • Ưu điểm: dễ thêm/bỏ/hoán đổi filter, xử lý song song tự nhiên
  • Nhược điểm: không phù hợp khi cần tương tác người dùng phức tạp
  • Ví dụ: pipeline xử lý ảnh, compiler (lexer → parser → optimizer → codegen)
MSc. Ngô Ngọc Đăng Khoa

Sơ Đồ: Pipe-and-Filter

Software Design

Data Flow — Batch Sequential

Hệ thống xử lý dữ liệu theo từng lô (batch) qua các bước tuần tự — mỗi bước hoàn thành toàn bộ trước khi bước tiếp theo bắt đầu.

  • Đặc trưng: không có tương tác người dùng trong quá trình xử lý
  • Khác với Pipe-and-Filter: dữ liệu không chảy liên tục — mỗi bước chờ bước trước xong hẳn
  • Ưu điểm: đơn giản, dễ kiểm soát, phù hợp xử lý khối lượng lớn
  • Nhược điểm: độ trễ cao, không xử lý theo thời gian thực
  • Ví dụ: xử lý bảng lương cuối tháng, ETL pipeline trong data warehouse
MSc. Ngô Ngọc Đăng Khoa

Sơ Đồ: Batch Sequential

Software Design

Call and Return — Main Program & Subroutine

Chương trình chính (main program) điều phối luồng thực thi bằng cách gọi các chương trình con (subroutine) theo thứ tự xác định.

  • Cấu trúc phân cấp: main → subroutine cấp 1 → subroutine cấp 2
  • Luồng điều khiển: hoàn toàn tập trung tại main program
  • Ưu điểm: dễ hiểu, dễ debug, theo dõi luồng thực thi tuyến tính
  • Nhược điểm: khó mở rộng, main program dễ trở nên phức tạp (god object)
  • Ví dụ: các chương trình thủ tục cổ điển viết bằng C, Pascal, COBOL
MSc. Ngô Ngọc Đăng Khoa

Sơ Đồ: Main Program & Subroutine

Software Design

Call and Return — Hệ Thống Hướng Đối Tượng

Hệ thống hướng đối tượng (OO Systems) tổ chức code thành các đối tượng tự quản lý trạng thái và hành vi của mình, giao tiếp qua gửi thông điệp.

  • Đóng gói (Encapsulation): đối tượng che giấu trạng thái nội tại
  • Kế thừa (Inheritance): tái sử dụng và mở rộng hành vi
  • Đa hình (Polymorphism): cùng interface, nhiều cách thực thi khác nhau
  • Ưu điểm: mô hình hóa tự nhiên, dễ tái sử dụng, dễ mở rộng
  • Ví dụ: Java EE applications, C++ systems, Python frameworks
MSc. Ngô Ngọc Đăng Khoa

Sơ Đồ: OO Systems — Giao Tiếp Qua Thông Điệp

Software Design

Call and Return — Layered Architecture

Kiến trúc phân lớp (Layered Architecture) tổ chức hệ thống thành các lớp xếp chồng — mỗi lớp chỉ sử dụng dịch vụ của lớp ngay bên dưới và cung cấp dịch vụ cho lớp ngay bên trên.

  • Phân tách trách nhiệm: mỗi lớp có một vai trò rõ ràng
  • Nguyên tắc: lớp trên gọi xuống, lớp dưới không biết lớp trên tồn tại
  • Ưu điểm: dễ thay thế từng lớp, dễ kiểm thử từng tầng độc lập
  • Nhược điểm: yêu cầu phải đi qua nhiều lớp, có thể gây overhead
  • Ví dụ điển hình: Presentation → Business Logic → Data Access → Database
MSc. Ngô Ngọc Đăng Khoa

Sơ Đồ: Layered Architecture — Luồng Gọi

Software Design

Independent Components — Event-based / Implicit Invocation

Các thành phần không gọi nhau trực tiếp — thay vào đó, chúng phát sự kiện (emit events) và đăng ký lắng nghe (subscribe) sự kiện từ các thành phần khác.

  • Khớp nối lỏng (loose coupling): thành phần phát sự kiện không biết ai xử lý
  • Implicit Invocation: việc gọi xảy ra ngầm định qua cơ chế sự kiện
  • Ưu điểm: dễ thêm thành phần mới mà không sửa code cũ
  • Nhược điểm: khó theo dõi luồng thực thi, khó debug
  • Ví dụ: GUI frameworks (onClick, onChange), message queues (Kafka, RabbitMQ)
MSc. Ngô Ngọc Đăng Khoa

Event-based — Call and Return vs. Implicit Invocation

Software Design

Lựa Chọn Phong Cách Kiến Trúc

MSc. Ngô Ngọc Đăng Khoa
Software Design

Tiêu Chí Lựa Chọn Kiến Trúc

Không có phong cách kiến trúc nào là tốt nhất tuyệt đối — mỗi lựa chọn là một đánh đổi (trade-off) dựa trên ngữ cảnh cụ thể.

  • Yêu cầu chức năng: hệ thống cần làm gì? (streaming, batch, interactive?)
  • Yêu cầu phi chức năng: hiệu năng, độ trễ, khả năng mở rộng, bảo mật
  • Đội ngũ: kinh nghiệm và quy mô của team phát triển
  • Thời gian và ngân sách: độ phức tạp triển khai và vận hành
  • Khả năng thay đổi: hệ thống có thường xuyên mở rộng tính năng không?
MSc. Ngô Ngọc Đăng Khoa
Software Design

So Sánh Các Phong Cách Kiến Trúc

Mỗi phong cách phù hợp với một nhóm bài toán khác nhau — hiểu rõ đặc trưng giúp lựa chọn đúng.

Phong cách Phù hợp khi Tránh khi
Pipe-and-Filter Xử lý luồng dữ liệu tuần tự Cần tương tác người dùng
Batch Sequential Xử lý khối lượng lớn, không thời gian thực Cần phản hồi tức thì
Layered Ứng dụng doanh nghiệp, dễ bảo trì Hiệu năng cao, độ trễ thấp
OO Systems Mô hình hóa nghiệp vụ phức tạp Xử lý dữ liệu thuần túy
Event-driven Hệ thống phân tán, mở rộng linh hoạt Cần luồng thực thi rõ ràng
MSc. Ngô Ngọc Đăng Khoa
Software Design

Các Phong Cách Kiến Trúc Phổ Biến

MSc. Ngô Ngọc Đăng Khoa
Software Design

Layered Architecture

Thuộc nhóm Call and Return Styles — hệ thống được tổ chức thành các lớp xếp chồng, mỗi lớp phục vụ lớp trên và sử dụng lớp dưới.

4 lớp điển hình:

  • Presentation Layer: giao diện người dùng (UI/API)
  • Business Logic Layer: quy tắc nghiệp vụ, xử lý logic
  • Data Access Layer: truy vấn và thao tác với dữ liệu
  • Database Layer: lưu trữ dữ liệu vật lý

MSc. Ngô Ngọc Đăng Khoa
Software Design

Layered Architecture — Ưu và Nhược Điểm

Layered Architecture đạt được sự cân bằng tốt giữa tính tổ chức và độ phức tạp — phù hợp với đa số ứng dụng doanh nghiệp vừa và nhỏ.

  • Separation of Concerns: mỗi lớp có trách nhiệm rõ ràng và độc lập
  • Testability: có thể kiểm thử từng lớp bằng cách mock lớp phụ thuộc
  • Maintainability: thay đổi một lớp ít ảnh hưởng đến các lớp còn lại
  • Overhead: mọi request đều phải đi qua tất cả các lớp, dù đơn giản
  • Anemic Domain Model: nguy cơ Business Logic chỉ là lớp trung gian rỗng
MSc. Ngô Ngọc Đăng Khoa
Software Design

Client-Server Architecture

Thuộc nhóm Call and Return Styles — hệ thống phân chia thành client (yêu cầu dịch vụ) và server (cung cấp dịch vụ), giao tiếp qua mạng.

  • Client: khởi tạo yêu cầu, hiển thị kết quả cho người dùng
  • Server: lắng nghe, xử lý yêu cầu, trả về phản hồi
  • Giao tiếp: request-response qua HTTP, TCP, hoặc RPC
  • Ưu điểm: tập trung hóa dữ liệu, dễ quản lý bảo mật và cập nhật
  • Ví dụ: trình duyệt web ↔ web server, mobile app ↔ REST API

MSc. Ngô Ngọc Đăng Khoa
Software Design

Peer-to-Peer Architecture

Thuộc nhóm Independent Components — mỗi node (peer) vừa đóng vai client vừa đóng vai server, không có node trung tâm điều phối.

  • Phi tập trung: không có server trung tâm, mọi node bình đẳng
  • Khả năng phục hồi: hệ thống tiếp tục hoạt động dù nhiều node bị mất
  • Khả năng mở rộng: thêm node tự động tăng tài nguyên hệ thống
  • Nhược điểm: khó quản lý bảo mật, khó đảm bảo tính nhất quán dữ liệu
  • Ví dụ: BitTorrent, blockchain, Skype (trước khi chuyển sang server-based)

MSc. Ngô Ngọc Đăng Khoa
Software Design

So Sánh: Client-Server vs. Peer-to-Peer

Client-Server tối ưu cho kiểm soát tập trung; Peer-to-Peer tối ưu cho khả năng phục hồi và mở rộng phi tập trung.

Client-Server

  • Dễ quản lý, bảo mật tập trung
  • Server là điểm nghẽn (bottleneck)
  • Phụ thuộc vào tính sẵn sàng của server
  • Dữ liệu nhất quán, dễ kiểm soát
  • Phù hợp: web app, mobile app, SaaS

Peer-to-Peer

  • Không có điểm nghẽn trung tâm
  • Khó kiểm soát, bảo mật phức tạp hơn
  • Tiếp tục hoạt động dù mất nhiều node
  • Đồng bộ dữ liệu phức tạp
  • Phù hợp: file sharing, blockchain, CDN
MSc. Ngô Ngọc Đăng Khoa
Software Design

Event-driven Architecture

Thuộc nhóm Independent Components — các thành phần giao tiếp qua sự kiện (events) thay vì gọi nhau trực tiếp, tạo ra khớp nối lỏng hoàn toàn.

  • Event Producer: phát sự kiện khi có thay đổi trạng thái
  • Event Broker: trung gian định tuyến sự kiện (Kafka, RabbitMQ)
  • Event Consumer: đăng ký và xử lý các sự kiện quan tâm
  • Ưu điểm: dễ mở rộng, thêm consumer mà không sửa producer
  • Ví dụ: hệ thống thông báo, microservices integration, IoT

MSc. Ngô Ngọc Đăng Khoa
Software Design

Service-Oriented Architecture (SOA)

Thuộc nhóm Call and Return Styles — hệ thống được xây dựng từ các dịch vụ (services) độc lập, giao tiếp qua giao thức chuẩn, có thể tái sử dụng và kết hợp linh hoạt.

  • Service: đơn vị chức năng độc lập, có interface rõ ràng
  • Loose Coupling: dịch vụ không phụ thuộc vào implementation của nhau
  • Reusability: dịch vụ được tái sử dụng bởi nhiều ứng dụng khác nhau
  • Interoperability: giao tiếp qua chuẩn mở (SOAP, REST, gRPC)
  • Ví dụ: hệ thống doanh nghiệp tích hợp ERP, CRM, và billing

MSc. Ngô Ngọc Đăng Khoa
Software Design

Bài Tập Áp Dụng

MSc. Ngô Ngọc Đăng Khoa
Software Design

Bài Tập 1: Nhận Diện Phong Cách Kiến Trúc

Cho mỗi mô tả hệ thống bên dưới, hãy xác định phong cách kiến trúc phù hợp nhất và giải thích lý do.

Tình huống A — Hệ thống xử lý ảnh y tế:
Mỗi đêm, bệnh viện chạy một job tự động: đọc 10.000 ảnh X-quang từ thiết bị, chuyển đổi sang định dạng chuẩn, phân tích bất thường bằng AI, lưu kết quả vào hồ sơ bệnh nhân. Không có người dùng tương tác trong quá trình này.

Tình huống B — Ứng dụng đặt vé máy bay:
Người dùng truy cập web, tìm kiếm chuyến bay, đặt vé và thanh toán. Hệ thống cần phân tách rõ giữa giao diện, quy tắc nghiệp vụ đặt vé, và truy cập cơ sở dữ liệu chuyến bay.

MSc. Ngô Ngọc Đăng Khoa
Software Design

Tình huống C — Hệ thống thông báo đa kênh:
Khi người dùng đăng ký tài khoản, hệ thống cần đồng thời: gửi email chào mừng, gửi SMS xác thực, tạo hồ sơ analytics, và cấp điểm thưởng. Mỗi tác vụ do một module riêng biệt xử lý.

MSc. Ngô Ngọc Đăng Khoa
Software Design

Bài Tập 2: Phân Tích Trade-Offs

Một startup đang xây dựng nền tảng chia sẻ tài liệu học tập cho sinh viên. Hãy phân tích ưu và nhược điểm của hai phương án kiến trúc được đề xuất.

Phương án X — Client-Server:
Một server trung tâm lưu toàn bộ tài liệu. Sinh viên upload và download thông qua web app. Server xử lý xác thực, phân quyền, và giới hạn dung lượng.

Phương án Y — Peer-to-Peer:
Mỗi sinh viên cài app trên máy tính. Tài liệu được chia sẻ trực tiếp giữa các máy qua mạng P2P. Không có server trung tâm lưu trữ nội dung.

MSc. Ngô Ngọc Đăng Khoa
Software Design

Câu hỏi thảo luận:

  • Phương án nào dễ kiểm soát vi phạm bản quyền hơn?
  • Phương án nào hoạt động tốt hơn khi số lượng sinh viên tăng gấp 10 lần?
  • Trường đại học nên chọn phương án nào? Tại sao?
MSc. Ngô Ngọc Đăng Khoa
Software Design

Bài Tập 3: Thiết Kế Kiến Trúc Mini

Nhóm 3-4 sinh viên. Thời gian: 10 phút. Vẽ sơ đồ kiến trúc cho hệ thống sau.

Yêu cầu hệ thống: Ứng dụng Giao đồ ăn

  • Khách hàng đặt món qua mobile app
  • Nhà hàng nhận đơn và xác nhận
  • Tài xế nhận thông báo đơn cần giao
  • Hệ thống theo dõi vị trí tài xế theo thời gian thực
  • Sau khi giao xong: tự động gửi hóa đơn qua email và trừ tiền ví
MSc. Ngô Ngọc Đăng Khoa
Software Design

Yêu cầu bài nộp:

  1. Liệt kê các thành phần chính của hệ thống
  2. Xác định phong cách kiến trúc cho từng phần (không nhất thiết một phong cách duy nhất)
  3. Vẽ sơ đồ tương tác giữa các thành phần
MSc. Ngô Ngọc Đăng Khoa
Software Design

Tóm Tắt

Kiến trúc phần mềm là nền tảng của mọi hệ thống — lựa chọn phong cách kiến trúc đúng sẽ quyết định khả năng phát triển và bảo trì lâu dài.

  • Kiến trúc định hình toàn bộ hệ thống; thiết kế chi tiết giải quyết từng thành phần
  • Data Flow: Pipe-and-Filter (streaming) và Batch Sequential (xử lý lô)
  • Call and Return: Main-Subroutine, OO Systems, Layered Architecture
  • Independent Components: Event-based — khớp nối lỏng qua sự kiện
  • Kiến trúc cơ bản: Layered, Client-Server, P2P, Event-driven, SOA — mỗi loại thuộc một phong cách và phù hợp với bài toán riêng
MSc. Ngô Ngọc Đăng Khoa

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.