Hướng dẫn toàn diện: Mô hình hóa một Hệ thống điều khiển cuộc gọi điện thoại bằng Sơ đồ Máy trạng thái UML

🎯 Tổng quan

Hướng dẫn này dẫn dắt bạn qua quá trình thiết kế và mô hình hóa mộtHệ thống điều khiển cuộc gọi điện thoạibằng cách sử dụngSơ đồ Máy trạng thái UML. Nó tập trung vàochu kỳ sống cuộc gọi đi, minh họa cách một đường dây điện thoại chuyển đổi giữa các trạng thái phản ứng với hành động của người dùng và các sự kiện mạng.

Sơ đồ này ghi lại cả haiđường đi thuận lợi (thiết lập cuộc gọi thành công) vàđường đi không thuận lợi (lỗi, hết thời gian chờ, đường dây bận), nhấn mạnh tính bền vững, xử lý ngoại lệ và các chuyển trạng thái rõ ràng – những nguyên tắc cốt lõi trong các hệ thống truyền thông thời gian thực.


🧩 Các khái niệm cốt lõi trong Máy trạng thái UML

Trước khi đi sâu vào sơ đồ, hãy hiểu rõ các khái niệm UML nền tảng sau:

Khái niệm Mô tả
Trạng thái Một trạng thái trong đó một đối tượng thoả mãn các điều kiện nhất định hoặc thực hiện các hành động.
Chuyển tiếp Một sự thay đổi từ trạng thái này sang trạng thái khác, được kích hoạt bởi một sự kiện.
Sự kiện Một sự kiện gây ra chuyển tiếp (ví dụ nhưonHookvalidNumber).
Chuyển tiếp tự thân Một chuyển tiếp bắt đầu và kết thúc ở cùng một trạng thái (ví dụ nhưchữ số(n)trong khi ở trongGọi).
Trạng thái giả Các điểm điều khiển đặc biệt nhưBan đầuhoặcCuối cùngmà không phải là các trạng thái thực sự.
Trạng thái hợp thành Một trạng thái chứa các trạng thái con (ví dụ nhưLỗitrạng thái vớiTone bậnTone bận nhanhTin nhắn ghi âm).
Điều kiện bảo vệ Một biểu thức logic phải đúng để chuyển tiếp xảy ra.

✅ Mẹo hay:Sử dụngsự kiện [điều kiện bảo vệ] / hành độngcú pháp trong UML để ghi chú các sự kiện kích hoạt, điều kiện và hệ quả phụ.


🔄 Chu kỳ sống cuộc gọi ra: Phân tích từng bước

1. Giai đoạn khởi tạo và gọi

🔹 Trạng thái giả ban đầu → Đang chờ

  • Hệ thống khởi động ở trạng thái Trạng thái giả ban đầu.
  • Chưa có hoạt động nào; điện thoại đang để trên giá đỡ.

🔹 Đang chờ → Tín hiệu chuông (đã nhấc máy)

  • Sự kiện: đã nhấc máy (người dùng nhấc máy lên)
  • Chuyển tiếp: đã nhấc máy → tín hiệu chuông
  • Hành động: Tạo tín hiệu chuông; chuẩn bị cho đầu vào chữ số.

📌 Đây là thay đổi trạng thái đầu tiên có thể quan sát được trong chu kỳ cuộc gọi.

🔹 Tín hiệu chuông → Đang gọi (chữ số(n))

  • Sự kiện: chữ số(n) (người dùng nhập một chữ số)
  • Chuyển tiếp: chữ số(n) → Đang gọi
  • Trạng thái: Chuyển sang Đang gọi chế độ.

🔹 Chuyển tiếp tự thân: Đang gọi → Đang gọi (chữ số(n))

  • Sự kiện: chữ số(n) (nhiều chữ số được nhập)
  • Điều kiện: Không (luôn được phép)
  • Hành động: Thêm chữ số vào số đang được gọi.
  • Mục đích: Cho phép nhập liên tục các chữ số mà không cần rời khỏi trạng tháiĐang gọi trạng thái.

💡 Các chuyển tiếp tự thân là thiết yếu để xử lý các chuỗi đầu vào như số điện thoại.


2. Logic kết nối và xử lý ngoại lệ

🔹 Đang gọi → Đang kết nối (số hợp lệ)

  • Sự kiện: số hợp lệ (số hoàn chỉnh đã được xác minh)
  • Chuyển tiếp: số hợp lệ → Đang kết nối
  • Hành động: Khởi tạo thiết lập cuộc gọi với mạng lưới.

🔹 Đang gọi → Tin nhắn đã ghi (số không hợp lệ)

  • Sự kiện: số không hợp lệ (ví dụ: độ dài sai, tiền tố không hợp lệ)
  • Chuyển tiếp: số không hợp lệ → Tin nhắn đã ghi
  • Hành động: Phát tin nhắn đã ghi trước: “Số bạn vừa gọi hiện không hoạt động.”

🔹 Đang kết nối → Tín hiệu bận (số bận)

  • Sự kiện: số bận
  • Chuyển tiếp: số bận → Tiếng bíp bận
  • Hành động: Phát tiếng bíp bận; thông báo cho người dùng đường dây đang bận.

🔹 Đang kết nối → Tiếng bíp bận nhanh (trunkBusy)

  • Sự kiện: trunkBusy
  • Chuyển tiếp: trunkBusy → Tiếng bíp bận nhanh
  • Hành động: Phát tiếng bíp bận nhanh; cho biết mạng đang quá tải.

⚠️ Ghi chú: Đây là trạng thái lỗi là những trạng thái làm gián đoạn luồng hoạt động bình thường. Chúng cần được xử lý một cách trơn tru.


3. Cơ chế hết thời gian & cảnh báo

🔹 Đang quay số → Cảnh báo (hết thời gian)

  • Sự kiện: hết thời gian sau 30 giây không hoạt động
  • Chuyển tiếp: hết thời gian → Cảnh báo
  • Hành động: Phát tiếng bíp cảnh báo; thông báo cho người dùng tiếp tục hoặc treo máy.

🔹 Cảnh báo → Hết thời gian (hết thời gian)

  • Sự kiện: hết thời gian lại sau 10 giây
  • Chuyển tiếp: timeout → Timeout
  • Hành động: Hủy bỏ thử gọi; quay lại Ngưng hoạt động.

⏱️ Logic thời gian chờ giúp ngăn chặn việc chờ đợi vô hạn và cải thiện trải nghiệm người dùng.


4. Cuộc gọi đang hoạt động và ngắt kết nối

🔹 Đang kết nối → Bắt máy (được định tuyến)

  • Sự kiện: được định tuyến (mạng đã định tuyến cuộc gọi thành công)
  • Chuyển tiếp: được định tuyến → Bắt máy
  • Hành động: Gửi tín hiệu bắt máy đến bên được gọi.

🔹 Bắt máy → Kết nối (điện thoại được gọi trả lời)

  • Sự kiện: điện thoại được gọi trả lời
  • Chuyển tiếp: điện thoại được gọi trả lời → Kết nối
  • Hành động: Thiết lập kết nối âm thanh; bắt đầu ghi âm cuộc gọi (nếu được bật).

🔹 Đã kết nối → Ngắt kết nối (treo máy HOẶC điện thoại được gọi ngắt kết nối)

  • Hai con đường để ngắt kết nối:
    1. Người dùng treo máy: treo máy → Ngắt kết nối
    2. Đối phương ngắt cuộc gọi: calledPhoneHangsUp → Ngắt kết nối

🔄 Cả hai chuyển tiếp đều dẫn đến Ngắt kết nối trước khi đạt đến Trạng thái cuối.

🔹 Ngắt kết nối → Trạng thái cuối

  • Sự kiện: Không (ngầm định hoặc thông qua hành động dọn dẹp)
  • Chuyển tiếp: Ngắt kết nối → Cuối
  • Hành động: Dọn dẹp tài nguyên, ghi lại thời lượng cuộc gọi, cập nhật thống kê.

✅ Trạng thái cuối biểu thị kết thúc chu kỳ cuộc gọi.


🎨 Nguyên tắc thiết kế trực quan để rõ ràng

Để làm cho các máy trạng thái phức tạp dễ đọc và dễ bảo trì:

Nguyên tắc Thực hiện
Đường đi chính (Happy Path) trung tâm Giữ luồng chính (Ngưng → Tín hiệu gọi → Đang gọi → Đang kết nối → Đang reo → Đã kết nối) như một đường thẳng dọc hoặc ngang rõ ràng.
Tách nhánh ra ngoài cho các ngoại lệ Đặt các trạng thái lỗi (BusyTone, FastBusyTone, Tin nhắn ghi âm) như các nhánh phụ.
Nhóm các trạng thái liên quan Sử dụng trạng thái hợp thành cho các điều kiện lỗi (xem bên dưới).
Sử dụng trạng thái giả một cách khôn khéo Ban đầu và Cuối cùng phải được đánh dấu rõ ràng.
Tránh các chuyển tiếp chéo nhau Giữ cho các mũi tên không chồng chéo lên nhau; sử dụng các vùng vuông góc nếu cần thiết.

🔧 Các kỹ thuật mô hình hóa nâng cao

✅ Trạng thái tổng hợp: Nhóm “Lỗi”

Thay vì liệt kê BusyToneFastBusyTone, và RecordedMessage như các trạng thái riêng biệt, hãy nhóm chúng dưới một trạng thái tổng hợp gọi là Lỗi:

[Lỗi] 
├── BusyTone
├── FastBusyTone
└── RecordedMessage
  • Hành động vào: Phát âm thanh lỗi hoặc tin nhắn.
  • Hành động thoát: Trở về DialTone hoặc Idle sau phản hồi của người dùng.

✅ Lợi ích:Giảm sự lộn xộn về mặt thị giác và cải thiện khả năng mở rộng.


✅ Điều kiện bảo vệ (Cải tiến tùy chọn)

Thêm điều kiện bảo vệ để tinh chỉnh các chuyển tiếp:

digit(n) [number.length < 15] → Đang gọi
validNumber [number.isInternational] → Đang kết nối

🛠️ Điều kiện bảo vệ ngăn chặn các chuyển tiếp không hợp lệ và hỗ trợ logic điều kiện.


📌 Những điểm chính cần lưu ý: Các thực hành tốt nhất cho máy trạng thái phức tạp

Thực hành Tại sao điều đó quan trọng
Mô hình hóa các đường đi không mong muốn Các hệ thống thực tế thường thất bại. Thiết kế cho số không hợp lệhết thời giankênh bận đảm bảo độ tin cậy.
Sử dụng biểu thức hành động Bao gồm / logLanGoi() hoặc / playTone() để thể hiện các hiệu ứng phụ.
Giữ các sự kiện rõ ràng và hướng đến hành động Sử dụng treo máyđược định tuyếnđiện thoại được gọi đã trả lờithay vìe1e2.
Đặt tên trạng thái một cách rõ ràng TránhTrạng thái1Trạng thái2. Sử dụngĐang gọiĐang reo chuôngĐã kết nối.
Tài liệu các giả định Ví dụ: “Hết thời gian sau 30 giây không hoạt động” cần được ghi chú trong phần chú thích.

💻 Tạo mã: PlantUML & Mermaid

Dưới đây làcác khối mã sẵn sàng sử dụngđể tạo sơ đồ này theo định dạng bạn mong muốn.


✅ Mã PlantUML

@startuml

[*] --> Idle
Idle --> DialTone : onHook
DialTone --> Dialing : digit(n)
Dialing --> Dialing : digit(n) ' Chuyển tiếp tự thân
Dialing --> Connecting : validNumber
Dialing --> RecordedMessage : invalidNumber
Dialing --> Warning : timeout
Warning --> Timeout : timeout
Connecting --> Ringing : routed
Connecting --> BusyTone : numberBusy
Connecting --> FastBusyTone : trunkBusy
Ringing --> Connected : calledPhoneAnswers
Connected --> Disconnected : onHook
Connected --> Disconnected : calledPhoneHangsUp
Disconnected --> [*] : cleanup

state "Lỗi" as ErrorState {
state "BusyTone" as BusyTone
state "FastBusyTone" as FastBusyTone
state "Thông điệp ghi âm" as RecordedMessage
}

' Hành động nội bộ
Idle : entry / Chờ ngắt kết nối
DialTone : entry / Phát âm thanh gọi
Dialing : entry / Thu thập các chữ số
Connecting : entry / Chuyển cuộc gọi
Ringing : entry / Gọi điện thoại từ xa
Connected : entry / Thiết lập phiên gọi
Disconnected : entry / Kết thúc phiên

@enduml

📥 Cách sử dụng: Dán vào PlantUML Trực tuyến hoặc tiện ích cho IDE của bạn.


✅ Mã Mermaid

stateDiagram-v2
    [*] --> Idle
    Idle --> DialTone : onHook

    DialTone --> Dialing : digit(n)
    Dialing --> Dialing : digit(n)  ' Chuyển tiếp tự thân
    Dialing --> Connecting : validNumber
    Dialing --> RecordedMessage : invalidNumber
    Dialing --> Warning : timeout

    Warning --> Timeout : timeout

    Connecting --> Ringing : routed
    Connecting --> BusyTone : numberBusy
    Connecting --> FastBusyTone : trunkBusy

    Ringing --> Connected : calledPhoneAnswers
    Connected --> Disconnected : onHook
    Connected --> Disconnected : calledPhoneHangsUp

    Disconnected --> [*] : cleanup

    state Error {
        BusyTone
        FastBusyTone
        RecordedMessage
    }

    Connecting --> BusyTone : numberBusy
    Connecting --> FastBusyTone : trunkBusy
    Dialing --> RecordedMessage : invalidNumber

    note right of BusyTone
        Phát âm thanh bận tiêu chuẩn
    end note

    note right of FastBusyTone
        Phát âm thanh bận nhanh (mạng quá tải)
    end note

    note right of RecordedMessage
        Phát thông điệp ghi âm: "Số điện thoại không hoạt động."
    end note

    note right of Timeout
        Thử gọi bị hủy sau 40 giây
    end note

📥 Cách sử dụng: Dán vào Trình chỉnh sửa Mermaid Trực tuyến hoặc các công cụ Markdown được hỗ trợ (VS Code, Obsidian, v.v.).


📚 Tóm tắt và suy nghĩ cuối cùng

Đây là Hệ thống điều khiển cuộc gọi điện thoại máy trạng thái là một ví dụ thực tế về cách UML có thể mô hình hóa các hệ thống phức tạp, dựa trên sự kiện với độ tin cậy cao.

✅ Điều gì làm cho sơ đồ này hiệu quả:

  • Rõ ràng đường đi chính với luồng logic rõ ràng.
  • Xử lý lỗi toàn diện xử lý lỗi.
  • Sử dụng chuyển tiếp tự thântrạng thái hợp thành, và các điều kiện.
  • Sự rõ ràng trực quan nhờ sự nhóm lại và ghi chú.

🛠️ Khi nào nên sử dụng mẫu này:

  • Hệ thống điện thoại
  • Điều khiển thiết bị IoT
  • Quản lý phiên người dùng
  • Động cơ quy trình làm việc
  • Hệ thống nhúng với logic trạng thái hữu hạn

📝 Muốn mở rộng thêm?

Xem xét thêm:

  • Ghi âm cuộc gọi trạng thái (với bắt đầuGhi âmdừngGhi âm sự kiện)
  • Chuyển cuộc gọi logic (điều hướng có điều kiện)
  • Chờ cuộc gọi hỗ trợ (trạng thái song song)
  • Chuyển cuộc gọi là trạng thái con của Đã kết nối
  • Lịch sử trạng thái (lịch sử nông/lịch sử sâu) để tái nhập sau khi bị gián đoạn

📌 Đề xuất cuối cùng

Luôn mô hình hóa cả hai hành trình thành công và thất bại.
Một máy trạng thái chỉ xử lý các “đường đi thuận lợi” là chưa hoàn chỉnh và dễ gặp lỗi trong môi trường sản xuất.

Sử dụng hướng dẫn này như một mẫu để mô hình hóa bất kỳ hệ thống thời gian thực nào mà chuyển đổi trạng tháisự kiện, và khả năng chịu lỗi là điều quan trọng.


✅ Sẵn sàng tạo, trực quan hóa hoặc mở rộng?
👉 Sao chép mã PlantUML hoặc Mermaid bên trên và tích hợp nó vào tài liệu, sơ đồ kiến trúc hoặc tài liệu thiết kế hệ thống của bạn.

Hãy cho tôi biết nếu bạn muốn một phiên bản PDFsơ đồ tương tác, hoặc tích hợp vào mô hình hệ thống lớn hơn (ví dụ: với các thành phần hoặc sơ đồ tuần tự)!


📘 “Những hệ thống tốt nhất không chỉ đúng mà còn dự đoán trước thất bại.”
— Thiết kế với máy trạng thái UML