Thành phần (Composition)

Một phần của tài liệu Nghiên cứu ứng dụng “NModel” trong việc phát triển hệ thống nhúng thời gian thực (Trang 37)

Khái niệm thành phần [4]: “Thành phần là việc kết hợp các chƣơng trình mô hình riêng biệt vào một MP mới đƣợc gọi là sản phẩm (product). Sản phẩm đƣợc hình thành bằng cách soạn các MP M1 và M2 đƣợc viết M1xM2 hoặc M1*M2.”

Thành phần đƣợc thực hiện tự động bởi các công cụ phân tích và kiểm thử khi nhiều MP đƣợc đặt tên trên dòng lệnh. Sau đó, các công cụ có thể phân tích hoặc kiểm thử từ sản phẩm. Thành phần đƣợc sử dụng cho bản điều khiển kịch bản. Sau đây, là phần giải thích cách mà thành phần đƣợc thực hiện và mô tả một số kiểu bổ sung cho việc viết mã các MP làm cho nó dễ dàng để viết các kịch bản cho thành phần.

Thành phần có thể hiểu đƣợc (Understanding composition)

Thành phần kết hợp các MP riêng biệt có không gian tên riêng biệt và có thể đƣợc biên dịch vào các hội đồng riêng biệt. Bất kỳ số lƣợng MP nào đều đƣợc chấp nhận bởi tất cả các công cụ.

Sản phẩm của hai hoặc nhiều MP có tất cả các biến trạng thái và tất cả hành động của mỗi chƣơng trình đƣợc biên soạn. Ý tƣởng chính trong thành phần là: các hành động đƣợc chia sẻ có cùng tên trong hai hoặc nhiều chƣơng trình đƣợc biên soạn là một hành động trong sản phẩm. Chúng thực hiện cùng nhau, và có thể chỉ thực hiện khi tất cả các hành động đồng thời đƣợc kích hoạt trong mỗi chƣơng trình của chúng.

Yêu cầu trong thành phần là các hành động đƣợc chia sẻ phải đƣợc kích hoạt đồng thời trong mọi chƣơng trình đƣợc biên soạn, chúng xảy ra thƣờng xuyên có tác dụng giới hạn hành vi và loại bỏ một vài đƣờng chạy. Đó là lý do tại sao thành phần là hữu ích cho điều khiển kịch bản.

Tuy nhiên, có một ngoại lệ quan trọng là: Các hành động không đƣợc chia sẻ có thể xen kẽ vào thứ tự bất kỳ trong sản phẩm, và có thể thực hiện bất cứ khi nào chúng đƣợc kích hoạt trong các chƣơng trình riêng của chúng. Nếu muốn ngăn chặn việc xen kẽ này thì phải thêm những hành động đó tới các MP khác và vô hiệu hóa các hành động đó ở mọi trạng thái trong các MP khác.

Xét một ví dụ nhỏ sau: M1 và M2 là các MP, M1 có các hành động A() và B(2) tạo nên các chuyển tiếp từ trạng thái khởi tạo 0 đến trạng thái 1 và đến trạng thái chấp nhận 2 (hình 3.4). M2 có các hành động B() và C() tạo nên các chuyển tiếp từ trạng

thái 0 đến 1 và lặp lại, ở đây trạng thái 0 vừa là trạng thái khởi tạo vừa là trạng thái chấp nhận (hình 3.5). Sản phẩn của chúng là M1xM2 xuất hiện trong hình 3.6. Tất cả 3 hành động xuất hiện trong sản phẩm.

Hình 3.4: Chƣơng trình mô hình M1

Tiếp theo, là phần giải thích cách tạo thành FSM của sản phẩm M1xM2 (kết hợp từ M1 và M2) đã thu đƣợc trong hình 3.6 nhƣ sau:

Có một phƣơng thức có tính hệ thống để tạo sản phẩm của hai MP. Đầu tiên, xác định từ vựng hành động (action vocabulary) cho mỗi chƣơng trình và những hành động không đƣợc chia sẻ từ chƣơng trình khác. Trong ví dụ này, đối với M1 có từ vựng hành động là A, B và một hành động không đƣợc chia sẻ là C. Đối với M2 có từ vựng hành động là B, C và một hành động không đƣợc chia sẻ là A. Sau đó, bƣớc tiếp theo là hình thành mở rộng vòng lặp (loop extension) cho mỗi chƣơng trình bằng cách: Tại mỗi trạng thái, thêm vào một chuyển tiếp vòng lặp với chính nó cho mỗi hành động không đƣợc chia sẻ. Trong các mở rộng vòng lặp, các hành động có cùng ký tự hành động (tức các hành động có cùng tên) đƣợc tạo để có cùng arity (tức số lƣợng tham số) bằng cách mở rộng chúng với các tham số gữ chỗ (placehoder) bởi dấu gạch dƣới “_”. Ví dụ hành động B(2) từ M1 có tham số là 2 còn hành động B() ở M2 có cùng tên nhƣng chƣa có tham số sẽ trở thành B( _ ) trong phần mở rộng vòng lặp của M2, vì vậy nó có cùng arity với B(2) trong M1. Hình 3.7 và hình 3.8 chỉ ra các phần mở rộng vòng lặp của M1 và M2 tƣơng ứng. Sản phẩm đƣợc tạo nên từ các mở rộng vòng lặp này.

Hình 3.5: Chƣơng trình mô hình M2

Hình 3.6: MP M1xM2 - sản phẩm của M1 và M2

Hình 3.8: Phần mở rộng vòng lặp của M2

Mỗi trạng thái trong sản phẩm là một trạng thái đôi đƣợc hình thành từ một trạng thái trong M1 và một trạng thái trong M2 (hình 3.9). Hình thành trạng thái đôi khởi tạo (0,0) từ các trạng thái khởi tạo của M1 và M2. Tạo ra phần còn lại của sản phẩm bằng cách thăm dò từ trạng thái đôi khởi tạo. Mỗi hành động đƣợc kích hoạt trong một trạng thái đôi phải đƣợc kích hoạt trong cả hai trạng thái tƣơng ứng ở các mở rộng vòng lặp của cả hai chƣơng trình. Ở ví dụ này, hành động A( ) là hành động chỉ đƣợc kích hoạt trong các trạng thái khởi tạo của cả hai chƣơng trình; C( ) và B( _ ) chỉ đƣợc kích hoạt trong M1 và M2 tƣơng ứng. Việc thực hiện hành động A( ) tạo nên chuyển tiếp tới trạng thái 1 trong M1 và tạo một chuyển tiếp lặp với chính nó quay trở lại trạng thái 0 trong M2, do đó trong sản phẩm A( ) tạo nên chuyển tiếp tới trạng thái đôi (1,0). Trong trạng thái này, B(2) đƣợc kích hoạt trong M1 và B( _ ) đƣợc kích hoạt trong M2. Hai hành động này phù hợp bởi vì tên của chúng là giống nhau. Các hành động này tạo nên các chuyển tiếp tới trạng thái 2 và 1 trong M1 và M2 tƣơng ứng, kết quả trong sản phẩm là trạng thái đôi (2,1). Hành động xuất hiện trong sản phẩm là B(2) không phải là B(_). Trong trạng thái đôi (2,1), C( ) đƣợc kích hoạt ở cả hai chƣơng trình, tạo nên một chuyển tiếp cuối cùng tới trạng thái (2,0) trong sản phẩm. Trong trạng thái đôi đó không có hành động đƣợc kích hoạt tiếp nên việc thăm dò dừng lại, sản phẩm hoàn chỉnh. Trạng thái đôi (2,0) là một trạng thái chấp nhận trong sản phẩm bởi vì cả hai trạng thái trong cặp đôi đều là các trạng thái chấp nhận.

Trong hình 3.10 tổng hợp thủ tục này. Với mỗi trạng thái đôi, nó chỉ ra các hành động đƣợc kích hoạt trong các mở rộng vòng lặp với các hành động phù hợp đƣợc bôi đậm. Các trạng thái chấp nhận cũng đƣợc bôi đậm.

Có một vài biến chứng bổ sung mà không phát sinh trong ví dụ đơn giản này, liên quan đến các đối số của các hành động. Khi các hành động có cùng tên nhƣng các đối số khác nhau (khác với tham số giữ chỗ) thì chúng không phù hợp. Ví dụ, nếu M2 trong ví dụ này có hành động B(3) thay vì B(_) thì nó sẽ không phù hợp với B(2) trong M1 và không có hành động B xuất hiện trong sản pẩm. Tuy nhiên, có thể xác định các hành động có tham số giữ chỗ ở bất kỳ vị trí nào, ví dụ hành động D(_,4) trong một

chƣơng trình này sẽ phù hợp với D(3,_) trong một chƣơng trình khác, kết quả là có D(3,4) trong sản phẩm.

Hình 3.9: MP M1xM2, các trạng thái đôi và hành động phù hợp

Hình 3.10: Các trạng thái và hành động trong M1xM2 FSMs cho điều khiển kịch bản:

Một MP kịch bản thƣờng đƣợc viết để biên soạn với một MP hợp đồng cho điều khiển kịch bản. Nó rất thuận tiện để thể hiện một MP kịch bản nhƣ một FSM. Thƣ viện và các công cụ hỗ trợ nhiều kiểu (styles) để mã hóa (coding) các MP. Trong phần này, một số kiểu để viết mã (code) FSMs cho điều khiển kịch bản sẽ đƣợc giới thiệu.

Đầu tiên, cách code một FSM đƣợc chỉ ra theo cách quen thuộc. Hình 3.11 chỉ ra chƣơng trình M1 (ở ví dụ trên) đƣợc code bằng C# trong cùng kiểu nhƣ các MP khác. Chỉ có một biến trạng thái duy nhất tƣơng ứng với số trạng thái nhƣ trong hình vẽ 3.4. Một chƣơng trình đƣợc code theo kiểu này đƣợc gọi là một MP thƣ viện (library). Có một phƣơng thức factory gọi hàm tạo cho lớp LibraryModelProgram

có nguồn gốc từ lớp cơ sở ModelProgram. Để hiển thị các FSM, biên dịch chƣơng trình và gọi mpv: mpv /r: M1.dll M1.Factory.Create

Để biên soạn và hiển thị hai MP trong ví dụ M1 và M2 nhƣ trong hình 3.6, gọi mpv: mpv /r: M1.dll /r:M2.dll M1.Factory.Create M2.Factory.Create

Hình 3.11: M1 dƣới dạng FSM text file

Một kiểu thứ hai là có thể dùng MP FSM. MP cũng sử dụng C# nhƣng thay vì mã hóa các biến trạng thái và các phƣơng thức hành động thì lập trình viên code FSM nhƣ một mảng các chuỗi. Trong đó, mỗi chuỗi mô tả một chuyển tiếp theo định dạng “t(trạng thái hiện tại, hành động, trạng thái tiếp theo)”. Trạng thái hiện tại trong chuyển tiếp đầu tiên là trạng thái khởi tạo. Trong phƣơng thức factory, mảng của các chuỗi đƣợc truyền vào phƣơng thức FSM.Create trả về một thể hiện (an instance) của lớp FSM. Một phƣơng thức khác trong lớp này có thể đƣợc sử dụng để xác định các trạng thái chấp nhận nếu có. Thể hiện FSM đƣợc truyền vào hàm tạo cho lớp FsmModelProgram cũng có nguồn gốc từ ModelProgram. Một MP FSM đƣợc biên dịch và hiển thị một cách chính xác theo cùng cách nhƣ một MP library.

Kiểu thứ ba là tệp văn bản FSM (FSM text file), đây là cách nhỏ gọn nhất (hình 3.11). Kiểu này kết hợp cùng với C# và phối hợp hoàn toàn, chỉ việc đặt FSM trong một tệp văn bản, trong một định dạng dấu ngoặc đơn. Phần tử đầu tiên bên trong dấu ngoặc đơn là trạng thái khởi tạo. Phần tử thứ hai là một chuỗi các trạng thái chấp nhận. Không cần thiết để biên dịch một tệp FSM. Để hiển thị FSM trong tệp tin, gọi mpv với tùy chọn /fsm và tên tệp tin: mpv /fsm:M1.txt

Trên thực tế, rất hiếm khi một MP FSM đƣợc viết, mà chỉ có một tệp văn bản FSM đƣợc viết thay thế. Khi một công cụ đƣợc gọi với tùy chọn “/fsm”, nó đọc FSM từ tệp và xây dựng một thể hiện FsmModelProgram trong nhiều cách tƣơng tự. Các công cụ yêu cầu kiểm thử viên viết một phƣơng thức factory cho các MP thƣ viện (library) chứ không phải chỉ là cách gọi hàm tạo tự động bởi vì đây là cách xác định các tính năng mà kiểm thử viên muốn thêm vào.

Một phần của tài liệu Nghiên cứu ứng dụng “NModel” trong việc phát triển hệ thống nhúng thời gian thực (Trang 37)