免责声明:作者是OTP的新手,具有Erlang语法,流程和消息的一些基本知识。
我试图理解Erlang中的行为概念,但是我脑海中浮现出许多问题,使我无法理解像gen_server这样的行为的整个原则。
好的,gen_server的官方文档显示了一个很好的服务器图和三个与Query和Reply箭头相关的客户端: http://www.erlang.org/doc/design_principles/gen_server_concepts.html
但每次我试图进一步理解这个概念时,我都会陷入困境。
我脑子里有许多概念无法构建成一个更大的概念:
我使用以下资源:
我仍处于状态“我们在一个模块中调用一个函数,此函数调用另一个函数,该函数创建一个进程...卡住了”
有没有办法在图表中描述gen_server的概念?如何在视觉上显示客户端和服务器之间的交互流程?(帮助不那么聪明的新手直观地理解这个概念)
例如:http://support.novell.com/techcenter/articles/img/dnd2003080506.gif
UPD:我试图绘制一张我自己的图表,但我仍然没有达到图表中任何连接器的目的:http://postimage.org/image/qe215ric/full/
UPD2:这与我希望看到的类似:http://cryptoanarchy.org/wiki/Worker_patterns(模型)。但是,它没有显示模块,功能和过程之间的交互。
答案 0 :(得分:12)
我没有精确的图解来解释它,但是我有this chapter之后的那个,并且展示了如何从它背后的抽象原理开始构建gen_server。
帮助处理各个组件:
行为本身有点像我之前链接过的章节。它是一个包含许多函数的模块,为您完成所有通用工作:接收消息,定义函数和隐藏协议进行通信等。高级OTP包含用于进行软件升级的特殊消息类型以及用于跟踪选项的特殊代码。
我不确定这应该是什么。也许只是具有行为名称的模块?
在您的行为实现的同一模块中,您必须定义behaviour_info/1
函数。该函数将让Erlang编译器知道在其中有-behaviour(SomeModuleName)
的任何模块都需要一些回调。 SomeModuleName
等同于包含实现和behaviour_info函数的SomeModuleName.erl
(和.beam
)文件。
包含所有特定代码的模块,处理所有自定义内容。
非通用的所有东西都会以YourModule:SomeCall(Args)
的形式委托给回调模块。这些是由您的模块提供的,其中包含-behaviour(gen_server).
行。
如果需要,回调模块有两个接口:一个用于gen_server
行为(init / 0,handle_call / 3,handle_info / 2,handle_cast / 2,terminate / 2,code_change / 3),以及用户的一个(启动服务器,发送一些信息,回复一些信息)。
我可以尝试用那种方式描述
---------------------------------------------------------------------
| some process | server process |
------------------------+--------------------------------------------
[client] | [callback] : [behaviour]
| :
callback:start >-------|---------------------:--> starting the process
| : V
| : |
| init() <-----:-----------`
| | :
| `-----------:------> initial state
{ok, Pid} <----------|---------------------:----------,/
| :
callback:store >------|---------------------:--> handles message
(calls the process) | (formats msg) : V
| : |
| handle_call() <--:-----------`
| | :
| `----------:--> updates state, sends reply
| : V
| : |
gets result <--------|---------------------:--------`
| :
所有通用部分都位于服务器进程的右侧,在行为中,所有特定部分都在左侧(回调)。客户端使用回调模块的API /接口来联系服务器进程并对其产生影响。
您必须将行为视为某种非常通用的代码段,有时会将其执行流程(对于更精确的部分,如接收和发送消息)放弃到特定代码(如何对这些消息作出反应)。 / p>
希望这有帮助。