1. 4 Cấu trúc khóa luận
2.9.2. Xây dựng máy hữu hạn trạng thái từ các thành phần của biểu đồ
Gọi tập hợp các trạng thái (State) là S = {s0, s1, s2, … sn}
Tập hợp các thông điệp (không tính thông điệp trả lời) là M = {m0, m1, m2, m3… mn} Đầu tiên ta tạo ra trạng thái s0, đặt nó là trạng thái khởi đầu.
Với mỗi thông điệp thứ mi, ta tạo ra State si + 1 và tạo ra Transition (si, mi, si+1) nối từ State thứ i tới State thứ i + 1 có Event tương ứng với thông điệp thứ i.
Lưu tên các State si và si + 1 vào trong thông điệp mi như là trạng thái nguồn và đích của thông điệp thứ i để sau này làm việc với các đoạn gộp nếu có.
Đặt trạng thái cuối cùng tạo ra là trạng thái kết thúc.
Nếu không có các đoạn gộp thì coi như công việc đã hoàn thành.
Lưu lý là trạng thái đích của thông điệp mi sẽ là trạng thái nguồn của của thông điệp mi+1.
Nếu có đoạn gộp Loop, trong Loop có thể có một hoặc nhiều thông điệp và khối Loop này có thể được thực thi chỉ một lần hoặc có thể lặp lại nhiều lần hoặc không thực hiện lần nào.
Không mất tính tổng quát, ta đặt thông điệp đầu tiên và cuối cùng trong Loop theo thứ tự là mi và mn . Ở bước trên ta đã lưu lại trạng thái nguồn và đích của mỗi thông điệp ví dụ như thông điệp mi sẽ có nguồn là si và đích là si + 1 còn mn có nguồn là sn và đích là sn + 1 Để cho dễ hình dung ta sẽ ký hiệu một thông điệp giống như một transition (snguồn, m,
27
sđích) . Như thế, thông điệp đầu tiên ngay sau Loop là thông điệp mn+1 sẽ ký hiệu là (sn + 1, mn + 1, sn + 2)
Đầu tiên ta xét khối Loop này được thực hiện ít nhất một lần. Vậy sau khi thông điệp cuối cùng mn trong loop thực thi xong thì chương trình đang ở trạng thái sn + 1 và có hai khả năng một là chạy tiếp thông điệp ngay sau loop hai là quay trở lại trạng thái trước khi thông điệp đầu tiên mi thực hiện. Trường hợp thứ nhất thì không có vấn đề gì, ta chỉ quan tâm tới trường hợp còn lại khi mà thông điệp đầu tiên trong Loop (mi) được gọi lại lần nữa. Vậy ta phải thêm vào máy trạng thái một Transition có nguồn là trạng thái hiện tại (sn + 1), Event tương ứng với mi và đích là đích của mi. Tức là ta phải bổ sung thêm Transition (sn + 1, mi, si + 1).
Tiếp theo ta xét khối loop này không được thực hiện một lần nào mà thực hiện ngay thông điệp đầu tiên sau Loop. Lúc này, chương trình đang ở trạng thái si và tiếp theo thông điệp mn + 1 sẽ được gọi. Do vậy ta phải thêm vào một Transition có nguồn là si, Event tương ứng với mn + 1 và đích là trạng thái đích của mn + 1. Tức là ta phải bổ sung thêm Transition (si, mn + 1, sn + 2).
Để dễ hình dung, ta lấy một ví dụ về việc một người truy vấn số dư tài khoản ở ngân hàng như sơ đồ sau:
Ở sơ đồ này, một User có thể tạo nhiều tài khoản và khi truy vấn số dư thì sẽ phải truy vấn ở tất cả các tài khoản của anh ta.
Với các bước như trên, ta sẽ thu được một state machine như hình vẽ sau:
Hình 11. Máy hữu hạn trạng thái ứng với ví dụ truy vấn tài khoản ngân hàng.
Nếu biểu đồ có đoạn gộp Option, ta dễ thấy đây là trường hợp đặc biệt của Loop khi mà các thông điệp bên trong chỉ được thực hiện một lần hoặc không lần nào. Do vậy với các giả thiết như trên ta thấy cần thiết phải thêm vào Transition (si, mn + 1, sn + 2).
Đối với đoạn gộp Break, các thông điệp trong đoạn gộp này hoặc là không được thực thi lần nào nếu được gọi thì sau khi thực thi xong các thông điệp trong đoạn gộp này, chương trình sẽ kết thúc ngay. Như thế, ta có thể hình dung đây là một trường hợp đặc biệt của đoạn gộp Option chỉ khác là nếu được sử dụng thì toàn bộ các thông điệp đứng sau nó sẽ bị bỏ qua. Trong trường hợp này, sau khi thực thi thông điệp cuối cùng trong đoạn gộp, chương trình đang ở trạng thái sn + 1. Tới đây, chương trình chấm dứt nên ta phải bỏ đi tất cả các Transition có nguồn là trạng thái này đồng thời đặt sn + 1 cũng là một trạng thái kết thúc. Trong trường hợp còn lại thì vẫn những giả thiết giống như với Option ta vẫn phải thêm vào Transition (si, mn + 1, sn + 2).
Nếu có đoạn gộp Alternative, chúng ta giới hạn chỉ có hai Interaction Operand trong đoạn gộp này là một if then Operand và một else Operand. Bắt buộc một trong hai Operand này phải được thực thi và chỉ một trong hai mà thôi. Do đó ta phải bỏ đi một Transition xây dựng ở bước đầu tiên nối giữa trạng thái cuối và đầu của hai Operand này đi. Ngoài ra do tất cả các Operand trong đoạn gộp này có vai trò ngang hàng nhau nên trạng thái nguồn và đích của mỗi Operand cũng là giống nhau. Việc còn lại là ta phải xác định và thêm các Transition tương ứng với chúng.
29
Tuy nhiên sẽ có vấn đề nảy sinh nếu như các đoạn gộp này nằm ở cuối cùng của biểu đồ tuần tự. Với các đoạn gộp có một Interaction Operand như Loop, Opt, Break thì các thông điệp có thể không được gọi lần nào. Hoặc với Alternative thì chỉ có một trong các Interaction Operand được thực hiện. Như thế ta phải thêm các trạng thái kết thúc cho phù hợp với từng trường hợp đó. Cuối cùng, có một vấn đề là trong các bước trên có thể sẽ sinh ra một trạng thái mà có hai Transition với các Event có cùng tên thông điệp. Như vậy sẽ làm cho máy trạng thái của chúng ta trở thành một máy trạng thái không đơn định (Non-deterministic finite state machine). Do đó sau khi đã tạo ra máy trạng thái như trên, ta phải kiểm tra xem nó có đơn định hay không nếu không thì ta sẽ phải biến đổi nó trở thành đơn định.
CHƯƠNG 3
Aspect và lập trình hướng khía cạnh