> Things become problematic when you do not entirely understand the
> abstraction.
> Maybe the abstraction is inappropriate for your needs. I have seen many
> examples
> of code where the gen_server *is* inappropriate. The acid test is "does the
> gen_sever code look like spaghetti" if the answer is yes then all you have
> done
> is shoe horn the applications into an inappropriate form. In this case
> you should ditch the gen_server and roll-your own.
Another problem I often see is that newbies tend to regard gen_server
as something that does magic, and fail to understand how the code runs
in the server and the clients (since that code lives in the same
module, usually).
They end up in solutions with parts of the gen server sending messages
back and forth, putting receives that spoil the abstraction
intercepting messages that gen_server code should be handling,
throwing exits in server code and attempting to catch them in the
client code, blocking servers with heavyweight operations, ...
I really consider advising against using gen_server (or any other
abstraction) until one is able to write a client-server and a
supervisor tree without them so that you can understand what's
happening under the hood of gen_server (which, as you say, it's not
rocket science).
Absolutely.
I think the problem stems from the use of IDEs - in eclipse/Xcode etc you click on
a "new project" button and the system automatically generates a load of crap files
full of incomprehensible undocumented nonsense. This leads to a mentality
of "using stuff without understanding it" - All I ever use is emacs, make and a shell.
Usually I put all the files in one directory. I want to understand *everything*
As IDEs get more and more complex and help you more and more
it gets harder and harder to understand what's really going on.
Graphics programming used to be easy - anybody remember Borlands turbo graphics?
- but now it's far more difficult since you have to fight with all the tools and
frameworks that get in the way and make life difficult.
/joe
Cheers
--
Samuel
I think this is the most confusing design pattern in Erlang:
send(x,y) ->
gen_server:call(?NAME, {send, x, y}).
handle_call({send, x, y}, State) ->
i_send(x, y).
i_send(x,y) ->
...
One always have to keep in mind that actual code he's looking at is in
the client process (send) or server (i_send). Obviously calling send
from i_send in the above example would just lead to a deadlock. Maybe
it would be a nice tool that I could run on a huge codebase and split
these modules into a client and server part...
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions
This is *why* we made the gen_server abstraction. You can write well-typed
sequential code (the handle_call and init functions) to parametrize
a concurrent behavior, ie you need to know nothing about concurrency to
get the job done. We've "abstracted out" the concurrency.
Things become problematic when you do not entirely understand the abstraction.
Maybe the abstraction is inappropriate for your needs. I have seen many examples
of code where the gen_server *is* inappropriate. The acid test is "does the
gen_sever code look like spaghetti" if the answer is yes then all you have done
is shoe horn the applications into an inappropriate form. In this case
you should ditch the gen_server and roll-your own.
The most common form of gen _server abuse I have seen (and I plead guilty of it myself) is attempting to turn it into something akin to a state machine. My rule of thumb is if your state record contains a field called state or something like it and you take different actions based on it, then it's time to re-factor into a gen_fsm. It's easy to get into this situation since things usually start simple and build up once more functionality is piled on.
On the other hand it's far from the functionality of a gen_server,
because e.g. it doesn't send back data to the caller. When you add
this functionality, you essentially reinvent the gen_server.
In other words: gen_server is great to provide safe access to shared
data, maybe it's not so great to control stuff. There's one more great
point in using the gen_* behaviours - they provide usually useful and
detailed crash reports when something goes wrong.
Abstractions aren't very helpful if you don't understand what they're abstracting.
--Kevin
The most common form of gen _server abuse I have seen (and I plead guilty of it myself) is attempting to turn it into something akin to a state machine. My rule of thumb is if your state record contains a field called state or something like it and you take different actions based on it, then it's time to re-factor into a gen_fsm. It's easy to get into this situation since things usually start simple and build up once more functionality is piled on.I don't know about this -- I have written numerous gen_servers whose state-record include a state-field (although I usually call it 'current'), and events (calls, casts, infos) are handled differently depending on its value. The reason for not using a gen_fsm is that very often, an event should be handled in one way in one particular state, and in another way in _all_ other states. This is easy to do using pattern-matching when using a gen_server, but when using a gen_fsm you have no choice but to write out every state/event combination, which can become pretty cumbersome.
On a related note, I have been moving away from using gen_servers all the time. The reason for this is that in a gen_server, the state consists of just the state term. In an arbitrary process, the state actually consists of the process' entire call-stack, and it makes the flow in code such as the almost proverbial:idle() ->receive{ Number, incoming } ->start_ringing(),ringing(Number);off_hook ->start_tone(),dial()end.... much easier to follow than when using a gen_server or gen_fsm.
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions
Strong agreement with everything stated. When I teach an "Intro To Erlang" class I spend a lot of time (lecture and labs) working on the basics before we tackle gen_server. In fact, one of the last labs before getting to gen_server requires the class to write their own server very similar to Joe's code.
Abstractions aren't very helpful if you don't understand what they're abstracting.
On Wed, Apr 20, 2011 at 15:09, Jeroen Koops <koo...@gmail.com> wrote:The most common form of gen _server abuse I have seen (and I plead guilty of it myself) is attempting to turn it into something akin to a state machine. My rule of thumb is if your state record contains a field called state or something like it and you take different actions based on it, then it's time to re-factor into a gen_fsm. It's easy to get into this situation since things usually start simple and build up once more functionality is piled on.I don't know about this -- I have written numerous gen_servers whose state-record include a state-field (although I usually call it 'current'), and events (calls, casts, infos) are handled differently depending on its value. The reason for not using a gen_fsm is that very often, an event should be handled in one way in one particular state, and in another way in _all_ other states. This is easy to do using pattern-matching when using a gen_server, but when using a gen_fsm you have no choice but to write out every state/event combination, which can become pretty cumbersome.
Then one can use an gen_fsm:send_all_state_event/2 and pattern match on both state and state date that in the modules handle_event/3 function.
I have done that many times and it works rather well.
Of course, but when you do that for the majority of the events it amounts to the same as using a gen_server with a 'state'-field, doesn't it?
Hi,
I am saving up for a new laptop to run Erlang. Can't drag my tower around. Two questions:
1 - I want to run Ubuntu. Will Erlang work well with this? (Assuming Ubuntu v10/11)
2 - What's a decent laptop manufacturer/model to run this on? I've always bought Dell in the past, but I am not wed to this manufacturer.
--Peter
I tend to use proc_lib (spawn_link, start_link, init_ack) and sys
(handle_system_msg) a lot. They gives you almost all the bells and
whistles that gen_server has, but it enables you to have the same
simple code structure that you have in your very pedagogic code
snippet below.
/Håkan
PS.
By the way, it seems more appropriate to use spawn_link in a
function called start_link.
I tend to use proc_lib (spawn_link, start_link, init_ack) and sys
(handle_system_msg) a lot. They gives you almost all the bells and
whistles that gen_server has, but it enables you to have the same
simple code structure that you have in your very pedagogic code
snippet below.
Usually, it involves writing your own versions of system_continue/3, system_terminate/4, system_code_change/4, and format_status/2.
BR,
Ulf W
On 21 Apr 2011, at 18:14, Håkan Mattsson wrote:
> I gladly write two lines of code to handle system
> messages, if that enables me to avoid a boring
> template. I really like the simplicity of Joe's code
> snippet. It is easy to understand and does not
> imply any black magic. It is just proc_lib that is
> missing...
>
> /Håkan
>
> PS. You did also have two "boring" lines in your
> template to handle code change.
> --
> Sent from my Android phone with K-9 Mail. Please excuse my brevity.
Ulf Wiger, CTO, Erlang Solutions, Ltd.
http://erlang-solutions.com
_______________________________________________
--
Olivier / http://biniou.net
ASUS laptops work just fine, both in 32 or 64 bits
> Any laptop just about will work. I would suggest you go with something
> that has multiple cores so you get true concurrency off the bat. Just
> about every laptop has that now though.
At the bottom end, I have had occasion to use Erlang on my Asus eee
netbook with 1 Gb of RAM and a single-core Atom processor. (You can get
these for under EUR 200 these days.)
It isn't very fast and I'm very glad it isn't my main development
environment, but it does work OK and it fits neatly into my handluggage
for flights.
Cheers,
Des
--
Des Small,
Scientific Programmer, JIVE
Contact details on http://www.jive.nl/~small
you will have R13B03, and if you try to compile from scratch to get
R14B02, expect to do a bit of work (especially wxwidgets)
You may want to try this:
http://sivieri.wordpress.com/2011/04/08/erlang-r14b02-in-ppa/
if you want R14B02.
I just tried it and it seems to work fine so far.
You can also try this procedure (installing packages) to get R14B02
working on Ubuntu 10.10
http://sites.google.com/site/comptekkia/erlang/how-to-install-erlang-on-ubuntu-10-10
> 2 - What's a decent laptop manufacturer/model to run this on? I've always
> bought Dell in the past, but I am not wed to this manufacturer.
>
>
-wes
> Many users seem to use the gen_server for absolutely everything
> and often force their problems to fit the gen_sever even though the
> gen_server is not appropriate for their problems.
>
> . . .
>
> This is *why* we made the gen_server abstraction. You can write well-typed
> sequential code (the handle_call and init functions) to parametrize
> a concurrent behavior, ie you need to know nothing about concurrency to
> get the job done. We've "abstracted out" the concurrency.
>
> Things become problematic when you do not entirely understand the
abstraction.
> Maybe the abstraction is inappropriate for your needs. I have seen many
examples
> of code where the gen_server *is* inappropriate. The acid test is "does
the
> gen_sever code look like spaghetti" if the answer is yes then all you have
done
> is shoe horn the applications into an inappropriate form. In this case
> you should ditch the gen_server and roll-your own.
I am not sure what you are advocating in gen_server's stead. Some others on
this thread seem to be pushing gen_fsm as the alternative, but I don't think
that's what you are arguing, since you have generally preferred lightweight
non-OTP processes. Are you arguing for more use of gen_fsm, more creation
of roll-your-own OTP-compliant processes using proc_lib and sys, or less
reliance on the OTP framework and more use of plain old Erlang?
> I am not sure what you are advocating in gen_server's stead. Some others on
> this thread seem to be pushing gen_fsm as the alternative, but I don't think
> that's what you are arguing, since you have generally preferred lightweight
> non-OTP processes. Are you arguing for more use of gen_fsm, more creation
> of roll-your-own OTP-compliant processes using proc_lib and sys, or less
> reliance on the OTP framework and more use of plain old Erlang?
I believe I am the one who brought gen_fsm into this discussion.
My intention was to exemplify a particular case of gen_server abuse, one where gen_fsm would have made a lot more sense.
I did not intend to suggest that gen_fsm be regarded as a generic alternative to gen_server, but rather that each abstraction has its own domain of applicability.
Just thought I'd clear any possible misunderstandings.
Mihai
Why is this question even asked? I think it might be because of a lack of
good explanations with lots of reasoning pro / contra per approach.
How is a person learning about OTP supposed to know the implications of
leaving the tested path? Leaving a tested path is generally a bad thing. To
do so you should be aware of the consequences (or whether there even are
any). People lack the knowledge to gauge the consequences. That knowledge is
only gained from experience - which can include writing spaghetti gen_server
code and recognizing it as a mess.
You have that knowledge and that might make it hard for you to comprehend
the impact of uncertainty here.
--
View this message in context: http://erlang.2086793.n4.nabble.com/The-gen-server-simplified-how-it-works-tp3462381p3474996.html
Sent from the Erlang Questions mailing list archive at Nabble.com.
++> Des Small <sm...@jive.nl> [2011-04-22 08:13:56 +0200]: