关于状态机的一点心得体会

使用状态机的好处:
1. 有限状态机(FSM)是收敛的,保证用户操作(外部事件)都能够响应,并且回到可以预测的可控制范围内。
2. 状态机是正交的,可以覆盖用户操作(外部事件)的所有可能性,而又不会重复处理。
3. 另外,状态机作为一个通用的表现形式,有时候还能够在某一个抽象层次上作为一个可以复用的模板。比如高通的CDMA代码中,实现ICMP协议和LCP协议的时候就抽象出了一个通用的FSM。

既然状态机有这样的好处,为什么不是所有的程序都用状态机的形势表示和处理呢?这是因为“有限”两个字,如果都用状态机表示,势必造成状态的无限扩展,反尔不好处理。比如,在输入密码的界面,如果每输入一个密码,也认为是一个新的状态,那么……

另外,状态机表现世界也不是万能的,比如状态机不具有记忆性(仅能记忆当前的内容),所以,需要配合其它的结构,比如栈等。比如,在brew程序里,使用栈来记忆App获得焦点的顺序。

怎样比较好的实现一个状态机:
状态机的一般表现形式:
     event / action
A -------------------------> B

action 又可以分为:
1) 接收到event时做的事情,这个时候还不发生状态的改变, s_ev_handle;
2) 状态改变时,从A退出做的动作, exit_action;
3) 状态改变时,进入B做的动作, enter_action。

这样的分法有这样的好处:
1)有的时候,一个状态在等到某一个事件时,会进行一次长时间的,或者是特定的处理,或者处理完成并不进行状态的转移,这个时候用s_ev_handle进行特别处理比较合理。
2) 有的时候,进入或退出一个状态都会进行一些公共的处理,例如初始化或者回收状态期间的临时对象等,比如,在mot的UI程序中,创建或POP该状态对应的FORM;注册某些特定状态下才会响应或不响应的事件等,这个时候用enter_action或exit_action比较合理。
3) 状态转移应该是个比较快的过程,这样才能满足时间上状态机的正交性,所以enter_action和exit_action应该处理一些耗时比较短的动作。
4) 通过在状态初始化时进行enter_action的动作,状态中进行s_ev_handle的处理,状态退出时进行exit_action的动作,一个状态就有了自己的生命周期,这个在C编程中似乎只是形式上的东西,没有什么意义,但是通过这种OO的思考方式应该对设计有所帮助。

下表是一个状态机的通用表现形式

 ev1ev2ev3
s1 (enter_action, exit_action) s1_ev1_handle  
s2   
s3   

在mot目前的代码框架中,brew_comm就是通过遍历每个App的状态表实现的,brew_comm的event_handle函数的第一次循环是按行遍历了状态表的第一列,找到了当前的App状态,再按列遍历找到event响应的处理函数。
另外,brew_comm还提供了app_change_state的方法,实现状态转移时enter_action, exit_action的调用。

运用状态机有可能遇到的问题:
有的时候,会发现enter_action的动作中需要上一个状态的信息,比如按CLR键进入前一个FORM时有可能需要知道是从哪个FORM退回的,那是不是要把前一个FORM的enter_action的动作加到s_CLR_handle中去呢?我觉得这里有两个思路可以解决这个问题,1) 利用别的数据结构来克服状态机缺乏记忆功能的问题,例如使用一个变量保存s_CLR_handle的状态标识;
2) 索性把新状态分成几个状态(或者子状态),因为从状态机描述客观世界的角度看,处理流程的不一致,其实就是产生了新的状态。不过这个方法好像和目前mot的框架思想不太一致,因为这样可能会产生这样的结果:一个FORM会对应若干个状态。

一点建议:
在设计到编写代码之前,建议填写完整上面的状态表格,能够集中检查设计中的不足;统一确定各个事件,状态,处理函数的命名规则,使程序具有较好的可维护性;能够利用第三方工具直接生成代码,进行测试,或者反映射成状态图等。

需不需要在一个App进入和退出的时候加两个不需要FORM对应的伪状态?这样可以解决下面一些问题:
1)比如在进入App的第一个状态前,App需要根据一个事件才能确定进入哪个状态,如果加了初始的伪状态,App就可以在伪状态中等待触发事件了。
2) App可以从很多状态退出,那么这些状态都需要调用App的退出处理过程,这时,加一个结束伪状态更加可以精简代码,并且提高状态机的收敛性和完备性。 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值