OTP vs. non-OTP

Martin Bjorklund mbj@REDACTED
Sat Feb 1 22:12:13 CET 2003


Klacke <klacke@REDACTED> wrote:
> On Fri, Jan 31, 2003 at 10:54:01AM +0100, Martin Bjorklund wrote:
> > Klacke wrote:
> > 
> > > >>You would not divide the processes into behaviors? 
> > > > 
> > > > 
> > > > Nope
> > 
> > Oh yes you would and you even do that.
> > 
> 
> Actually I don't even know what a behavior is. If I do indeed
> " divide the processes into behaviors" it is entirely by
> accident.
> 
> 
> So, what is an OTP behaviour  ?

All right, I'll pick it up :)

There are 5 OTP behaviours, gen_server, gen_fsm, gen_event, supervisor
and application.  You can also define your own behaviour, but these
5 are included in OTP.

[I know you use gen_server; you even wrote one of it's predecessors
(you know, the one with the fantastic name 'generic')!]

The idea is that *if* you know that the process you're about to write
matches one of the behaviours, you should use that behaviour.  If you
need something else, fine by me, OTP just provides you with these
behaviours, and hope that you'll find them useful and use them. 

And as Joe said, the behaviours are no rocket-science; the basic idea
behind each behaviour is super-simple - Joe wrote the gen_server one,
here'e the gen_event:

send_event(Pid, Event) ->
   Pid ! {event, Event}.

register(Pid, F) ->
   Pid ! {register, F}.

loop(Funs) ->
   receive
      {register, Fun} ->
          loop([Fun | Funs]);
      {event, Event} ->
          lists:foreach(fun(F) -> F(Event) end, Funs),
          loop(Funs)
   end.

So, an error_logger process could have one fun that writes to the tty,
one that writes to a file and one that sends the msg to a syslog
server.  And it's very easy to add another one that sends an SNMP
notification for some events without modifying the existing code.

Now, by using the OTP behaviours you get a lot of things for free,
e.g. it fits into the OTP concept of an application which can be used
to make your code easily integrated into other peoples projects, it's
pretty well-tested, it reduces your code size, it's easier to read by
other people that know this behaviuor (than pure erlang code with !
and receive (of course a statement like 'easy to read' is very
subjective, but I think most people agree), and it's easier to debug.
E.g. when I need to debug one of our installed systems, I know that I
can do sys:get_status(Pid) even if the process is written by you or
jocke :) to get the internal state of the process.   And I know I can
do sys:trace() (ok, it's not as important now when we have the trace
support in the emulator as it used to be) to see how a specific
message changes the state of a process.

To summarize, if you're relatively new to erlang and you don't really
know if you should use a behaviour or not, you should use it (*).  If
you know what you're doing, and would like to be "OTP-compliant", use
! and receive as you like, and use the proc_lib(3) and sys(3) to
handle system messages.  Otherwise, do whatever you like.

(*) I know that I would _never_ follow such an advice.  I need to make
my own mistakes first :)



/martin



More information about the erlang-questions mailing list