问题描述
我们有一个相当大的USSD应用程序,它使用Erlang的gen_fsm模块来管理菜单选项。
We have a fairly large USSD application that uses Erlang's gen_fsm module to manage the menu options.
当前版本只有一个 menus_fsm。包含5000多个gen_fsm相关代码的erl
文件。我们的下一个版本使我们有机会将 menus_fsm.erl
拆分为单独的文件,以使其将来更易于维护。
The current version has a single menus_fsm.erl
file that contains 5000+ lines gen_fsm related code. Our next version gives us an opportunity to split menus_fsm.erl
into separate files to make it more maintainable in the future.
在旧版本中,要显示帮助菜单,我们需要执行以下操作(从显示主菜单的未显示代码中调用 help_menu / 1
):
In the old version, to display the help menu we do the following (help_menu/1
gets called from code not shown that displays the main menu):
-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入口点的代码,依此类推。
I've left out a lot of code that shows the entry point into the FSM and so on.
在新版本中,我们希望移动 help_menu / 1
和 waitHelpMenuChoice / 2
到新模块 help_menu
,该模块从 menus_fsm
调用,如下所示:
In the new version, we'd want to move help_menu/1
and waitHelpMenuChoice/2
to a new module help_menu
, which gets called from menus_fsm
, like so:
-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 ,这使我回到了开始的地方。
The problem is with the line {next_state, waitHelpMenuChoice, StateData, ?MENU_TOUT};
: gen_fsm
expects the waitHelpMenuChoice
to be in the module menus_fsm
which takes me back to where we started.
我尝试用$ p $替换有问题的行b
I've tried to replace the problematic line with
{next_state, fun help_menu:waitHelpMenuChoice/2, StateData, ?MENU_TOUT};
但这只会导致如下错误:
{badarg,[{erlang,apply,[conv_fsm,#Fun< help_menu.waitHelpMenuChoice.2>,[]]}
but that just leas to an error like the following:{badarg,[{erlang,apply,[conv_fsm,#Fun<help_menu.waitHelpMenuChoice.2>,[]]}
有人对如何解决这个问题有什么建议?
Does anyone have any suggestions of how to get around this?
推荐答案
我设法找到了自己的问题的解决方案。如果这似乎很明显,那可能是因为我对Erlang有点陌生。
I managed to find a solution to my own question. If this seems obvious, it could be because I'm a bit new to Erlang.
我添加了一个新函数 wait_for_menu_response / 2
到模块 menus_fsm
代表其他模块处理状态转换。
I added a new function wait_for_menu_response/2
to module menus_fsm
that handles state transitions on behalf of the other modules.
-module(menus_fsm),
-export([wait_for_menu_response/2]).
% ...snip...
wait_for_menu_response(Params, {Function, StateData}) ->
Function(Params, StateData).
然后 help_menu
模块进行了如下更改:
Then the help_menu
module was changed as follows:
-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
不需要进行任何修改。
so gen_fsm
stays within the menus_fsm
module when it invokes wait_for_menu_response
, but wait_for_menu_response
is now free to invoke help_menu:waitHelpMenuChoice/2
. help_menu:waitHelpMenuChoice/2
did not need to be modified in any way.
实际上,在我的最终版本中, menus_fsm:send_menu
函数被修改为接受 fun waitHelpMenuChoice / 2
作为其第三个参数,因此 help_menu
函数简单地变为:
Actually, in my final version, the menus_fsm:send_menu
function was modified to accept the fun waitHelpMenuChoice/2
as its third parameter, so that the help_menu
function simply becomes:
help_menu(StateData) ->
menus_fsm:send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2",
fun waitHelpMenuChoice/2).
但我认为以上解释更好地说明了这一点。
but I think my explanation above illustrates the idea better.
这篇关于将gen_fsm状态更改为其他模块中的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!