科学と家事とプログラミング (python を中心に)

python 温度計測 湿度計測 DS18B20 USB9097

超構造化(07) 状態機械の実装モデル

状態機械の実装モデル

コーディングの話からは大きく逸脱するが、ここで、最も原初的な(シンプルな)状態機械 の設計について述べておきたい。まず「状態」を以下の3つの操作/動作で定義(モデル 化)する。

  1. enter() ある状態への入場時の初期化
  2. leave() その状態から退場するときの後始末
  3. daily_job() その状態がアクティブな間の動作

状態遷移を C 言語っぽく書くと、以下の通り。この状態遷移は、アトミック・アクション にする必要がある(current_task の排他アクセスの保証)。アトミック・アクションが分か らない人は調べてもらうとして、乱暴に言えば、設計対象の時間が止まっていると見做せ るということ。

static TASK *current_task = (TASK *)0; /* 現在タスク pointer */
void task_switch(new_task) {
    /* 状態を current_task から new_task に変更する。
    * この関数はアトミックに実施する
    */
    if (current_task != (TASK *)0) { /* 実効中のタスクがあれば */
        current_task->leave(); /* 後始末 */
    }
    current_task = new_task; /* 新しいタスクに切り替えて */
    current_task->enter(); /* 初期化 */
}

void task_tick(void) {
    /* task_tick() は タイマーなどから呼ばれて、
    定期的に現在タスクの仕事を起動する */
    if (current_task != (TASK *)0) {
        current_task->daily_job();
    }
}

状態遷移は 必ず task_switch() という関数で行うというルールさえ守れば、前の状態 の後始末と、次の状態の初期化が保証される。この方式の一番のメリットは状態毎の単体 試験を実施しやすいことだろう。ここで紹介した方式/手法の核心は、各状態が遷移前の状 態に依存しないことである。誘惑に負けて、enter や daily_job の中から(こっそりと)、ひ とつ前の状態を参照したりすると台無しになる。 状態機械は、動的なモデルとして紹介されることが多いが、表現された状態遷移図や状態 遷移表は至って静的なものである。未来に起こり得るすべての遷移を全て含んでいると言 っても良い。どこかで聞いたフレーズの繰り返しになるが、未来を全て含んでしまえば、 そこに時間は流れない((C)養老孟司)。状態機械は、時間的な推移を空間化したうえで、全 体的な構造を把握し、見た目の対称性や、形式的な完全性、直交性、整合性を設計/確認す るための手法と捉えることができる。

f:id:sken20k:20180211225557j:plain 状態遷移の良いイラストは、なかなか思いつかず...

状態機械の条件分岐?

UML の状態機械には、コンディションやチョイスといった条件分岐的な要素が用意されているけ れど、それらを適用するかどうかの判断は慎重に行った方がよい。状態機械に条件分岐的な要素を許 すと、レビューや試験設計が極端に難しくなる。原則論として、同一のイベントに対して遷移先が異 なるのであれば、それは別の状態として扱うべきだ。そうではないか?

試験といえば、状態遷移行列を使った試験ケースの設計手法は有効と思う。いずれ紹介したい。