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