私は組み込みのものを扱っており、ハードウェアを管理するソフトウェア モジュールをいくつか持っています。このモジュールには状態があり、状態遷移は複雑です。イベントに応じて、モジュールは状態から状態A
へB
、またはおそらくへと移行しC
ます。ただし、何らかの状態を終了するときに、ハードウェアを正しい状態に保つために、ハードウェアでいくつかのアクションを実行する必要があります。
かなり単純なモジュールの場合、次のような関数がいくつかあります。
enum state_e {
MY_STATE__A,
MY_STATE__B,
};
static enum state_e _cur_state;
void state_on_off(enum state_e state, bool on)
{
switch (state){
case MY_STATE__A:
if (on){
//-- entering the state A
prepare_hardware_1(for_state_a);
prepare_hardware_2(for_state_a);
} else {
//-- exiting the state A
finalize_hardware_2(for_state_a);
finalize_hardware_1(for_state_a);
}
break;
case MY_STATE__B:
if (on){
//-- entering the state B
prepare_hardware_1(for_state_b);
prepare_hardware_2(for_state_b);
} else {
//-- exiting the state B
finalize_hardware_2(for_state_b);
finalize_hardware_1(for_state_b);
}
break;
}
}
void state_set(enum state_e new_state)
{
state_on_off(_cur_state, false);
_cur_state = new_state;
state_on_off(_cur_state, true);
}
明らかに、関数内のすべての状態に必要なすべてのアクションを保持する必要があり_state_on_off()
ます。別の状態に移動する必要がある場合は、呼び出すだけで_state_set(new_state)
、状態遷移は方向に関係なくスムーズに進みます。必要なすべてのアクションが実行されます。
ただし、単純な状況でのみ機能します。MY_STATE__B
状態との間に何か共通点があり、状態が からにMY_STATE__C
変更されたり、元に戻ったりするときに、短縮されたデストラクション/コンストラクションのみを実行する必要がある場合はどうなるでしょうか? しかし、他の状態 (たとえば、) に移動するときは、完全な破棄を実行する必要があります。MY_STATE__B
MY_STATE__C
MY_STATE__A
頭に浮かぶのはサブステートです。したがって、1 つの状態MY_STATE__BC
と、およびのようなサブ状態がMY_BC_SUBSTATE__B
ありMY_BC_SUBSTATE__C
ます。もちろん、 のような独自の機能があり_state_bc_on_off()
ます。これでもすでに苦痛ですが、もっと複雑なことを想像してみてください。
では、そのようなことのベストプラクティスは何ですか?