tags:

views:

229

answers:

5

Hi, I've recently finished Joe's book and quite enjoyed it. I'm since then started coding a soft realtime application with erlang and I have to say I am a bit confused at the use of gen_server.

When should I use gen_server instead of a simple stateless module? I define a stateless module as follow: - A module that takes it's state as a parameter (much like ETS/DETS) as opposed to keeping it internally (like gen_server)

Say for an invoice manager type module, should it initialize and return state which I'd then pass subsequently to it? SomeState = InvoiceManager:Init(), SomeState = InvoiceManager:AddInvoice(SomeState, AnInvoiceFoo).

Suppose I'd need multiple instances of the invoice manager state (say my application manages multiple companies each with their own invoices), should they each have a gen_server with internal state to manage their invoices or would it better fit to simply have the stateless module above?

Where is the line between the two?

(Note the invoice manage example above is just that, an example to illustrate my question)

A: 

Having used both models, I must say that using the provided gen_server helps me stay structured more easily. I guess this is why it is included in the OTP stack of tools: gen_server is a good way to get the repetitive boiler-plate out of the way.

jldupont
+1  A: 

If you have shared state over multiple processes you should probably go with gen_server and if the state is just local to one process a stateless module will do fine.

Rickard
+2  A: 

It strongly depend of your needs and application design. When you need shared state between processes you have to use process to keep this state. Then gen_server, gen_fsm or other gen_* is your friend. You can avoid this design when your application is not concurrent or this design doesn't bring you some other benefits. For example break your application to processes will lead to simpler design. In other case sometimes you can choose single process design and using "stateless" modules for performance or such. "stateless" module is best choice for very simply stateless (pure functional) tasks. gen_server is often best choice for thinks that seems naturally "process". You must use it when you want share something between processes (using processes can be constrained by scalability or concurrency).

Hynek -Pichi- Vychodil
+1  A: 

I suppose your invoices (or whatever they stand for) should be persistent, so they would end up in an ETS/Mnesia table anyway. If this is so, you should create a stateless module where you put your API for accessing the invoice table.

Zed
+2  A: 

I don't really think you can make that distinction between what you call a stateless module and gen_server. In both cases there is a recursive receive loop which carries state in at least one argument. This main loop handles requests, does work depending on the requests and, when necessary, sends results back the requesters. The main loop will most likely handle a number of administrative requests as well which may not be part of the main API/protocol.

The difference is that gen_server abstracts away the main receive loop and allows the user to only the write the actual user code. It will also handle many administrative OTP functions for you. The main difference is that the user code is in another module which means that you see the passed through state more easily. Unless you actually manage to write your code in one big receive loop and not call other functions to do the work there is no real difference.

Which method is better depends very much on what you need. Using gen_server will simplify your code and give you added functionality "for free" but it can be more restrictive. Rolling your own will give you more power but also you give more possibilities to screww things up. It is probably a little faster as well. What do you need?

rvirding