OTP vs. non-OTP

Joe Armstrong joe@REDACTED
Sat Feb 1 20:02:41 CET 2003


On Fri, 31 Jan 2003, Vance Shipley wrote:

> On Sat, Feb 01, 2003 at 11:00:27AM +0100, Eduardo Figoli wrote:
> }  
> }  Should I invest time to learn OTP (patterns)?
> 
> By all means.  
> 
> As has been said here before the sequence of events should be like this:
> 
> 	1) write small example programs using just Erlang
> 
> 	2) write real applications using generic behaviors and if 
> 	   appropriate supervision, application, OAM, etc.
> 
> 	3) spend years being happily productive
> 
> 	4) become purist and write/rewrite your own frameworks
> 

The whole point of OTP was to capture common usage patterns in modules -
forget about the *actual* gen_server and look at the pattern:

Here is a mini gen server

rpc(Pid, Q) ->
	Pid ! {self(), Q},
	receive
		{Pid, Reply} -> Reply
	end.

loop(State, Fun) ->
	receive
	    {swapCode, Fun1} ->
		loop(State, Fun1);
	    {From, Q} ->
		{Reply, State1} = Fun(Q, State),
		From ! {self(), Reply},
		loop(State1)
	end.

This is the *basic* model for all gen_servers: This particular one allows
you to hot swap the code in the server.

One you understand the basic *structure* it's easy to "roll your own"

Here's one that crashes the client if the quert in the server results
in a crash:


rpc(Pid, Q) ->
	Pid ! {self(), Q},
	receive
		{ok, Pid, Reply} -> Reply;
		{oops, Pid, Why} -> exit(Why)
	end.

loop(State, Fun) ->
	receive
	    {swapCode, Fun1} ->
		loop(State, Fun1);
	    {From, Q} ->
		case (catch Fun(S,State)) of
		    {'EXIT', Why} ->
			From ! {opps, self(), Why},
			loop(State);
	    	    {Reply, State1} ->
		        From ! {ok, self(), Reply},
		        loop(State1)	
		end
	end.

This one gives you "transaction semantics" in the server - i.e. it loops
with State is the transaction failed, ok State1 if it worked.

Note that *once you have understood the basic idea* (which is pretty
simple) - all the rest follows naturally.

This explains my earlier posting - I *always* roll my own - as you can see
from the previous examples this is pretty easy.

The gen_server is just a *particular set of choices* for
error-trapping, code swapping etc. - we hoped it would be generally useful -
but it is *not* a universal panicea. Stick with the underlying patterns
and you'll end up writing much prettier code

<aside>
Erlang started by modify the "solve" pattern in prolog:

solve(true).
solve((A,B)) :- solve(A),solve(B).
solve(A)     :- clause(A,B),solve(B).

I mucked around with this adding small things (like concurrency and error
handling :-) until the changes became a language in its own right.

The basic power of prolog came from this simple pattern which can be
modified in countless ways
</aside>

Moral: *understand* the basic patterns involved and then "roll you own" for
the problem domain in question.

/Joe

> 
> If you're writing a filter or file parser or tax calculator then keep
> it simple and just write some Erlang.  If you're writing an application
> which is going to be turned on and run for a while like an SMTP daemon, 
> web server, instant messaging server, directory server, etc. then use
> the design principles and package and run it as an embedded system (*).
> 
> 	-Vance
> 
> (*) until you have reached 4 in above
> 




More information about the erlang-questions mailing list