TÓM TẮT
- 1 1. Giới thiệu chung về UML và Class Diagram
- 2 2. Chuẩn bị trước khi vẽ Class Diagram
- 3 3. Quy tắc ký hiệu trong Class Diagram UML
- 4 4. Các bước vẽ Class Diagram chi tiết
- 4.1 Bước 1: Xác định các lớp chính
- 4.2 Bước 2: Định nghĩa thuộc tính và phương thức
- 4.3 Bước 3: Xác định quan hệ
- 4.4 Bước 4: Thêm multiplicity
- 4.5 Bước 5: Đánh dấu các interface và realization
- 4.6 Bước 6: Kiểm tra tính nhất quán
- 4.7 Bước 7: Đánh dấu các thuộc tính đặc biệt
- 4.8 Bước 8: Thêm các constraint (nếu cần)
- 5 5. Ví dụ thực tế: Class Diagram cho hệ thống Bán Hàng Trực Tuyến
- 6 6. Kỹ thuật nâng cao trong Class Diagram
- 7 7. Thực hành: Các bước vẽ Class Diagram trong công cụ thực tế
- 8 8. Lưu ý thường gặp và cách khắc phục
- 9 9. Ứng dụng Class Diagram trong quy trình phát triển phần mềm
- 10 10. Tổng kết
1. Giới thiệu chung về UML và Class Diagram
UML (Unified Modeling Language) là ngôn ngữ mô hình hoá chuẩn quốc tế, được thiết kế để mô tả, diễn đạt và truyền đạt các khái niệm trong thiết kế phần mềm, hệ thống và các quy trình kinh doanh. Trong số hơn 14 loại diagram mà UML hỗ trợ, Class Diagram (sơ đồ lớp) là một trong những loại quan trọng nhất, vì nó mô tả cấu trúc tĩnh của hệ thống: các lớp (class), thuộc tính (attribute), phương thức (operation) và mối quan hệ giữa các lớp.
Việc vẽ Class Diagram không chỉ giúp các nhà phát triển hiểu rõ cấu trúc hệ thống, mà còn hỗ trợ:
- Phân tích yêu cầu: Xác định các đối tượng cần thiết và cách chúng tương tác.
- Thiết kế kiến trúc: Định nghĩa các mô-đun, lớp dịch vụ, lớp dữ liệu…
- Giao tiếp nhóm: Cung cấp một ngôn ngữ chung để thảo luận và đồng nhất các quyết định thiết kế.
Bài viết này sẽ hướng dẫn bạn cách vẽ Class Diagram UML một cách chi tiết, từ việc chuẩn bị, lựa chọn công cụ, quy tắc ký hiệu, đến các kỹ thuật nâng cao như kế thừa đa dạng, quan hệ tổng hợp & hợp thành, và cách áp dụng vào dự án thực tế.
2. Chuẩn bị trước khi vẽ Class Diagram
2.1. Thu thập và phân tích yêu cầu
- Đọc tài liệu yêu cầu (SRS): Xác định các chức năng, quy trình nghiệp vụ và dữ liệu cần quản lý.
- Phân tích nghiệp vụ: Liệt kê các thực thể (entity) chính, ví dụ: Khách hàng, Đơn hàng, Sản phẩm, Thanh toán.
- Xác định ranh giới hệ thống: Định nghĩa rõ ràng những gì nằm trong phạm vi thiết kế và những gì là ngoại vi (có thể được mô tả bằng các diagram khác như Use Case Diagram).
2.2. Xác định các lớp (Class)
- Lớp thực thể (Entity Class): Thường tương ứng với bảng trong cơ sở dữ liệu (ví dụ:
Customer,Order). - Lớp dịch vụ (Service Class): Chứa logic nghiệp vụ (ví dụ:
OrderService,PaymentProcessor). - Lớp trợ trợ (Utility/Helper Class): Các hàm tiện ích không thuộc domain (ví dụ:
StringUtils). - Lớp giao diện (Interface): Định nghĩa các phương thức mà các lớp thực thi (ví dụ:
IRepository).
2.3. Chọn công cụ vẽ
| Công cụ | Ưu điểm | Nhược điểm |
|---|---|---|
| draw.io (diagrams.net) | Miễn phí, chạy trên trình duyệt, tích hợp Google Drive | Giao diện không chuyên sâu cho UML |
| StarUML | Hỗ trợ đầy đủ UML, export sang nhiều định dạng | Bản trả phí, giao diện có thể hơi phức tạp |
| Enterprise Architect | Tính năng mạnh mẽ, quản lý dự án lớn | Giá cao, yêu cầu máy mạnh |
| PlantUML | Định dạng text, dễ tích hợp CI/CD, hỗ trợ version control | Cần học cú pháp, không có giao diện kéo-thả |
| Visual Paradigm | Hỗ trợ nhiều loại diagram, có phiên bản Community | Giới hạn tính năng trong bản miễn phí |
Lựa chọn công cụ tùy thuộc vào quy mô dự án, ngân sách và thói quen làm việc của nhóm.
3. Quy tắc ký hiệu trong Class Diagram UML

Có thể bạn quan tâm: Cách Vẽ Chữ Trên Tường: Hướng Dẫn Từng Bước Để Tạo Nên Những Tác Phẩm Độc Đáo Và Ấn Tượng
3.1. Cấu trúc lớp
Mỗi lớp được biểu diễn bằng một hộp chữ nhật chia thành ba phần:
- Tên lớp (Class Name) – viết in đậm, thường đặt ở phần trên cùng.
- Thuộc tính (Attributes) – danh sách các biến thành viên, mỗi dòng có dạng:
visibility name : type multiplicity = defaultValue {property} visibility:+(public),-(private),#(protected),~(package).multiplicity:1,0..,1..…-
property:static,abstract,derived. -
Phương thức (Operations) – danh sách các hàm, mỗi dòng có dạng:
visibility name(parameterList) : returnType {property}
3.2. Các loại quan hệ
| Quan hệ | Ký hiệu | Mô tả |
|---|---|---|
| Association | Đường thẳng | Mối quan hệ “có” (has-a). Có thể có tên, vai trò (role) và multiplicity ở mỗi đầu. |
| Aggregation | Đường thẳng + hình thùng (hollow diamond) | Quan hệ “toàn bộ – một phần” yếu hơn, phần có thể tồn tại độc lập. |
| Composition | Đường thẳng + hình thùng (filled diamond) | Quan hệ “toàn bộ – một phần” mạnh, phần không tồn tại nếu toàn bộ bị xóa. |
| Generalization (Inheritance) | Đường thẳng mũi tên mở | Lớp con kế thừa lớp cha, mũi tên chỉ về lớp cha. |
| Realization | Đường thẳng mũi tên mở + nét đứt | Lớp thực thi interface. |
| Dependency | Đường nét đứt với mũi tên | Sử dụng tạm thời, không phải sở hữu. |
| Association Class | Hộp chữ nhật gắn vào association bằng nét | Mô tả thuộc tính/phương thức của một association. |
3.3. Các ký hiệu bổ trợ
- Stereotype (
<<interface>>,<<abstract>>): Đặt trong<< >>phía trên tên lớp để chỉ loại lớp. - Constraint (ràng buộc): Đặt trong
{}hoặc viết dưới dạng OCL (Object Constraint Language). - Visibility:
+,-,#,~.
4. Các bước vẽ Class Diagram chi tiết
Bước 1: Xác định các lớp chính
- Lập danh sách thực thể từ yêu cầu.
- Nhóm các thuộc tính chung vào lớp cha (nếu có).
- Xác định lớp dịch vụ cho các hành vi nghiệp vụ phức tạp.
Ví dụ, trong một hệ thống bán hàng trực tuyến, chúng ta có:
Customer,Order,OrderItem,Product,Payment,ShoppingCart,User,Admin.OrderService,PaymentService,ProductRepository.
Bước 2: Định nghĩa thuộc tính và phương thức
- Thuộc tính: Lấy từ các trường dữ liệu trong yêu cầu. Ví dụ,
CustomercócustomerId,name,email,address. - Phương thức: Dựa trên hành vi mà lớp cần thực hiện. Ví dụ,
OrdercócalculateTotal(),addItem(OrderItem),removeItem(OrderItem).
Bước 3: Xác định quan hệ
- Association:
Customer“đặt” (places)Order. - Aggregation:
Order“gồm” (contains) nhiềuOrderItem. - Composition:
ShoppingCart“sở hữu” (owns) cácCartItem(không tồn tại nếu giỏ hàng bị xóa). - Inheritance:
AdminvàCustomerkế thừaUser.
Bước 4: Thêm multiplicity

Có thể bạn quan tâm: Cách Vẽ Chữ Trong Adobe Illustrator: Hướng Dẫn Chi Tiết Từ Cơ Bản Đến Nâng Cao
Customer 1 — 0.. Order(một khách hàng có thể có nhiều đơn, không bắt buộc).Order 1 — 1.. OrderItem(mỗi đơn hàng ít nhất một mặt hàng).
Bước 5: Đánh dấu các interface và realization
IRepository<T>là interface chung cho các repository.ProductRepositoryvàOrderRepositoryrealizeIRepository.
Bước 6: Kiểm tra tính nhất quán
- Không có vòng lặp kế thừa (no circular inheritance).
- Mối quan hệ phù hợp: nếu một đối tượng không thể tồn tại độc lập, dùng composition.
- Tên thuộc tính và phương thức thống nhất (camelCase, PascalCase).
Bước 7: Đánh dấu các thuộc tính đặc biệt
- Static: Thuộc tính hoặc phương thức tĩnh (
{static}). - Abstract: Lớp hoặc phương thức trừu tượng (
<<abstract>>,{abstract}).
Bước 8: Thêm các constraint (nếu cần)
Ví dụ: Order.totalAmount >= 0 có thể viết dưới dạng {totalAmount >= 0} hoặc OCL:
context Order
inv: self.totalAmount >= 0
5. Ví dụ thực tế: Class Diagram cho hệ thống Bán Hàng Trực Tuyến
5.1. Danh sách lớp
| Lớp | Thuộc tính | Phương thức |
|---|---|---|
| User (< |
-userId: String, -username: String, -password: String |
+login(): boolean, +logout(): void |
| Customer | -name: String, -email: String, -address: String |
+placeOrder(o: Order): void, +viewOrderHistory(): List<Order> |
| Admin | -role: String |
+manageProduct(p: Product): void, +viewAllOrders(): List<Order> |
| Product | -productId: String, -name: String, -price: double, -stock: int |
+updateStock(qty: int): void, +isAvailable(): boolean |
| Order | -orderId: String, -orderDate: Date, -status: OrderStatus |
+addItem(item: OrderItem): void, +removeItem(item: OrderItem): void, +calculateTotal(): double |
| OrderItem | -quantity: int, -unitPrice: double |
+getSubtotal(): double |
| Payment | -paymentId: String, -amount: double, -method: PaymentMethod |
+process(): boolean |
| ShoppingCart | -items: List<CartItem> |
+addProduct(p: Product, qty: int): void, +removeProduct(p: Product): void, +checkout(): Order |
| CartItem | -product: Product, -quantity: int |
+getSubtotal(): double |
| IRepository |
– | +findById(id: String): T, +save(entity: T): void, +delete(entity: T): void |
| ProductRepository | – | +findByCategory(cat: String): List<Product> |
| OrderRepository | – | +findByCustomer(custId: String): List<Order> |
| OrderService | – | +createOrder(customer: Customer, items: List<OrderItem>): Order, +cancelOrder(orderId: String): void |
| PaymentService | – | +pay(order: Order, method: PaymentMethod): PaymentResult |
5.2. Quan hệ chính
UsergeneralizationCustomervàAdmin.CustomerassociationOrder(1 — 0..).OrdercompositionOrderItem(1 — 1..).OrderItemassociationProduct(1 — 1).ShoppingCartcompositionCartItem(1 — 0..).CartItemassociationProduct.OrderServicedependencyOrderRepositoryvàProductRepository.PaymentServicedependencyPayment.ProductRepositoryvàOrderRepositoryrealizeIRepository<T>.
5.3. Mô tả diagram (được vẽ bằng PlantUML)

Có thể bạn quan tâm: Cách Vẽ Chữ “t” 3d Đẹp, Ấn Tượng Và Dễ Thực Hiện Cho Người Mới Bắt Đầu
@startuml
' Define abstract class User
abstract class User { -userId: String -username: String -password: String +login(): boolean +logout(): void
} class Customer { -name: String -email: String -address: String +placeOrder(o: Order): void +viewOrderHistory(): List<Order>
} class Admin { -role: String +manageProduct(p: Product): void +viewAllOrders(): List<Order>
} User <|-- Customer
User <|-- Admin class Product { -productId: String -name: String -price: double -stock: int +updateStock(qty: int): void +isAvailable(): boolean
} class Order { -orderId: String -orderDate: Date -status: OrderStatus +addItem(item: OrderItem): void +removeItem(item: OrderItem): void +calculateTotal(): double
} class OrderItem { -quantity: int -unitPrice: double +getSubtotal(): double
} class Payment { -paymentId: String -amount: double -method: PaymentMethod +process(): boolean
} class ShoppingCart { -items: List<CartItem> +addProduct(p: Product, qty: int): void +removeProduct(p: Product): void +checkout(): Order
} class CartItem { -product: Product -quantity: int +getSubtotal(): double
} interface IRepository<T> { +findById(id: String): T +save(entity: T): void +delete(entity: T): void
} class ProductRepository { +findByCategory(cat: String): List<Product>
}
class OrderRepository { +findByCustomer(custId: String): List<Order>
}
class OrderService { +createOrder(customer: Customer, items: List<OrderItem>): Order +cancelOrder(orderId: String): void
}
class PaymentService { +pay(order: Order, method: PaymentMethod): PaymentResult
} Customer "1" --> "0.." Order : places
Order "1" -- "1.." OrderItem : contains
OrderItem --> Product : references
ShoppingCart "1" -- "0.." CartItem : owns
CartItem --> Product : references OrderService ..> OrderRepository : uses
OrderService ..> ProductRepository : uses
PaymentService ..> Payment : uses ProductRepository ..|> IRepository<Product>
OrderRepository ..|> IRepository<Order>
@enduml
Bản vẽ trên thể hiện đầy đủ các lớp, thuộc tính, phương thức, quan hệ kế thừa, composition, aggregation và dependency. Bạn có thể sao chép mã PlantUML vào bất kỳ công cụ nào hỗ trợ (PlantUML Online Server, VS Code extension) để xem hình ảnh thực tế.
6. Kỹ thuật nâng cao trong Class Diagram
6.1. Sử dụng Interface và Abstract Class
- Interface: Thích hợp cho các hành vi chung không có cài đặt, ví dụ
IPrintable,IRepository. Các lớp có thể realize nhiều interface, giúp đạt tính đa kế thừa (multiple inheritance) mà không gặp vấn đề “diamond problem”. - Abstract Class: Dùng khi muốn chia sẻ một số thuộc tính hoặc phương thức đã được cài đặt, đồng thời khai báo một số phương thức trừu tượng.
Lưu ý: Khi một lớp kế thừa một abstract class và một interface, hãy đặt abstract class ở đầu cây kế thừa (vì UML không cho phép multiple inheritance cho class).
6.2. Aggregation vs Composition
| Điểm | Aggregation | Composition |
|---|---|---|
| Sự tồn tại | Phần có thể tồn tại độc lập (ví dụ: Course và Student). |
Phần phụ thuộc toàn bộ (ví dụ: Order và OrderItem). |
| Độ mạnh của quan hệ | Yếu (hollow diamond). | Mạnh (filled diamond). |
| Xóa | Xóa toàn bộ không ảnh hưởng tới phần. | Xóa toàn bộ sẽ xóa phần. |
Khi nào dùng?
– Dùng composition cho các thành phần không có ý nghĩa riêng khi không có “toàn bộ”.
– Dùng aggregation khi phần có thể được chia sẻ giữa nhiều “toàn bộ” hoặc tồn tại độc lập.
6.3. Association Class
Khi một mối quan hệ association có thuộc tính hoặc hành vi riêng, bạn có thể tạo Association Class. Ví dụ, trong mối quan hệ Student—Course, có thể có một lớp Enrollment chứa grade, enrollmentDate.

Có thể bạn quan tâm: Cách Vẽ Chữ S 3d Đẹp Và Ấn Tượng: Hướng Dẫn Từng Bước Cho Người Mới Bắt Đầu
6.4. Multiplicity chi tiết
0..1– Tối đa một, có thể không có.1– Bắt buộc một.hoặc0..– Không giới hạn.1..– Ít nhất một.
Sử dụng multiplicity để thể hiện ràng buộc nghiệp vụ: ví dụ, một Invoice phải có ít nhất một InvoiceLine.
6.5. Constraint (Ràng buộc)
Bạn có thể dùng OCL để mô tả các ràng buộc phức tạp mà không thể biểu diễn bằng multiplicity. Ví dụ:
context Order
inv: self.orderItems->forAll(oi | oi.quantity > 0)
6.6. Packages (Gói)
Khi diagram trở nên quá lớn, hãy phân chia thành các package (gói) để tổ chức các lớp theo module hoặc layer (ví dụ: domain, service, repository). Mối quan hệ giữa các package thường dùng dependency hoặc import.
7. Thực hành: Các bước vẽ Class Diagram trong công cụ thực tế
7.1. Vẽ bằng draw.io
- Tạo file mới → Chọn “UML” → Kéo “Class” vào canvas.
- Nhập tên lớp, thuộc tính, phương thức.
- Dùng công cụ “Connector” để vẽ các quan hệ, chọn kiểu (solid, dashed, diamond).
- Đặt multiplicity bằng cách double-click vào đầu connector.
- Sắp xếp layout, sử dụng “Align” để căn chỉnh.
7.2. Vẽ bằng StarUML

- File → New Project → UML Diagram → Class Diagram.
- Kéo “Class” từ toolbox.
- Nhấn
F2để chỉnh sửa tên, thuộc tính, phương thức. - Dùng “Association”, “Aggregation”, “Composition” từ toolbox, kéo thả để kết nối.
- Đặt multiplicity trong “Properties” panel.
- Export → PNG, PDF hoặc XMI để chia sẻ.
7.3. Vẽ bằng PlantUML (textual)
- Viết file
.pumlvới cú pháp như trong ví dụ ở mục 5.3. - Chạy lệnh
plantuml diagram.pumlhoặc dùng plugin trong IDE. - Ưu điểm: version control (Git) dễ dàng, tự động cập nhật khi thay đổi.
7.4. Kiểm tra tính đúng đắn
- Kiểm tra vòng lặp kế thừa: Không để
Akế thừaBvàBlại kế thừaA. - Kiểm tra tính đồng nhất: Tên lớp, thuộc tính, phương thức phải thống nhất trong toàn dự án.
- Kiểm tra quan hệ: Mỗi quan hệ có mục đích rõ ràng, không thừa thãi.
8. Lưu ý thường gặp và cách khắc phục
| Vấn đề | Nguyên nhân | Giải pháp |
|---|---|---|
| Quá nhiều lớp trong một diagram | Thiết kế chưa phân tầng, không dùng package | Tách ra thành multiple diagrams hoặc package diagram. |
| Không phân biệt aggregation và composition | Nhầm lẫn về mức độ sở hữu | Xác định xem phần có thể tồn tại độc lập hay không, dùng diamond tương ứng. |
| Thiếu multiplicity | Quên ghi ràng buộc hoặc không hiểu yêu cầu | Đọc lại yêu cầu nghiệp vụ, cố gắng biểu diễn số lượng tối thiểu và tối đa. |
| Rối mắt vì quá nhiều connector | Đánh dấu quan hệ không cần thiết | Loại bỏ các dependency không quan trọng, hoặc dùng narrower scope (chỉ vẽ quan hệ chính). |
| Không đồng nhất naming convention | Tham khảo chuẩn coding style của dự án | Áp dụng quy tắc: lớp PascalCase, thuộc tính camelCase, phương thức camelCase, interface bắt đầu bằng I. |
9. Ứng dụng Class Diagram trong quy trình phát triển phần mềm
- Giai đoạn Phân tích (Analysis)
- Dùng Class Diagram để xác định domain model.
-
Kết hợp với Use Case Diagram để liên kết các hành vi với đối tượng.
-
Giai đoạn Thiết kế (Design)
- Từ Class Diagram tạo ra các component diagram hoặc deployment diagram.
-
Xác định layer architecture (Presentation, Business, Data).
-
Giai đoạn Lập trình (Implementation)
- Các lớp trong diagram trở thành code skeleton (cấu trúc lớp).
-
Các interface và abstract class giúp định nghĩa API và đảm bảo tính mở rộng.
-
Giai đoạn Kiểm thử (Testing)
- Dựa trên Class Diagram xây dựng unit tests cho từng lớp, đặc biệt là các phương thức công cộng.
-
Kiểm tra độ bao phủ của các quan hệ (ví dụ: test composition bằng mock objects).
-
Bảo trì (Maintenance)
- Khi thay đổi yêu cầu, cập nhật Class Diagram trước khi sửa code, giúp tránh lỗi phá vỡ kiến trúc.
10. Tổng kết
Việc vẽ Class Diagram UML không chỉ là một công việc “đồ họa” mà còn là quá trình phân tích, suy nghĩ có hệ thống về cấu trúc và mối quan hệ trong phần mềm. Bằng cách tuân thủ các quy tắc ký hiệu, lựa chọn đúng loại quan hệ, và áp dụng các kỹ thuật nâng cao như interface, aggregation/composition, bạn sẽ có được một mô hình mạnh mẽ, dễ hiểu và có thể mở rộng.
Các bước quan trọng để thành công:
- Hiểu rõ yêu cầu và xác định các thực thể, dịch vụ.
- Định nghĩa lớp, thuộc tính, phương thức một cách chi tiết.
- Chọn quan hệ phù hợp (association, aggregation, composition, inheritance).
- Thêm multiplicity và constraint để phản ánh đúng ràng buộc nghiệp vụ.
- Sử dụng công cụ thích hợp (draw.io, StarUML, PlantUML…) và duy trì đồng nhất trong naming và style.
Khi đã nắm vững quy trình này, bạn sẽ có thể tạo ra các Class Diagram chuẩn, hỗ trợ hiệu quả cho toàn bộ vòng đời phát triển phần mềm – từ phân tích, thiết kế, lập trình, kiểm thử cho đến bảo trì. Hy vọng bài viết đã cung cấp cho bạn một hướng dẫn chi tiết, đầy đủ để thực hiện công việc này một cách chuyên nghiệp và hiệu quả. Chúc bạn thành công trong việc mô hình hoá và xây dựng các hệ thống phần mềm chất lượng!
