LoginSignup
18
19

More than 5 years have passed since last update.

CoffeeScriptだけで簡単に作れるステートマシン

Posted at

jQueryとJavaScript(CoffeeScript)を使った開発をしていて、ユーザーからの入力のイベント処理とAjaxによる通信のイベント処理がごちゃごちゃになって困ったことはありませんか?

私は最近までよくフラグだらけになる失敗をしました。

このような問題を解決する道具のひとつとしてステートマシンがあります。

CoffeeScriptを使って試行錯誤した結果、短く簡単に作れるようになったので紹介してみたいと思います。

demo_state_machine.coffeeはサンプルのソースコードです。

DemoSMがステートマシンで、アクションのハッシュを引数にして関数として呼び出します。

ステートマシンに対してイベントを送る(sm().ev1(), sm().ev2()などをコールする)と、内部のステートが変わりアクションが実行されます。

デバッグモードも用意してあり、sm.setDebugMode(true)すると、内部のステートの遷移がコンソールに出力されます。

demo_state_machine.coffee
DemoSM = (actions) ->
  currentState = null
  inTransition = false
  debugMode = false

  setState = (state) ->
    throw 'Recursive call of setState is forbidden' if inTransition
    inTransition = true
    currentState.Exit() if currentState
    currentState = state
    console.log "ENTER STATE: #{state.name()}" if debugMode
    currentState.Entry()
    inTransition = false

  defaultAction = -> null

  class StateBase
    name: -> 'StateBase'
    Entry: defaultAction
    Exit: defaultAction
    ev1: defaultAction
    ev2: defaultAction

  STATE1 = new class extends StateBase
    name: -> 'STATE1'
    Entry: -> actions.onEntry 'STATE1'
    Exit: -> actions.onExit 'STATE1'
    ev1: -> setState STATE2

  STATE2 = new class extends StateBase
    name: -> 'STATE2'
    Entry: -> actions.onEntry 'STATE2'
    Exit: -> actions.onExit 'STATE2'
    ev2: -> setState STATE1

  setState STATE1

  self = -> currentState
  self.setDebugMode = (mode) -> debugMode = mode
  self.isDebugMode = -> debugMode
  self.isInTransition = -> inTransition
  self

sm = DemoSM
  onEntry: (name) -> console.log "#{name}: onEntry"
  onExit: (name) -> console.log "#{name}: onExit"

sm.setDebugMode true
sm().ev1()
sm().ev1()
sm().ev1()
sm().ev2()
sm().ev1()

動作の確認は、開発環境を用意しなくてもWeb上から行うことが出来ます。

サンプルであげたようなソースコードを定義ファイルから自動生成するツールを作成中なので、もしも需要がありそうなら公開したいと思います。

18
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
19