我们有一个相当大的USSD应用程序,它使用Erlang的gen_fsm模块来管理菜单选项。
当前版本有一个menus_fsm.erl
文件,其中包含5000+行gen_fsm相关代码。我们的下一个版本让我们有机会将menus_fsm.erl
拆分为单独的文件,以便将来更易于维护。
在旧版本中,为了显示帮助菜单,我们执行以下操作(从显示主菜单的未显示代码调用help_menu/1
):
-module(menus_fsm).
% Snipped some irrelvant code
help_menu(StateData) ->
% Display the first menu
send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2"),
{next_state, waitHelpMenuChoice, StateData, ?MENU_TOUT};
waitHelpMenuChoice(Params, StateData) ->
io:format("Got Help menu response: ~p", [Params]),
doTerminate(ok,"Help Menu", StateData).
我遗漏了很多代码,显示了进入FSM的入口点等等。
在新版本中,我们希望将help_menu/1
和waitHelpMenuChoice/2
移动到新模块help_menu
,该模块将从menus_fsm
调用,如下所示:
-module( help_menu ).
% Snipped some irrelevant code
help_menu(StateData) ->
menus_fsm:send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2"),
{next_state, waitHelpMenuChoice, StateData, ?MENU_TOUT};
waitHelpMenuChoice(Params, StateData) ->
io:format("Got Help menu response: ~p", [Params]),
menus_fsm:doTerminate(ok,"Help Menu", StateData).
问题在于行{next_state, waitHelpMenuChoice, StateData, ?MENU_TOUT};
:gen_fsm
期望waitHelpMenuChoice
位于模块menus_fsm
中,这会将我带回到我们开始的位置。
我试图用
替换有问题的行{next_state, fun help_menu:waitHelpMenuChoice/2, StateData, ?MENU_TOUT};
但这只是出现如下错误:
{badarg,[{erlang,apply,[conv_fsm,#Fun<help_menu.waitHelpMenuChoice.2>,[]]}
有没有人对如何解决这个问题有任何建议?
答案 0 :(得分:0)
也许您可以使用http://www.erlang.org/doc/man/gen_fsm.html#enter_loop-6来做到这一点?不确定它是否可以在另一个fsm中调用它,但它可能值得一试。
答案 1 :(得分:0)
我设法找到了解决自己问题的方法。如果这看起来很明显,可能是因为我对Erlang有点新鲜。
我向模块wait_for_menu_response/2
添加了一个新函数menus_fsm
,它代表其他模块处理状态转换。
-module(menus_fsm),
-export([wait_for_menu_response/2]).
% ...snip...
wait_for_menu_response(Params, {Function, StateData}) ->
Function(Params, StateData).
然后help_menu
模块更改如下:
-module( help_menu ).
% ...snip...
help_menu(StateData) ->
menus_fsm:send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2"),
{next_state, wait_for_menu_response, {fun waitHelpMenuChoice/2, StateData}, ?MENU_TOUT}.
waitHelpMenuChoice(Params, StateData) ->
io:format("Got Help menu response: ~p", [Params]),
menus_fsm:doTerminate(ok,"Help Menu", StateData).
所以gen_fsm
在调用menus_fsm
时会保留在wait_for_menu_response
模块中,但wait_for_menu_response
现在可以自由调用help_menu:waitHelpMenuChoice/2
。 help_menu:waitHelpMenuChoice/2
不需要以任何方式进行修改。
实际上,在我的最终版本中,menus_fsm:send_menu
函数已被修改为接受fun waitHelpMenuChoice/2
作为其第三个参数,因此help_menu
函数只会变为:
help_menu(StateData) ->
menus_fsm:send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2",
fun waitHelpMenuChoice/2).
但我认为我上面的解释更好地说明了这个想法。