Bài 3: Tìm hiểu về Use Case Diagram
Tóm tắt nhanh
- Trong bài trước, chúng ta đã tìm hiểu qua các khái niệm khi làm việc với UML cũng như tìm hiểu sơ qua các loại biểu đồ UML một cách cơ bản nhất và chúng ta cũng biết có 5 loại biểu đồ quan trọng và thường dùng nhất đó là use case diagram, class diagram, object diagram, state machine diagram và sequence diagram.
- Trong bài viết này, chúng ta sẽ đi sâu vào để học và sử dụng biểu đồ Use case (Use Case Diagram).
- Use case diagram là một loại biểu đồ cho phép chúng ta mô tả các trường hợp sử dụng mà hệ thống cần phát triển. Nó mô tả cái mà hệ thống nên làm nhưng không mô tả chi tiết các hành động thực thi như Data structures, algorithms,... Ngoài ra, use case diagram cũng mô hình hóa những tính năng và cho biết người dùng nào dùng tính năng nào.
- Một Use case diagram cũng có thể sử dụng để tài liệu hóa một hệ thống đã có sẵn và ghi lại người dùng nào được phép sử dụng những tính năng nào (điều này chính là thiết kế ngược, hệ thống sinh ra trước và thiết kế sinh ra sau).
- Trong use case diagram chúng ta có một khái niệm là use case. Use case (hay trường hợp sử dụng) là một khái niệm cơ bản của những phương pháp phát triển hệ thống theo hướng đối tượng. Nó được áp dụng trong toàn bộ quá trình phân tích và thiết kế tiến trình (process). Use case là đại diện cho những cái mà người dùng muốn hệ thống làm (hay chính là những requirement của người dùng đối với hệ thống).
- Chúng ta hoàn toàn có thể sử dụng một use case diagram để trả lời các câu hỏi sau:
- Hệ thống mô tả cái gì? (the system)
- Ai là người tương tác với hệ thống? (The Actors)
- Actors có thể làm cái gì? (The use case).
- Thoạt nhìn, biểu đồ use case được đánh giá là dễ nhìn và dễ học, vì thế mà nó lại hay bị đánh giá thấp vô cùng. Nội dung của một Use case diagram cần thể hiện được những kỳ vọng của khách hàng đối với hệ thống sắp phát triển. Nếu các use case bị bỏ sót hoặc mô tả thiếu chính xác sẽ khiến hệ thống gặp hậu quả cực kỳ nghiêm trọng như: chi phí phát triển và bảo trì tăng cao, người dùng không hài lòng,... Vì vậy, để xây dựng một hệ thống tối ưu, chúng ta cần phân tích và nắm vững kỹ thuật xây dựng Use Case Diagram một cách bài bản. Hãy cùng bắt đầu nhé!
1. Khái niệm Use Cases
-
Để đơn giản nhất thì ae cứ hiểu Use case là cái được dùng để mô tả một cái tính năng của hệ thống mà người dùng hoặc requirement mong muốn hệ thống có và ae phải dev nó.
-
Và để kích hoạt một use case thì chũng ta phải có hoặc là một Actor (người, vật thao tác vào hệ thống) hoặc một trigger event (một sự kiện xảy ra và use case đủ điều kiện để thực thi).
-
Để thể hiện trong hệ thống, use case sẽ được biểu diễn theo 3 dạng:
- Dạng 1: sử dụng một hình elip và đặt một đoạn text mô tả use case bên trong
- Dạng 2: sử dụng một hình elip tuy nhiên mô tả use case đươc đặt bên ngoài và ở dưới hình elip
- Dạng 3: sử dụng một hình chữ nhật, mô tả use case sẽ được đặt bên trong và góc trên bên trái của hình chữ nhật sẽ phải có một hình elip biểu thị rằng đó là một use case.
![image.png]()
-
Trong thực tế, người ta sẽ sử dụng dạng 1 để biểu diễn use case.
-
Và trong một hệ thống hoặc một tính năng, chúng ta sẽ phải có nhiều use case chứ đúng không? Và một bộ các use case cùng mô tả tính năng của hệ thống cung cấp người ta sẽ nhóm nó lại và đặt trong một hình chữ nhật với tên tính năng được đặt phía trên cùng của một hình chữ nhật như sau:

- Như hình ảnh ví dụ trên, nó đưa ra cho chúng ta một hệ thống quản lý học sinh gồm 3 tính năng chính: Query data học sinh, Phát chứng chỉ và thông báo kiểm tra. Và ở đây, Actor là professor hay nói cách khác, use case có thể được trigger bởi professor
2. Actors
- Một hệ thống, nếu không có sự tương tác thì hệ thống sinh ra chỉ để đắp xó. Chúng ta có thể nghĩ ra hàng chục, hàng trăm thậm chí cả nghìn use case nhưng tuy nhiên chúng ta không định hướng được đối tượng nào sử dụng use case nào hay các đối tượng nào sẽ tương tác với hệ thống vậy thì hệ thống sẽ chẳng đi tới đâu và chúng ta giống như những kẻ đẽo cày giữa đường.
- Vì vậy trong UML, người ta cho chúng ta một đối tượng đó là Actors. Đây là một đối tượng tương tác với hệ thống trong phạm vi những use cases của chúng.
- Một Actors được biểu diễn thông qua một hình người que (stick figures) hoặc một hình chữ nhật (chứa trong đó một label «actor») hoặc bằng một ký hiệu có thể định nghĩa tự do. Chúng có thể biểu diễn người, cũng có thể biểu diễn vật (non-human) như email, server. Nhìn chung thì nó có thể là một người hoặc một hệ thống tương tác nào đó mà tương tác với use case cụ thể có thể xảy ra

-
Chúng ta có hai loại Actor là active actor và passive actor.
- Một active actor là người hoặc hệ thống bên ngoài trực tiếp "nhấn nút" hoặc bắt đầu một quy trình.
- Ngược lại, một passive actor là các thực thể bên ngoài mà hệ thống cần gọi đến để hoàn thành công việc.
-
Trong ví dụ bên dưới đây, Actor Professor chính là một active actor còn actor Email Server là một passive actor. Professor có thể trực tiếp thực hiện hành vi thông báo tới học sinh (Inform student) trong khi Email server phải chờ có một yêu cầu từ một người nào đó hoặc một trigger nào đó thì mới thực hiện Inform student chứ nó không tự chủ động làm việc đó.

- Ngoài ra, trong use case diagrams cũng có thể chứa cả primary actor (tác nhân chính) và secondary actor (tác nhân phụ). Primary Actor là một actor sẽ nhận được lợi ích chính khi thực hiện use case và ngược lại, secondary actor sẽ nhận được ít lợi ích hơn. Nhìn vào ví dụ ta có thể thấy Professor sẽ là secondary trong khi student sẽ là primary khi thực hiện use case Exam. Tuy nhận được ít lợi ích hơn nhưng professor là cần thiết để có thể thực hiện được use case Exam này.
- Lưu ý: Một Actor luôn nằm ngoài hệ thống, nghĩa là người dùng (user) không bao giờ là một phần của hệ thống và vì vậy không bao giờ được triển khai. Tuy nhiên, dữ liệu người dùng có thể nằm trong hệ thống được đại diện bằng các class (class diagram). Vì thế, đôi khi rất khó để quyết định xem liệu rằng một thành phần có phải là một phần cần triển khai trong hệ thống hay đóng vai trò là một tác nhân. Như trong ví dụ trên, Email-server là một tác nhân, nó không thuộc hệ thống nhưng lại cần thiết để thực hiện use case "inform student". Tuy nhiên, nếu như hệ thống tự tích hợp tính năng thông báo (không cần máy chủ bên ngoài nào tác động) thì E-Mail server không còn là một tác nhân nữa. Trong trường hợp đó chỉ cần Acotr Professor để thông báo tới sinh viên.
3. Associations
3.1. Associations
- Để liên kết giữa Use case và Actor, người ta sử dụng một đường kẻ và không có chú thích hay node gì thêm. Đó là một association (liên kết).
- Mỗi Actor phải được kết nối với ít nhất một Use case, nếu không, chúng ta sẽ có một Actor chẳng liên quan gì tới hệ thống cả.
- Tương tự như vậy, mỗi use case phải được liên kết với một Actor. Nếu không, nó có nghĩa là chúng ta đang tạo ra một chức năng không phục vụ cho một đối tượng nào trong hệ thống, như vậy thì nó chẳng liên quan tới hệ thống nữa.
- Như vậy, một Association phải luôn luôn được kết nối, tức là nó luôn luôn ít nhất kết nối giữa một use case và một actor.

- Nếu có hai Actor cùng có Associations vào một use case. Điều này thể hiện rằng phải cùng có cả hai Actor đó tham gia vào thì use case mới thực hiện đúng. Vì nếu chỉ có student mà không có Assistant thì không thể vấn đáp được và ngược lại, nếu chỉ có Assistant mà không có student thì cũng không có ai vấn đáp. Nếu như bạn muốn thể hiện rằng nhiều Actor khác nhau có thể thực hiện được một use case (thực hiện độc lập) thì sẽ cần mối quan hệ kế thừa (inheritance relationship - sẽ nói ở phần sau)
3.2. Multiplicities
-
Ngoài ra, chúng ta cũng có khái niệm Multiplicities. Như có thể thấy ở ví dụ trên, ở liên kết giữa Student và Use case "Conduct Oral Exam", chỉ có một trợ giảng (Assistant) tham gia vào Use case đó nhưng có thể có từ 1 đến 3 Student tham gia vào use case này. Và con số 1..3 đó được gọi là Multiplicities.
-
Tóm lại, Multiplicities mô tả được số lượng mối quan hệ giữa các class. Cụ thể, nó sẽ nói lên được có bao nhiêu instances của một class có thể link tới một instance của một class khác. Ví dụ, khi order đồ ăn, nó sẽ mô tả được liệu rằng một khách hàng có thể đặt nhiều orders hay chỉ một order, nếu khách hàng nhấn order mà không chọn một món nào thì hệ thống sẽ "throw" một exception lỗi (nếu dùng try catch) để báo hiệu rằng cần có ít nhất 1 item khi order.. Hoặc trong một thư viện, sẽ có nhiều sách hay chỉ có một quyển sách. Việc hiểu được mối quan hệ này sẽ giúp cho chúng ta tránh được lỗi và chắc chắn rằng hệ thống thực hiện đúng như mong đợi. Nó cũng giúp chỉ dẫn cách mà data sẽ được lưu và quản lý trong database.
-
Một số quy tắc khi hệ hiện Multiplicities như sau:
- Nếu một Actor liên kết với một Use case chỉ thông qua Association thì tức là mặc định multiplicities là 1. Tức là chỉ có 1 Actor đó tham gia vào use case tại 1 thời điểm.
- 0...1 (zero or one) điều này ám chỉ rằng Actor có thể tham gia vào use case hoặc không. Lấy ví dụ như trường hợp dưới đây, Việc cấp bằng tốt nghiệp (Issue certificate) cần phải có ít nhất 1 Professor nhưng Assistant có thể có hoặc không có vẫn được.

- 1...* hoặc 1... (One or many): Phải có ít nhất 1 Actor tham gia vào hoặc sẽ có nhiều Actor tham gia vào use case đó.
- m...n: có ít nhất m Actor và tối đa n Actor tham gia vào use case.
-
Chúng ta sẽ có một ví dụ sau đây để minh họa rõ hơn về vấn đề này: Trong một lớp học, khi thông báo có bài kiểm tra, phải có ít nhất 1 giảng viên và sẽ có 1 hoặc nhiều học sinh lắng nghe. Nếu không có học sinh thì sẽ không có ai tham gia bài kiểm tra, và ngược lại không có giảng viên thì sẽ không có ai thông báo.
-
Đọc lý thuyết mãi thì khó hiểu nhỉ, nên tôi sẽ mô tả thông qua code C++ như sau:

- Tôi sẽ mô tả cho ae thông qua code thực tế như sau:
#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>
// ===================================================
// CLASS STUDENT
// Multiplicity 1..* trong use case "Announce Exam"
// → Phải có ít nhất 1 student nhận thông báo
// ===================================================
class Student {
private:
std::string name;
public:
Student(std::string name) : name(name) {}
std::string getName() const { return name; }
// Student nhận thông báo khi được gọi
void receiveAnnouncement(const std::string& message) const {
std::cout << " [Student - " << name << "] received: "
<< message << std::endl;
}
};
// ===================================================
// CLASS TEACHER
// Multiplicity 1 trong use case "Announce Exam"
// → Đúng 1 teacher thực hiện thông báo
// ===================================================
class Teacher {
private:
std::string name;
public:
Teacher(std::string name) : name(name) {}
std::string getName() const { return name; }
};
// ===================================================
// CLASS COURSE (System Boundary)
// Chứa use case "Announce Exam"
// Quản lý danh sách Student trong course
// ===================================================
class Course {
private:
std::string courseName;
std::vector<Student*> students; // 1..* : ít nhất 1 student
public:
Course(std::string courseName) : courseName(courseName) {}
std::string getCourseName() const { return courseName; }
// Đăng ký student vào course
void enrollStudent(Student* s) {
students.push_back(s);
}
const std::vector<Student*>& getStudents() const {
return students;
}
// Kiểm tra multiplicity 1..*
bool hasEnoughStudents() const {
return !students.empty();
}
};
// ===================================================
// USE CASE: ANNOUNCE EXAM
// Đây là nơi thể hiện multiplicity rõ ràng nhất:
// - teacher (1) : đúng 1, bắt buộc, không được null
// - course (1) : đúng 1 course được thông báo
// - students (1..*): ít nhất 1 student trong course
// ===================================================
class AnnounceExam {
private:
// ── Multiplicity 1 : Teacher ──────────────────
// Dùng reference (&) thay vì pointer
// → Không thể null, đảm bảo luôn có đúng 1 teacher
Teacher& teacher;
// ── Multiplicity 1 : Course ───────────────────
// Tương tự, dùng reference để đảm bảo luôn có course
Course& course;
std::string examDetails;
public:
// Constructor bắt buộc nhận teacher và course
// Không có default constructor → không thể tạo use case thiếu actor
AnnounceExam(Teacher& teacher, Course& course, std::string examDetails)
: teacher(teacher), course(course), examDetails(examDetails) {}
// Thực thi use case
void execute() {
std::cout << "============================================" << std::endl;
std::cout << "USE CASE: Announce Exam" << std::endl;
std::cout << "============================================" << std::endl;
// ── Kiểm tra multiplicity 1 : Teacher ─────
// (Đã đảm bảo bởi reference, không cần check thêm)
std::cout << "[Teacher - " << teacher.getName() << "] "
<< "is announcing exam for course: "
<< course.getCourseName() << std::endl;
std::cout << "Exam details: " << examDetails << std::endl;
std::cout << "--------------------------------------------" << std::endl;
// ── Kiểm tra multiplicity 1..* : Student ──
// Phải có ít nhất 1 student mới được thông báo
if (!course.hasEnoughStudents()) {
throw std::runtime_error(
"Cannot announce exam: course has no students! "
"At least 1 student required (multiplicity 1..*)."
);
}
// Thông báo đến từng student (1..*)
std::cout << "Notifying " << course.getStudents().size()
<< " student(s):" << std::endl;
for (const auto& student : course.getStudents()) {
student->receiveAnnouncement(examDetails);
}
std::cout << "============================================\n" << std::endl;
}
};
// ===================================================
// MAIN
// Mô phỏng 3 tình huống:
// 1. Hợp lệ: 1 teacher, nhiều students ✅
// 2. Vi phạm: không có student nào ❌
// 3. Vi phạm: cố tình không có teacher ❌
// ===================================================
int main() {
// ── Tình huống 1: Hợp lệ ──────────────────────
std::cout << "[Scenario 1] Valid: 1 teacher, 3 students\n" << std::endl;
{
Teacher teacher("Mr. Hung");
Course course("Advanced C++");
Student s1("Alice");
Student s2("Bob");
Student s3("Charlie");
course.enrollStudent(&s1); // 1..* : thêm từng student
course.enrollStudent(&s2);
course.enrollStudent(&s3);
// Tạo và thực thi use case
// teacher và course đều là reference → đảm bảo multiplicity 1
AnnounceExam use case(teacher, course, "Midterm Exam - Nov 30, Room 101");
use case.execute();
}
// ── Tình huống 2: Vi phạm 1..* ────────────────
// Course không có student nào → vi phạm multiplicity
std::cout << "[Scenario 2] Violate 1..*: no students enrolled\n" << std::endl;
{
Teacher teacher("Ms. Lan");
Course course("Data Structures");
// Không enroll student nào!
try {
AnnounceExam use case(teacher, course, "Final Exam - Dec 15");
use case.execute(); // Ném exception vì không có student
} catch (const std::runtime_error& e) {
std::cout << "Error: " << e.what() << "\n" << std::endl;
}
}
// ── Tình huống 3: Vi phạm multiplicity 1 ──────
// Cố tình tạo pointer teacher = nullptr để minh họa
// tại sao dùng reference tốt hơn pointer cho multiplicity 1
std::cout << "[Scenario 3] Why reference ensures multiplicity 1" << std::endl;
{
// Với POINTER (sai) → có thể null → vi phạm multiplicity 1
Teacher* teacherPtr = nullptr;
std::cout << " Using pointer: teacher can be nullptr → "
<< "multiplicity 1 NOT guaranteed!" << std::endl;
// Với REFERENCE (đúng) → không thể null → đảm bảo multiplicity 1
// Teacher& teacherRef = *teacherPtr; // ← compile được nhưng UB!
// AnnounceExam use case(*teacherPtr, ...); // ← NGUY HIỂM
std::cout << " Using reference: teacher CANNOT be nullptr → "
<< "multiplicity 1 IS guaranteed!\n" << std::endl;
}
return 0;
}
Output
[Scenario 1] Valid: 1 teacher, 3 students
============================================
USE CASE: Announce Exam
============================================
[Teacher - Mr. Hung] is announcing exam for course: Advanced C++
Exam details: Midterm Exam - Nov 30, Room 101
--------------------------------------------
Notifying 3 student(s):
[Student - Alice] received: Midterm Exam - Nov 30, Room 101
[Student - Bob] received: Midterm Exam - Nov 30, Room 101
[Student - Charlie] received: Midterm Exam - Nov 30, Room 101
============================================
[Scenario 2] Violate 1..*: no students enrolled
Error: Cannot announce exam: course has no students! At least 1 student required (multiplicity 1..*).
[Scenario 3] Why reference ensures multiplicity 1
Using pointer: teacher can be nullptr → multiplicity 1 NOT guaranteed!
Using reference: teacher CANNOT be nullptr → multiplicity 1 IS guaranteed!
4. Mỗi quan hệ giữa các Actors
- Trong một hệ thống, có nhiều trường hợp xảy ra, đôi khi có những trường hợp nhiều Actor cùng dùng chung một use case nhưng chúng phải hoạt động độc lập hoặc cũng có những trường hợp một use case cần phải có nhiều Actor cùng tham gia tại cùng 1 thời điểm thì mới hoạt động đúng. Khi này, chỉ sử dụng Association để liên kết use case và Actor là không đủ, chúng ta cần hơn vậy nữa.
- Lấy ví dụ trong một hệ thống hành chính tại trường học, ta có Use case diagram như sau:

-
Ở đây, cả professor và assistant đều có thể tham gia Query student data nhưng chúng hoạt động độc lập chứ không phải cần cả hai thì mới query được data. Vì thế, ta cần tạo một Actor gọi là super-actor (ở đây là Research Associate). Khi này Professor và Assistant sẽ có quan hệ kế thừa** (Inherite Relationship)** đối với Research Associate. Và nhìn vào như vậy ta có thể biết được rằng Professor và Assistant đều có thể tham gia vào Query Data của student.
-
Để thể hiện quan hệ kế thừa, người ta sử dụng mũi tên với phần mũi tên màu trắng.
-
Khi một Actor kế thừa từ một Actor khác, nó sẽ có quyền thực hiện toàn bộ use case mà Super Actor tham gia vào.
-
Nếu một Super Actor không phải là một object thực thì sẽ được đánh một nhãn {abstract} phía trên tên của nó.
- Không phải là một object tức là chỉ thể hiện đặc điểm chung. Ví dụ như khi truy cập vào web sẽ có hai thực thể là Admin và Client (khách hàng) cùng có thể thực hiện Login và Logout. Như vậy sẽ có một super actor là User và Admin và Client kế thừa vào nó).

-
-
Ngược lại, với Use case Issue certificate (trao bằng tốt nghiệp), cần phải có cả Professor và Assistant cùng tham gia thì mới có thể thực hiện.
-
Tóm lại, nếu một use case cần phải có sự tham gia của cả hai Actor thì chúng ta thể hiện như hình a, còn nếu muốn thể hiện rằng hai hoặc nhiều Actor có thể tham gia vào use case và sử dụng nó thì sử dụng Inherit Relation ship (hình b).

- Và với việc thể hiện như vậy, trong UML được gọi là khái quát hòa - Generalization. Đâylà một nội dung cơ bản sẽ được sử dụng nhiều trong Class Diagram khi lập trình hướng đối tượng.
5. Mối quan hệ giữa các Use Case
- Tương tự như Actor, các use case cũng cần có sự liên kết với nhau. Đôi khi cần thực hiện use case này thì phải thực thi một use case khác trước và cũng có lúc use case này là "option" của một use case khác.
5.1. Include
- Giả sử khi thực hiện mua hàng online, chúng ta cần phải làm một loạt các thao tác như: đăng nhập, chọn item, mua nó và thanh toán nó. Như vậy, nếu chúng ta không login thì sẽ không thể nào mua hàng được đúng không :>>
- Để thể hiện được điều này, chúng ta sẽ có mối quan hệ
<<include>>giữa các use case. - Khi một use case có mối quan hệ include với một use case khác thì nó thể hiện rằng phải thực hiện được use case này thì use case kia mới được thực thi.
- Quay lại với ví dụ mua hàng online, ta sẽ minh họa như sau:

- Từ sơ đồ trên, ta có thể thấy rằng, khi Client view các item, có thể không cần login. Tuy nhiên, khi muốn order item thì người đó được yêu cầu phải login thì mới thực hiện order được. Và cuối cùng, khi muốn thanh toán, rõ ràng người đó phải đã login và đã order thì mới thanh toán được. Đó chính là quan hệ
<<include>>của các use case.- Trong quan hệ include, Payment được gọi là Base use case còn Order Item được gọi là Include use case.
- Và khi một use case cần phải include từ một use case khác thì Base use case sẽ là nơi gốc của mũi tên và include use case sẽ là phần ngọn của mũi tên.
5.2. Extend
- Khác với include, quan hệ
extendlà quan hệ mà chúng ta được "lựa chọn" khi sử dụng. Dễ hiểu nhất chính là use case thanh toán (Payment) khi mua hàng. Chúng ta khi này sẽ có 2 option cơ bản hoặc là thanh toán ngay khi mua hàng hoặc thanh toán trả tiền khi nhận hàng. Nếu chọn thanh toán ngay thì ta lại có 2 option: 1 là thanh toán qua thẻ ngân hàng (Debit card) hoặc thanh toán qua thẻ trả sau (Credit Card):

- Use case Paynow và use case Pay when received ở đây được gọi là extending use case
- Trong quan hệ extent, hướng của mũi tên lại có phần ngược lại so với include. Cụ thể, hướng mũi tên sẽ được đi từ extending use case về phía hướng của base use case.
Kết luận
Vậy là chúng ta đã đi qua toàn bộ các khái niệm cơ bản của Use Case Diagram rồi lý thuyết thì dài nhưng tóm lại thì chỉ có vài ý chính sau:
- Use Case là đại diện cho những tính năng mà người dùng mong muốn hệ thống có.
- Actor là đối tượng tương tác với hệ thống, có thể là người hoặc một hệ thống khác, và luôn nằm ngoài hệ thống.
- Association là đường kết nối giữa Actor và Use Case, thể hiện sự tương tác. Mỗi Actor phải có ít nhất một Use Case và ngược lại.
- Multiplicities mô tả số lượng instance của Actor tham gia vào một Use Case tại cùng một thời điểm.
- Generalization giúp nhóm các Actor có cùng đặc điểm lại, tránh lặp lại các Association giống nhau.
- Include thể hiện rằng Use Case này bắt buộc phải thực thi Use Case kia.
- Extend thể hiện rằng Use Case này có thể mở rộng thêm hành vi tùy chọn cho Use Case kia.
Dù trông có vẻ đơn giản và "dễ nhìn", nhưng một Use Case Diagram tốt đòi hỏi sự hiểu biết sâu về nghiệp vụ. Một diagram bị bỏ sót requirement hay mô tả sai actor có thể kéo theo hậu quả rất nặng nề về sau như tăng chi phí, delay dự án hay người dùng không hài lòng.
Một Use Case Diagram tốt = Nền tảng vững chắc cho toàn bộ hệ thống.
Ở bài tiếp theo, chúng ta sẽ tiếp tục khám phá Class Diagram — loại biểu đồ quan trọng bậc nhất trong UML, nơi mà các khái niệm như Multiplicity, Association, Generalization sẽ được sử dụng nhiều và chi tiết hơn rất nhiều. Hẹn gặp lại ae ở bài sau! 🚀
All rights reserved
