2010-02-02 53 views
8

Máy hữu hạn có được coi là thiết kế kém trong OOP không?Máy trạng thái hữu hạn: Thiết kế kém?

Tôi nghe rất nhiều. Và, sau khi tôi phải làm việc trên một mảnh C++ cũ, không có giấy tờ để sử dụng nó, tôi có xu hướng đồng ý. Đó là một nỗi đau để gỡ lỗi.

những vấn đề về khả năng đọc/bảo trì là gì?

+0

liên quan: http://stackoverflow.com/questions/1647631/c-state-machine-design – jldupont

+7

Là một Pastafarian sùng đạo , FSM luôn tốt;) – richo

+7

Không bao giờ làm hỏng toàn bộ cách tiếp cận vì bạn đang xem xét việc triển khai kém. Bất cứ điều gì không có giấy tờ/khó gỡ lỗi là xấu, nhưng nó là việc thực hiện đó là xấu. –

Trả lời

16

FSM không bao giờ được coi là xấu. Chúng quá hữu ích, nhưng những người không quen với chúng sẽ thường coi chúng là gánh nặng.

Có nhiều cách để triển khai một ứng dụng có OOP. Một số thì xấu hơn những người khác. Những người cấp thấp của bạn sẽ sử dụng câu lệnh chuyển đổi, bảng nhảy hoặc thậm chí là "goto".

Nếu bạn đang tìm kiếm một cách rõ ràng hơn để làm điều đó, tôi khuyên bạn nên Boost's State Chart library, được xây dựng chỉ để triển khai sơ đồ trạng thái UML trong C++. Nó sử dụng các kỹ thuật mẫu hiện đại, để làm cho mọi thứ dễ đọc hơn. Nó cũng hoạt động rất tốt.

+4

+1 cho mô tả và liên kết Boost tự chứa trên trang đầu tiên liên kết tới tệp PDF của Robert C. Martin có tên "Hướng dẫn UML: Máy hữu hạn của tiểu bang". Một cổ điển cho bất cứ ai vào OO/State Machine. – SyntaxT3rr0r

+0

"Không bao giờ" là một quan điểm khá cực đoan. IMO, có một tập hợp hẹp các tình huống mà chúng thích hợp. Thậm chí sau đó, tôi chưa thấy một triển khai rõ ràng mà không đòi hỏi một số lượng lớn kỷ luật để sử dụng đúng (bao gồm cả biểu đồ trạng thái tăng). – Catskul

1

Tôi nghĩ rằng nếu mã được viết tài liệu thì không có vấn đề gì khi triển khai nó bằng cách sử dụng phương pháp OOP. Hầu hết việc sử dụng C/C++ để triển khai FSM bằng cách sử dụng các câu lệnh chuyển đổi đôi khi có thể làm tổn hại đến khả năng đọc nếu máy lớn.

Gần đây tôi cần phải phân tích cú pháp ngôn ngữ thông thường và triển khai FSM bằng cách sử dụng phương pháp tiếp cận OOP, khả năng đọc và bảo trì mã là tốt. Ý tôi là, tốt hơn nhiều so với sử dụng các câu lệnh chuyển đổi lớn.

Một mẹo, tại thời điểm đầu tiên, tôi đã triển khai các trạng thái containg FSM và các trạng thái chứa các hiệu ứng chuyển tiếp. Tuy nhiên, trong trường hợp của tôi, nó được chứng minh là một cách tiếp cận tốt hơn để có một lớp để đại diện cho FSM chứa một bộ sưu tập các trạng thái và một bộ chuyển tiếp khác. Nó giúp tôi dễ dàng sao chép các máy hơn (nó là một yêu cầu đối với tôi) và có một chức năng chuyển tiếp nhỏ hơn.

Tôi hy vọng điều đó sẽ giúp ích, Carlos.

2

Tôi sẽ nói rằng các máy trạng thái hữu hạn dễ debug hơn nhiều so với các cách khác để giải quyết các vấn đề tương tự (các vấn đề như kết hợp các ngôn ngữ thông thường). Có gì tốt đẹp về FSM là tất cả trong tên ... bạn có thể có một máy nhà nước với 15 tiểu bang, vì vậy bạn có thể vẽ một sơ đồ trên một mảnh giấy hiển thị tất cả các quá trình chuyển đổi. Bạn có thể sử dụng sơ đồ để tìm ra các thuộc tính hữu ích của hệ thống, chẳng hạn như các chuỗi nó chấp nhận và cách nó được đưa vào trạng thái lỗi. Với các hệ thống phức tạp hơn, việc lập biểu đồ thường khó hoặc không thể.

Ngay cả những người nói "gotos là ác" nghĩ rằng họ là đúng cách để thực hiện các máy nhà nước. (Tất nhiên, một số người nghĩ rằng gotos luôn luôn là ác ... nhưng bạn không thể làm hài lòng tất cả mọi người).

5

Không thể cho bạn biết những gì họ nói.

Nhưng phân loại OO và FSM tấn công các miền vấn đề khác nhau. Trong một miền, nơi các đối tượng đang tương tác - gọi các phương thức tiếp cận hướng đối tượng. Trong một miền nơi thế giới đang ở trạng thái này hay trạng thái khác - yêu cầu thiết kế FSM.

Thực tế, bạn có thể kết hợp các thiết kế này với/ở các mức trừu tượng khác nhau, sẽ trở nên sạch hơn so với chỉ sử dụng một hoặc cái kia.

6

Máy trạng thái hữu hạn là công cụ để đạt được kết thúc nhất định. Như bất kỳ công cụ nào, chúng cũng có thể bị lạm dụng.

Chúng không phải là công cụ duyên dáng nhất, nhưng công việc mà họ giỏi là không thể đạt được bằng các phương tiện khác (và thường là bất kỳ cách tiếp cận nào khác sau đó sẽ trở thành một đống lộn xộn khủng khiếp gấp hàng nghìn lần so với máy).

Công việc đang hoạt động trong điều kiện trạng thái chờ cổ điển bị cấm.

Tôi phải đọc màn hình cảm ứng. Để đọc vị trí, tôi phải trao đổi khoảng 15 lệnh trên SPI. Tôi cần 100 bài đọc tốt một giây. Tôi phải chờ khoảng 1 micro giây sau mỗi lệnh, cho lá cờ bận rộn tương ứng biến mất trước khi tôi có thể tiếp tục. Ngoài ra còn có một số hoạt động khác phải đạt được trên cùng một giao diện, như thiết lập độ tương phản, thay đổi chế độ, bật hoặc tắt đèn nền, đọc nhiệt độ. Nếu tôi thực hiện while(BUSY_BIT); cho mỗi lần chờ, tôi sẽ ăn hết tất cả CPU trong giây lát. Nếu tôi đã làm sched_yield() hoặc usleep(1), tôi sẽ không bao giờ đạt được số lượng readouts mà tôi muốn. Cách duy nhất là một máy trạng thái hữu hạn.

Nhưng có nhiều cách để làm cho máy trạng thái hữu hạn phát đẹp. Ẩn máy đằng sau hậu trường và cung cấp cho các chức năng của nhà phát triển để làm việc.

Kinh nghiệm làm việc của tôi cho đến nay bị chi phối bởi 2 hệ thống dựa trên 3 máy trạng thái hữu hạn khác nhau.

  1. cổng thông tin web lớn, trong mỗi bước bạn truy xuất một số dữ liệu từ cơ sở dữ liệu và dựa trên đó, chuẩn bị nhiều truy vấn hơn. Trong bước cuối cùng bạn sử dụng dữ liệu để tạo HTML. Mỗi tác vụ - một mô-đun trang web - được triển khai như một lớp PHP kế thừa từ công cụ. Nhà nước được bảo tồn trong các biến lớp. Mỗi bước là một chức năng riêng biệt. Vào cuối một bước, các truy vấn được lưu trữ đã được tối ưu hóa và gửi đến động cơ, thông qua bộ nhớ cache và các câu trả lời được cung cấp lại cho bản gốc.
  2. thiết bị được nhúng với nhiều hệ thống phụ. Task Pump được sử dụng. Mỗi mô-đun đăng ký một trình xử lý được gọi nhiều lần trong một giây từ vòng lặp chính. Trình xử lý có thể bảo toàn trạng thái trong các biến tĩnh hoặc lớp, với các trạng thái. Sự đa nhiệm hợp tác này cho phép lưu lượng bộ nhớ nhỏ hơn nhiều so với chạy tất cả trong các luồng riêng biệt, cho phép ưu tiên thủ công các tác vụ bằng cách đăng ký chúng hai lần, và có chuỗi chạy ở mức ưu tiên cao, làm lu mờ phần còn lại của hệ thống.
  3. thông dịch viên bán. Màn hình cảm ứng đó. Các cuộc gọi chức năng và trạng thái chờ của chúng được đăng ký, nhưng mỗi trạng thái được gọi chỉ một lần, sau đó bị xóa khỏi hàng đợi của chương trình. Trình thông dịch được gọi là nhiệm vụ của taskpump, thực hiện một số chức năng giới hạn cho đến khi gặp phải một hàm được đánh dấu là trạng thái chờ (hoặc vượt quá số hàm được gọi). Sau đó, nó tiếp tục cho đến khi trạng thái chờ biến mất. Các công việc khác enqueue công việc như (đôi khi dài) trình tự của các chức năng được thực hiện, sau đó chờ kết quả. Bằng cách này tôi có thể giới hạn số lượng trạng thái tôi cần để tạo ra khoảng 4 nơi tôi cần kết quả. Nếu lệnh là "gửi đi, không bao giờ kiểm tra kết quả" như "thiết lập tương phản", họ không cần các trạng thái rời rạc cả. Vì vậy, các trạng thái thực tế là "chờ sự kiện và đăng ký dữ liệu được yêu cầu", "chờ đợi để đo lường" và "đọc kết quả và gán chúng đúng cách".

Mã sẽ đơn giản gấp hai lần và rõ ràng hơn ba lần nếu được viết theo cấu trúc hoặc tuần tự. Ngoại trừ nó sẽ không làm việc, hoặc sẽ làm việc với hiệu suất abysmal.

0

Máy trạng thái có thể được sử dụng để thể hiện hành vi của bất kỳ Lớp nào. Nếu thứ tự các sự kiện đến không quan trọng đối với hành vi Lớp (lớp tổ hợp), việc sử dụng Mô hình Nhà nước không mang lại lợi ích đặc biệt nào.

Tuy nhiên, nếu hành vi của lớp phụ thuộc vào thứ tự của các sự kiện đến (lớp tuần tự), máy trạng thái thể hiện sự lựa chọn tốt nhất cho phân tích hành vi và thực hiện.

Nếu khả năng đọc/bảo trì là mối quan ngại của bạn, hãy sử dụng các biểu diễn đồ họa. Ví dụ về hành vi của các lớp thuộc các lĩnh vực kỹ thuật khác nhau được trình bày dưới dạng đồ họa và thực thi tại http://www.StateSoft.org -> Thư viện máy nhà nước.

-Janusz

+0

Tôi không tin rằng điều này đúng với các lớp học có đầy đủ ngôn ngữ hoàn chỉnh. https://upload.wikimedia.org/wikipedia/commons/a/a2/Automata_theory.svg – Catskul

1

FSM có thể dễ hiểu và duy trì nếu mã được cấu trúc đúng cách. Tôi đã thực hiện một FSM trong công việc trước, đây là một mẫu xương:

FSM

Các vấn đề liên quan