TÓM TẮ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

  1. Đọ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ý.
  2. 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.
  3. 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ách Vẽ Class Diagram Uml
Cách Vẽ Class Diagram Uml

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:

  1. Tên lớp (Class Name) – viết in đậm, thường đặt ở phần trên cùng.
  2. 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}
  3. visibility: + (public), - (private), # (protected), ~ (package).
  4. multiplicity: 1, 0.., 1..…
  5. property: static, abstract, derived.

  6. 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

  1. Lập danh sách thực thể từ yêu cầu.
  2. Nhóm các thuộc tính chung vào lớp cha (nếu có).
  3. 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ụ, Customer có 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ụ, Order có calculateTotal(), addItem(OrderItem), removeItem(OrderItem).

Bước 3: Xác định quan hệ

  • Association: Customer “đặt” (places) Order.
  • Aggregation: Order “gồm” (contains) nhiều OrderItem.
  • Composition: ShoppingCart “sở hữu” (owns) các CartItem (không tồn tại nếu giỏ hàng bị xóa).
  • Inheritance: Admin và Customer kế thừa User.

Bước 4: Thêm multiplicity

Cách Vẽ Class Diagram Uml
Cách Vẽ Class Diagram Uml
  • 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.
  • ProductRepository và OrderRepository realize IRepository.

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

  • User generalization Customer và Admin.
  • Customer association Order (1 — 0..).
  • Order composition OrderItem (1 — 1..).
  • OrderItem association Product (1 — 1).
  • ShoppingCart composition CartItem (1 — 0..).
  • CartItem association Product.
  • OrderService dependency OrderRepository và ProductRepository.
  • PaymentService dependency Payment.
  • ProductRepository và OrderRepository realize IRepository<T>.

5.3. Mô tả diagram (được vẽ bằng PlantUML)

Cách Vẽ Class Diagram Uml
Cách Vẽ Class Diagram Uml
@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ách Vẽ Class Diagram Uml
Cách Vẽ Class Diagram Uml

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ặc 0.. – 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

  1. Tạo file mới → Chọn “UML” → Kéo “Class” vào canvas.
  2. Nhập tên lớp, thuộc tính, phương thức.
  3. Dùng công cụ “Connector” để vẽ các quan hệ, chọn kiểu (solid, dashed, diamond).
  4. Đặt multiplicity bằng cách double-click vào đầu connector.
  5. Sắp xếp layout, sử dụng “Align” để căn chỉnh.

7.2. Vẽ bằng StarUML

Cách Vẽ Class Diagram Uml
Cách Vẽ Class Diagram Uml
  1. File → New Project → UML Diagram → Class Diagram.
  2. Kéo “Class” từ toolbox.
  3. Nhấn F2 để chỉnh sửa tên, thuộc tính, phương thức.
  4. Dùng “Association”, “Aggregation”, “Composition” từ toolbox, kéo thả để kết nối.
  5. Đặt multiplicity trong “Properties” panel.
  6. Export → PNG, PDF hoặc XMI để chia sẻ.

7.3. Vẽ bằng PlantUML (textual)

  • Viết file .puml với cú pháp như trong ví dụ ở mục 5.3.
  • Chạy lệnh plantuml diagram.puml hoặ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 để A kế thừa B và B lại kế thừa A.
  • 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

  1. Giai đoạn Phân tích (Analysis)
  2. Dùng Class Diagram để xác định domain model.
  3. Kết hợp với Use Case Diagram để liên kết các hành vi với đối tượng.

  4. Giai đoạn Thiết kế (Design)

  5. Từ Class Diagram tạo ra các component diagram hoặc deployment diagram.
  6. Xác định layer architecture (Presentation, Business, Data).

  7. Giai đoạn Lập trình (Implementation)

  8. Các lớp trong diagram trở thành code skeleton (cấu trúc lớp).
  9. Các interface và abstract class giúp định nghĩa API và đảm bảo tính mở rộng.

  10. Giai đoạn Kiểm thử (Testing)

  11. 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.
  12. Kiểm tra độ bao phủ của các quan hệ (ví dụ: test composition bằng mock objects).

  13. Bảo trì (Maintenance)

  14. 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:

  1. Hiểu rõ yêu cầu và xác định các thực thể, dịch vụ.
  2. Định nghĩa lớp, thuộc tính, phương thức một cách chi tiết.
  3. Chọn quan hệ phù hợp (association, aggregation, composition, inheritance).
  4. Thêm multiplicity và constraint để phản ánh đúng ràng buộc nghiệp vụ.
  5. 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!

Rate this post
Mục nhập này đã được đăng trong Blog. Đánh dấu trang permalink.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *