1
<?xml version="1.0" encoding="latin1" ?>
2
<!DOCTYPE chapter SYSTEM "chapter.dtd">
7
<year>1997</year><year>2009</year>
8
<holder>Ericsson AB. All Rights Reserved.</holder>
11
The contents of this file are subject to the Erlang Public License,
12
Version 1.1, (the "License"); you may not use this file except in
13
compliance with the License. You should have received a copy of the
14
Erlang Public License along with this software. If not, it can be
15
retrieved online at http://www.erlang.org/.
17
Software distributed under the License is distributed on an "AS IS"
18
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
19
the License for the specific language governing rights and limitations
24
<title>Overview</title>
29
<file>des_princ.xml</file>
31
<p>The <em>OTP Design Principles</em> is a set of principles for how
32
to structure Erlang code in terms of processes, modules and
36
<title>Supervision Trees</title>
37
<p>A basic concept in Erlang/OTP is the <em>supervision tree</em>.
38
This is a process structuring model based on the idea of
39
<em>workers</em> and <em>supervisors</em>.</p>
40
<list type="bulleted">
41
<item>Workers are processes which perform computations, that is,
42
they do the actual work.</item>
43
<item>Supervisors are processes which monitor the behaviour of
44
workers. A supervisor can restart a worker if something goes
46
<item>The supervision tree is a hierarchical arrangement of
47
code into supervisors and workers, making it possible to
48
design and program fault-tolerant software.</item>
50
<marker id="sup6"></marker>
51
<image file="../design_principles/sup6.gif">
52
<icaption>Supervision Tree</icaption>
54
<p>In the figure above, square boxes represents supervisors and
55
circles represent workers.</p>
59
<title>Behaviours</title>
60
<p>In a supervision tree, many of the processes have similar
61
structures, they follow similar patterns. For example,
62
the supervisors are very similar in structure. The only difference
63
between them is which child processes they supervise. Also, many
64
of the workers are servers in a server-client relation, finite
65
state machines, or event handlers such as error loggers.</p>
66
<p><em>Behaviours</em> are formalizations of these common patterns.
67
The idea is to divide the code for a process in a generic part
68
(a behaviour module) and a specific part (a <em>callback module</em>).</p>
69
<p>The behaviour module is part of Erlang/OTP. To implement a
70
process such as a supervisor, the user only has to implement
71
the callback module which should export a pre-defined set of
72
functions, the <em>callback functions</em>.</p>
73
<p>An example to illustrate how code can be divided into a generic
74
and a specific part: Consider the following code (written in
75
plain Erlang) for a simple server, which keeps track of a number
76
of "channels". Other processes can allocate and free the channels
77
by calling the functions <c>alloc/0</c> and <c>free/1</c>,
79
<marker id="ch1"></marker>
83
-export([alloc/0, free/1]).
90
ch1 ! {self(), alloc},
101
register(ch1, self()),
108
{Ch, Chs2} = alloc(Chs),
112
Chs2 = free(Ch, Chs),
115
<p>The code for the server can be rewritten into a generic part
116
<c>server.erl</c>:</p>
120
-export([call/2, cast/2]).
124
spawn(server, init, [Mod]).
127
Name ! {call, self(), Req},
138
register(Mod, self()),
145
{Res, State2} = Mod:handle_call(Req, State),
149
State2 = Mod:handle_cast(Req, State),
152
<p>and a callback module <c>ch2.erl</c>:</p>
156
-export([alloc/0, free/1]).
157
-export([init/0, handle_call/2, handle_cast/2]).
163
server:call(ch2, alloc).
166
server:cast(ch2, {free, Ch}).
171
handle_call(alloc, Chs) ->
172
alloc(Chs). % => {Ch,Chs2}
174
handle_cast({free, Ch}, Chs) ->
175
free(Ch, Chs). % => Chs2</code>
176
<p>Note the following:</p>
177
<list type="bulleted">
178
<item>The code in <c>server</c> can be re-used to build many
179
different servers.</item>
180
<item>The name of the server, in this example the atom
181
<c>ch2</c>, is hidden from the users of the client functions.
182
This means the name can be changed without affecting them.</item>
183
<item>The protcol (messages sent to and received from the server)
184
is hidden as well. This is good programming practice and allows
185
us to change the protocol without making changes to code using
186
the interface functions.</item>
187
<item>We can extend the functionality of <c>server</c>, without
188
having to change <c>ch2</c> or any other callback module.</item>
190
<p>(In <c>ch1.erl</c> and <c>ch2.erl</c> above, the implementation
191
of <c>channels/0</c>, <c>alloc/1</c> and <c>free/2</c> has been
192
intentionally left out, as it is not relevant to the example.
193
For completeness, one way to write these functions are given
194
below. Note that this is an example only, a realistic
195
implementation must be able to handle situations like running out
196
of channels to allocate etc.)</p>
199
{_Allocated = [], _Free = lists:seq(1,100)}.
201
alloc({Allocated, [H|T] = _Free}) ->
202
{H, {[H|Allocated], T}}.
204
free(Ch, {Alloc, Free} = Channels) ->
205
case lists:member(Ch, Alloc) of
207
{lists:delete(Ch, Alloc), [Ch|Free]};
211
<p>Code written without making use of behaviours may be more
212
efficient, but the increased efficiency will be at the expense of
213
generality. The ability to manage all applications in the system
214
in a consistent manner is very important.</p>
215
<p>Using behaviours also makes it easier to read and understand
216
code written by other programmers. Ad hoc programming structures,
217
while possibly more efficient, are always more difficult to
219
<p>The module <c>server</c> corresponds, greatly simplified,
220
to the Erlang/OTP behaviour <c>gen_server</c>.</p>
221
<p>The standard Erlang/OTP behaviours are:</p>
223
<tag><seealso marker="gen_server_concepts">gen_server</seealso></tag>
224
<item>For implementing the server of a client-server relation.</item>
225
<tag><seealso marker="fsm">gen_fsm</seealso></tag>
226
<item>For implementing finite state machines.</item>
227
<tag><seealso marker="events">gen_event</seealso></tag>
228
<item>For implementing event handling functionality.</item>
229
<tag><seealso marker="sup_princ">supervisor</seealso></tag>
230
<item>For implementing a supervisor in a supervision tree.</item>
232
<p>The compiler understands the module attribute
233
<c>-behaviour(Behaviour)</c> and issues warnings about
234
missing callback functions. Example:</p>
237
-behaviour(gen_server).
241
./chs3.erl:10: Warning: undefined call-back function handle_call/3
246
<title>Applications</title>
247
<p>Erlang/OTP comes with a number of components, each implementing
248
some specific functionality. Components are with Erlang/OTP
249
terminology called <em>applications</em>. Examples of Erlang/OTP
250
applications are Mnesia, which has everything needed for
251
programming database services, and Debugger which is used to
252
debug Erlang programs. The minimal system based on Erlang/OTP
253
consists of the applications Kernel and STDLIB.</p>
254
<p>The application concept applies both to program structure
255
(processes) and directory structure (modules).</p>
256
<p>The simplest kind of application does not have any processes,
257
but consists of a collection of functional modules. Such an
258
application is called a <em>library application</em>. An example
259
of a library application is STDLIB.</p>
260
<p>An application with processes is easiest implemented as a
261
supervision tree using the standard behaviours.</p>
262
<p>How to program applications is described in
263
<seealso marker="applications">Applications</seealso>.</p>
267
<title>Releases</title>
268
<p>A <em>release</em> is a complete system made out from a subset of
269
the Erlang/OTP applications and a set of user-specific
271
<p>How to program releases is described in
272
<seealso marker="release_structure">Releases</seealso>.</p>
273
<p>How to install a release in a target environment is described
274
in the chapter about Target Systems in System Principles.</p>
278
<title>Release Handling</title>
279
<p><em>Release handling</em> is upgrading and downgrading between
280
different versions of a release, in a (possibly) running system.
281
How to do this is described in
282
<seealso marker="release_handling">Release Handling</seealso>.</p>