0

我们有一个相当大的 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/1waitHelpMenuChoice/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>,[]]}

有人对如何解决这个问题有任何建议吗?

4

2 回答 2

0

也许您可以使用http://www.erlang.org/doc/man/gen_fsm.html#enter_loop-6来做到这一点?不确定在另一个 fsm 中调用它是否可行,但可能值得一试。

于 2012-04-05T12:20:36.417 回答
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/2help_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).

但我认为我上面的解释更好地说明了这个想法。

于 2012-04-05T13:24:41.143 回答