姚红岩,李佳琦,马云吉
(辽宁科技大学 辽宁 鞍山 114051)
通过状态的变化来考量对象的属性数据集合、评估对象的行为是最为细微全面的[1,2]。在软件建模范畴,针对某级别的对象为其进行状态建模,是全面把握对象行为的关键。目前在工程领域,为对象进行状态建模时,状态图和状态表是两种常见手段[3-7]。如何选用这两种手段将关乎到设计思想的清晰表达以及模型的代码转化,目前在这方面鲜有分析。本文通过一个电梯模拟系统的验证,对这两种手段进行分析,探讨在不同场景下,状态图和状态表哪个更利于设计。
形式化的有限状态机在模型上可定义为四元组:M ={S,S0,X,Transition}。S是一个对象的有限状态集合;S0∈S,是初始状态;X是对象的有限事件的集合;Transition:S*X→S是状态转移函数。
状态图是状态机的一种直观的图形化表达,状态图应至少表达出与状态机对应的信息,如各状态的名称、响应的事件、迁移函数等。图1的左半部分是对应四元组的描述状态的基本图形,右半部分是设计模型时实际用到的简化版本,其中“活动”即是表达状态变化的迁移函数。“事件/活动”表达的语义是针对某个事件,引发哪些对应的活动。
图3 为电梯设计的状态转换图
图1中的状态图在遇到复杂的状态表达时,有两类数据表达缺失:一是不能表达守卫条件;二是缺少表达状态特征的属性数据。这两类信息的缺失不利于设计思路的图形化表达,往往会使整个状态图细化的状态颇多,语义晦涩。改进后的基本状态图形如图2所示。
图1 图形化的基本状态元素
图2 改进后的基本状态元素
利用图2进行状态建模时,不必针对特征数据或者守卫条件对状态做过细的划分。这能极大地减少状态图中基本状态的数目,使状态图更清晰、语义更流畅。
状态表是状态建模的另一种形式。结合图2的说明,定义状态表的字段如表1所示。对应该表的一个示例参见表2。
?
?
电梯是典型的需建模状态的对象。下面将先后使用改进后的状态图、表对电梯系统进行状态建模,然后对比两种建模方法的适用性。
建模电梯状态的状态图见图3。对图3的说明如下:
(1)基础状态有6个,分别是movedown_straight_for_pickup(下行接人),move_up_for_dump_and_pickup(上行接/送人),idle(静止),stop_and_open(暂停并开/关门),moveup_straight_for_pickup(上行接人),move_down_for_dump_and_pickup(下行接/送人)。
(2)以moveup_straight_for_pickup(上行接人)为例,该状态的语义描述是:状态名,moveup_straight_for_pickup;特征数据,“电梯方向:向上”。该状态有两个事件/活动,一个是:守卫条件G1,无;活动,“向上移动一层”;守卫条件G2,“未到达目标楼层”;箭头指向迁移后的状态moveup_straight_for_pickup。另一个是:守卫条件G1,“到达目标楼层”;活动,“开门/关门、设定相反方向”;守卫条件G2,无;箭头指向目标状态为move_down_for_dump_and_pickup。图3中的其它基本状态在语义上与此类似,不赘述。
(3)初始时,电梯处于idle状态,根据目的表是否为空,从idle状态存在8条迁移路线:首先是目的表非空(意味着有人在轿厢内点击了按钮)的情况,如首个目的楼层大于当前楼层,则迁移至move_up_for_dump_and_pickup状态,如小于当前楼层则迁移至move_down_for_dump_and_pickup,如等于当前楼层则进入状态stop_and_open;其次是目的表为空的情况(轿厢内没人点击按钮),如有人在更高的楼层传唤电梯且要上楼,则电梯转入move_up_for_dump_and_pickup状态,如有人在更低的楼层传唤电梯且要下楼,则电梯转入move_down_for_dump_and_pickup状态,如有人在更高的楼层传唤电梯并要下楼,则转入moveup_straight_for_pickup,如有人在更低的楼层传唤电梯并要上楼,则转入movedown_straight_for_pickup状态。如有人在当前楼层传唤电梯,则转入stop_and_open状态并开/关门。
(4)当电梯处于move_up_for_dump_and_pickup和move_down_for_dump_and_pickup状态时,在当前移动方向上,既可以在传唤楼层接人,也可以在目的楼层送人;但当电梯处于moveup_straight_for_pickup和movedown_straight_for_pickup时,在到达指定传唤楼层接人期间,如A层,中途不能再接人(因为无法预测中途进入轿厢的人它的目的楼层是高于还是低于A层),但可以在到达目的楼层时送人。
(6)如电梯处于move_up_for_dump_and_pickup状态,在有人呼叫上行或者仍有上行目的楼层时(守卫条件G1),要上行一层,如当前楼层有上行传唤要求或者目的楼层正是当前层(守卫条件G2),则转入stop_and_open状态。在stop_and_open状态时,电梯开/关门时间是8秒,之后根据电梯当前运行方向,如向上,则重新转入move_up_for_dump_and_pickup状态。如在move_up_for_dump_and_pickup状态时,在满足守卫条件G1:“没有待接送的货物”时,自行转入状态idle,特征数据重置为无方向。
电梯在move_down_for_dump_and_pickup状态与move_up_for_dump_and_pickup状态下的行为类似,不再赘述。
下表2是遵照表1给出的电梯状态的转换表。该表清楚记录状态迁移时需考虑的守卫条件和进行的活动。该表明显没有状态图直观,不易形成电梯运行的直观印象。对于大家都熟悉的电梯尚且如此,如果直接给出一个陌生系统的状态表,要深入理解各状态迁移的合理性将更为费力。
(1)增加了守卫条件的状态图,能大幅减少基本状态的数目。(参见图3)试想如果不在迁移箭线上注明各种守卫条件,那么势必要对应这些条件细化出若干子状态或衍生出新的状态。整个状态图将涵盖更多状态,使得主体状态之间的迁移路线不清晰且状态图很“脏”。
(2)虽然状态图在表达设计路线上有优势,但也应注意到,箭线上的守卫条件的性质表达的不够明显,不能直观有效地区分GC1和GC2。当守卫条件更复杂时,状态迁移在语义上较为含混,不利于指导编码人员有效地进行模型的代码转化。
(3)状态表能清晰地指出源状态和目标状态,迁移时需考量的守卫条件GC1、GC2以及对应的活动也是一目了然。但是,如果直接用状态表建模,建模的思路相比于状态图而言,表达的不直观、不利于设计路线的展示。同时从表2中难于体会图3中体现出的设计上的对称性,这会增加理解状态迁移的难度。
(4)状态表能有效指导模型的代码转化。参照表2能直接针对特定的源状态进行编码且在编码时不必额外考虑状态迁移的合理性。
综上,在设计状态模型时,状态图在表达主体状态迁移上更有优势,编排良好的状态绘图能最大程度提升设计思路的表现力。而在代码化状态模型时,状态表则能更有秩序地指导编码意图。
应用改进的基本状态元素的图形表达方式,可将复杂的迁移条件和活动表示在迁移路线上,这能极大地减少细粒度状态的数目,同时能清晰表现主干状态的迁移,防止出现子状态。设计给出的电梯系统的状态图同时也证明了没有子状态的状态图是清晰可辨的,有设计美感。此外,根据电梯系统的状态表也能得出另外一个结论:直接给出状态表不便于设计思想的表达。状态和迁移路线较多的状态表,除了有利于指导编码之外,在表现设计思路上并不适合。因此在面对状态较多的复杂系统,建模状态时应首先使用状态图表现设计思路,在指导模型编码时才应转化为状态表。
[1]徐宝文,周毓明,卢红敏.UML与软件建模[M].清华大学出版社,2013.
[2] R o b e r t C.M a r t i n,M i c a h M a r t i n.A g i l e Principles,Patterns,and Practices in C#[M].Prentice Hall,July 2006,ISBN:0131857258.
[3] Hongyan Yao,Xuebo Sun,Han Bao.A New Notation TN for Expressing Concurrency in Program Design[J].ICIC Express Letters,2017(11)2:285-290.
[4] 刘忠,邓苏,沙基昌,张维明.基于状态图的对象行为建模[J].计算机工程与设计,2001,22(2):9-12.
[5] Jilong CHEN,Quanli YANG,Fang ZHANG,Xiong WU.Research and Design of Simulative System of Elevators Based on Java[J],Agricultural Science &Technology,2014,15(2):307-309.
[6]陈纪龙,孟洪兵,吴刚,六层电梯模拟系统的研究与实现[J].伊犁师范学院学报,2014,8(1):57-62.
[7]陈纪龙,孟洪兵,利用OO方法实现电梯控制系统的模拟[J],塔里木大学学报,2014,(26)1:128-132.