Erlang/OTP Forums

Author Message

<  Open Telecom Platform (OTP)  ~  Why use public wrapper functions?

chagan
Posted: Sat Apr 04, 2009 5:02 am Reply with quote
Joined: 04 Apr 2009 Posts: 3
Perhaps one of you experts can explain something to me?

The chat app I'm building starts a gen_server on every client, and a different gen_server on the main server, which is responsible for long term persistence and also for filling in content for absent users (present users distribute their own content and history on request).

Every example I see is structured like this (snippet, obviously):
-export([handle_call/3,etc]).
-export([my_function/1]).

handle_call({my_function,_SomeArgs},_From,State)->
%%Do the actual work here
State.
my_function(SomeArgs)->
gen_server:call(?SERVER, {my_function,SomeArgs}).

My question is, what is the benefit of explicitly exporting my_function, which is a wrapper to the functionality exposed by calling the gen_server? The server can be accessed from other nodes with gen_server:call(GlobalNameForThisServer,{my_function,SomeArgs}) anyway.

Is there some nuance to this indirection that enables hotswapping or something like that? Why double up the declarations like this?

I look forward to being instructed as to why this redundancy is the norm in such a concise and beautiful language.
View user's profile Send private message Send e-mail
mhenoch
Posted: Tue Apr 07, 2009 2:15 pm Reply with quote
User Joined: 06 Nov 2008 Posts: 29
You use the wrapper functions so that other parts of the code do not need to know the internals of the module.

For example, you might at some point decide that the thing that this function does should be done in the process of the caller, not in the gen_server. Or you might decide to use a gen_fsm instead of a gen_server, or you might decide to have several gen_servers, sending requests to a certain server depending on the arguments, etc. If all calls from other modules go through the wrapper functions, the other modules do not need to be changed at all.

Besides, foo:my_function(bar) is shorter than gen_server:call(foo, {my_function, bar}) Smile
View user's profile Send private message
chagan
Posted: Wed Apr 08, 2009 1:36 am Reply with quote
Joined: 04 Apr 2009 Posts: 3
Thanks for your answer, mhenoch. I understand what you mean about hardening the interfaces so that internal changes can take place without other clients needing to adapt.

How would you easily register all the other nodes in the network so that they're addressable in the style of
foo:my_thing(Args)?

I've been trawling through the global module and haven't got a clear picture of how to do it. Say you had fifteen users, each of whom had globally registered themselves with their nickname (by initializing their server with {global,Nick}, and user Foo wanted to call app:message(Msg) on user Bar?
View user's profile Send private message Send e-mail
chagan
Posted: Wed Apr 08, 2009 1:49 am Reply with quote
Joined: 04 Apr 2009 Posts: 3
Oops, missed a closing bracket after {global, Nick}. No wonder my answer wouldn't compile Smile
View user's profile Send private message Send e-mail

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum