8

有限ステート マシンは、一般に OOP の悪い設計と見なされますか?

私はそれをよく聞きます。そして、それを利用する非常に古い文書化されていない C++ の部分に取り組まなければならなかった後、私は同意する傾向があります。デバッグするのは苦痛でした。

可読性/保守性の問題はどうですか?

4

7 に答える 7

20

FSMは決して悪いと見なされるべきではありません。それらはあまりにも便利ですが、それらに慣れていない人々はしばしばそれらを負担と見なします。

OOPを使用して実装する方法は多数あります。他のものより醜いものもあります。低レベルの人は、switchステートメント、ジャンプテーブル、さらには「goto」を使用します。

よりクリーンな方法をお探しの場合は、C++でUML状態図を実装するためだけに構築されたBoostの状態チャートライブラリをお勧めします。それは物事をより読みやすくするために、最新のテンプレート技術を利用しています。また、非常に優れたパフォーマンスを発揮します。

于 2010-02-02T00:52:21.327 に答える
9

有限ステート マシンは、特定の目的を達成するためのツールです。他のツールと同様に、それらも悪用される可能性があります。

彼らは最も優雅なツールではありませんが、彼らが得意とする仕事は、他の手段ではほぼ不可能です (通常、他のアプローチは、機械よりも何千倍もひどい混乱になる運命にあります)。

ジョブは、従来の待機状態が禁止されている状態で動作しています。

タッチスクリーンを読む必要があります。位置を読み取るには、SPI 経由で約 15 のコマンドを交換する必要があります。毎秒100回の読み取りが必要です。続行する前に、それぞれのビジー フラグが消えるまで、各コマンドの後に約 1 マイクロ秒待つ必要があります。コントラストの設定、モードの変更、バックライトのオン/オフ、温度の読み取りなど、同じインターフェイスで達成できる必要がある他の操作も多数あります。while(BUSY_BIT);待機ごとに実行すると、一瞬のうちにすべての CPU を使い果たします。sched_yield()またはを行った場合usleep(1)、必要な読み取り回数を達成することはできません。唯一の方法は、有限ステート マシンです。

しかし、有限状態マシンをうまく機能させる方法もあります。マシンを舞台裏に隠し、開発者が操作できる機能を提供します。

これまでの私の仕事の経験は、3 つの異なる有限状態マシンに基づく 2 つのシステムに支配されていました。

  1. 各ステップでデータベースからいくつかのデータを取得し、それに基づいてさらにクエリを準備する大きな Web ポータル。最後のステップでは、データを使用して HTML を生成します。各タスク (Web ページ モジュール) は、エンジンから継承する PHP クラスとして実装されました。状態はクラス変数に保持されました。各ステップは個別の機能でした。ステップの最後に、保存されたクエリが最適化され、キャッシュを介してエンジンに送信され、回答が元のクエリに返されました。
  2. 多くのサブシステムを備えた組み込みデバイス。タスク ポンプが使用されます。各モジュールは、メイン ループから 1 秒間に何度も呼び出されるハンドラを登録します。ハンドラーは、状態を使用して、静的変数またはクラス変数に状態を保持できます。この協調的なマルチタスキングにより、すべてを個別のスレッドで実行するよりもはるかに少ないメモリ フットプリントが可能になり、タスクを 2 回登録することでタスクの手動優先順位付けが可能になり、スレッドが高い優先度で実行され、システムの残りの部分が見えなくなります。
  3. 半通訳。あのタッチパネル。関数呼び出しとその待機状態は登録されますが、それぞれが 1 回だけ呼び出され、その後プログラム キューから削除されます。インタープリターは taskpump のタスクとして呼び出され、待機状態としてマークされた関数に遭遇する (または呼び出される関数の数を超える) まで、制限された数の関数を実行します。その後、待機状態がなくなるまで続行します。他のタスクは、実行される関数の (場合によっては長い) シーケンスとしてジョブをキューに入れ、結果を待ちます。このようにして、作成する必要がある状態の数を、結果が必要な約 4 つに制限できます。コマンドが「コントラストを設定」のように「送信し、結果を確認しない」の場合、個別の状態はまったく必要ありません。したがって、実際の状態は、「イベントを待機し、要求されたデータを登録する」、「測定を待機する」、および「

構造的に、または順番に記述した場合、コードは 2 倍シンプルになり、3 倍明確になります。それが機能しないか、ひどいパフォーマンスで機能することを除いて。

于 2010-02-02T11:22:12.970 に答える
5

彼らが言うことをあなたに言うことができませんでした。

しかし、OOとFSMは、異なる問題のドメインを攻撃します。オブジェクトが相互作用しているドメインでは、オブジェクト指向のアプローチが必要です。世界がある状態または別の状態にあるドメインでは、FSM設計が必要です。

現実的には、これらのデザインをさまざまな抽象化レベルと組み合わせることができます。これにより、どちらか一方だけを使用するよりもクリーンになります。

于 2010-02-02T00:51:09.890 に答える
3

有限状態マシンは、同じ問題(正規言語のマッチングなどの問題)を解決する他の方法よりもデバッグがはるかに簡単だと思います。FSMの優れている点は、すべてその名のとおりです。15の状態を持つステートマシンがある場合があるため、すべての遷移を示す図を紙に描くことができます。この図を使用して、システムが受け入れる文字列やエラー状態になる方法など、システムの有用なプロパティを把握できます。より複雑なシステムでは、図表化はしばしば困難または不可能です。

「ゴトは悪だ」と言う人々でさえ、ステートマシンを実装する正しい方法だと考えています。(もちろん、ゴトは常に邪悪だと考える人もいます...しかし、みんなを喜ばせることはできません)。

于 2010-02-02T00:48:38.710 に答える
1

コードが十分に文書化されていれば、OOP アプローチを使用して実装しても問題はないと思います。C/C++ のほとんどは、switch ステートメントを使用して FSM を実装するために使用されます。これは、マシンが大きい場合に可読性を損なうことがあります。

最近、正規言語を解析する必要があり、OOP アプローチを使用して FSM を実装しました。コードの可読性と保守性は良好でした。つまり、大きな switch ステートメントを使用するよりもはるかに優れています。

ヒントとして、最初に、状態を含む FSM と遷移を含む状態を実装しました。ただし、私の場合は、1 つの状態のコレクションと別の遷移のコレクションを含む FSM を表すクラスを作成する方が優れたアプローチであることがわかりました。マシンのクローンを作成し (それは私にとって必要条件でした)、移行機能を小さくすることが容易になりました。

お役に立てば幸いです、カルロス。

于 2010-02-02T00:44:06.130 に答える
0

ステートマシンは、任意のクラスの動作を表すために使用できます。着信イベントの順序がクラスの動作(組み合わせクラス)に関係ない場合、状態モデルを使用しても特別なメリットはありません。

ただし、クラスの動作が着信イベントの順序に依存する場合(シーケンシャルクラス)、ステートマシンは、動作の分析と実装に最適な選択肢です。

読みやすさ/保守性が懸念される場合は、グラフィック表現を使用してください。さまざまなエンジニアリングドメインに属するクラスの動作の例は、http://www.StateSoft.org- > StateMachineGalleryにグラフィカルで実行可能な形式で示されています。

-ヤヌス

于 2011-09-21T20:19:48.483 に答える