An Integrated Approach
to
System Implementation
Minor Thesis in Computer Science
at
Linköping University
S-581 83 Linköping, Sweden
Supervisors:
Professor Fergus O'Brien, RMIT
Doctor Lin Padgham, RMIT
Doctor Nahid Shahmehri, LiTH
Reg nr: LiTH-IDA-Ex 96XX
I
Abstract
Erlang is a functional programming language for large industrial real-time
systems. The language provides mechanisms to implement concurrency and
has a declarative syntax. Erlang can model a class-based language supporting
abstraction, information hiding, modularity, dynamic binding, and polymor-
phism; the concepts associated with object orientation.
This thesis describes a way from thinking about a problem to an implemen-
tation in an integrated fashion. That is, a bridge from an object-oriented
analysis and design to an implementation in Erlang. The bridge is illustrated
with an example. Reuse, maintenance and efficiency aspects are discussed. It
is found that Erlang is well suited as implementation language for an object-
oriented design.
II
Acknowledgements
I would like to thank the many individuals who have made this thesis possi-
ble. I especially want to thank my supervisor Professor Fergus O'Brien, the
staff at the Software Engineering Research Centre (SERC), and the Ad-
vanced Services Applications Centre (ASAC) for support, enthusiasm and
constructive advice. I want to thank Doctor Lin Padgham for taking me under
your wing and assisting me during the work on the thesis. I want to thank
Doctor Nahid Shahmehri for having confidence in me and helping me in ar-
ranging my stay in Australia.
Melbourne
April 1996
III
Preface
Directions to the reader
Chapter 1 presents the background and the outline of the thesis. Chapter 2
gives an overview of the Erlang language, concepts concerning it, program
examples, and the author's reflections on Erlang. Chapter 3, describes the
main phases in Rumbaugh's Object Modelling Technique and a design ex-
ample leading to an implementation of an automatic teller machine in Erlang.
In Chapter 4 the example is analysed, followed by discussion and conclu-
sions in Chapter 5.
The steps in Rumbaugh's Object Modelling Technique are listed in
Appendix A. Supplementary design to the automatic teller machine and its
Erlang code is given in Appendix B.
Typographic Conventions
Code is written in this font. When a concept is introduced or a word is em-
phasised it is written in this style.
Contents
IV
Contents
1 Introduction .............................................................................. 1
1.1 Objects as Processes ............................................................................................6
1.2 Keisu ....................................................................................................................7
Static passive private objects ......................................................................................8
Static passive shared objects ......................................................................................9
1.3 Subsystems ........................................................................................................10
1.4 Discussion .........................................................................................................11
2 Erlang ...................................................................................... 13
2.1 Background .......................................................................................................14
PLEX ........................................................................................................................16
2.2 Characteristics of Erlang ...................................................................................17
2.3 Program Examples ............................................................................................20
2.4 Reflections on Erlang ........................................................................................21
The language ............................................................................................................22
The programming environment ................................................................................23
3 Object-Modeling Technique ................................................. 25
3.1 OMT ..................................................................................................................25
3.2 ATM ..................................................................................................................26
3.3 Analysis .............................................................................................................27
Object Model ............................................................................................................28
Dynamic Model ........................................................................................................29
Functional Model ......................................................................................................32
3.4 System Design ...................................................................................................33
3.5 Object Design ....................................................................................................34
3.6 Implementation - Hobbins ..............................................................................36
Init .............................................................................................................................37
Running ....................................................................................................................37
Stopping ....................................................................................................................38
Other .........................................................................................................................39
Contents
V
4 A Development Technique for Erlang ................................. 40
4.1 Object Design ....................................................................................................41
4.2 Implementation in Erlang ..................................................................................44
Class Manager ..........................................................................................................44
Active classes ...........................................................................................................45
Inheritance ................................................................................................................47
Association ...............................................................................................................48
Passive classes ..........................................................................................................49
4.3 Discussion .........................................................................................................50
5 Discussion and Conclusions .................................................. 52
Reuse ........................................................................................................................52
Maintenance .............................................................................................................53
Efficiency .................................................................................................................53
Psychological aspects ...............................................................................................53
Measurements ...........................................................................................................54
Future work ..............................................................................................................55
Conclusions ..............................................................................................................55
6 References ............................................................................... 56
6.1 Books and papers ...............................................................................................56
6.2 WWW Sources ..................................................................................................58
6.3 Other Sources ....................................................................................................58
7 Glossary .................................................................................. 59
A OMT ........................................................................................ 61
A.1 OMT ..................................................................................................................61
A.2 Analysis .............................................................................................................62
Object Model ............................................................................................................62
Dynamic Model ........................................................................................................62
Functional Model ......................................................................................................63
Refining ....................................................................................................................63
A.3 System Design ...................................................................................................64
A.4 Object Design ....................................................................................................64
Obtain operations for the object model ....................................................................65
Design algorithms .....................................................................................................65
Optimize access paths to data ...................................................................................66
Adjust class structure ................................................................................................66
Contents
VI
Design implementation of associations ....................................................................66
A.5 Implementation ..................................................................................................66
B ATM Design and Code .......................................................... 67
B.1 Class specifications ...........................................................................................67
B.2 Erlang Code .......................................................................................................71
Index 88
Contents
VII
1
1 Introduction
This chapter gives an introduction, background, and outline to the thesis.
Software development is by far the largest part of the design costs of telecom-
munication products. For example, 62 million lines of PLEX1 source code
have been written for the Ericsson's AXE-102 telephony switching system.
An operational AXE-10 telephone exchange, typically, contains between
five and ten million lines of source code. Reducing the cost of software de-
sign, improving quality, and cutting time to market are thus of high impor-
tance. Computer Science research at Ericsson has concentrated on these goals
for many years. In 1982 Ericsson's Computer Science Laboratory started
evaluating a number of existing programming languages in a prototype te-
lephony environment. They concluded that the shortest and clearest pro-
grams were written in functional and declarative languages. Experience
gained in the development of PLEX and telephony in general resulted in the
identification of the following desirable characteristics: concurrency, change
of code in a running system, programming error recovery, no pointers, mod-
ular structure, and no global data.
Operating systems like UNIX encapsulate concurrency in processes. UNIX
processes are currently regarded as relatively expensive in terms of system
resources. Extensive work is being conducted in the area of light weight proc-
esses and threads. Languages like Ada provide mechanisms which exploit
heavy weight processes provided by an operating system. Ada uses the task
concept to encapsulate concurrency. In telephony it is beneficial to have mas-
sive concurrency but the cost of implementing massive concurrency in lan-
guages like Ada carries a large overhead. The costs make light-weight
1. PLEX - A programming language developed for the AXE-10, see page 16 for a description.
2. AXE-10 - Ericsson's digital switching system for public telecommunications
Chapter 1: Introduction
2
concurrency highly desirable. The Ericsson Computer Laboratory's research
resulted in a new programming language which they have called Erlang, after
the Danish mathematician (or Ericsson Language) [Ahlberg 1993], [Däcker
1993], [Erlang overview].
Erlang is a functional language developed by Ericsson and introduced to the
public market in 1993. The language provides mechanisms to implement
concurrency and has a declarative syntax. Parallel activities can be pro-
grammed directly in Erlang using facilities built into the language. Erlang
processes are lightweight processes, that is, they require little memory. Fur-
thermore, creating and deleting processes and message passing require little
computational effort. An Erlang process is a self-contained, separate unit of
computation which exists concurrently with other processes in the system. It
can be considered as an object that lives an autonomous life with its own code
and data, which can only be communicated with through messages to and
from the object (process). Henceforth a process will denote an Erlang proc-
ess.
Procedural languages, such as, C++, PLEX, and Pascal, dominate program
development at Ericsson. Experience gained from the introduction of PLEX
indicates that development methodologies must be carried over into pro-
grams written in a new language. Rapid uptake of the language and minimis-
ing the cost of cross-training is achieved by retaining proven design
techniques. Requiring significant changes in approaches to design results in
experienced staff working less efficiently and having to be cross-trained for
a long period of time. A worse consequence is that the experienced staff will
be assigned new responsibilities and their know-how be lost or not utilised.
The transition from a procedural language to a functional language with a de-
clarative syntax can be difficult at first, as it introduces another way of think-
ing. Once a pattern of solving problems has been learnt it is difficult to
change. A way to make this step easier is to retain a proven design technique
and to supply an approach for implementation in Erlang. Much of Ericsson's
development is based on modules and objects. In Ericsson a top-down func-
tional decomposition followed by grouping into cohesive and loosely cou-
pled modules is used when designing for PLEX. This procedure encompasses
the notion of information hiding and modularity (discussed on page 4). Ob-
ject-oriented development builds on techniques already existing in the com-
pany thus making the transition to Erlang easier.
Chapter 1: Introduction
3
Interest in object-orientation in analysis, design, and implementation in soft-
ware development is growing. Object-oriented development views the sys-
tem as a collection of objects. The system state is decentralised and each
object manages its own state information. Object-oriented development puts
emphasis on modelling the problem domain, information hiding, and inherit-
ance.
Practitioners of object-orientation claim the following features and advantag-
es [Booch 1994] [Sommerville 1992] [Yourdon 1994]. Object-oriented de-
velopment encourages the reuse of both software and of entire designs thus
reducing development costs. Integration is spread out over the life cycle rath-
er than occurring as one major event; thus mistakes in the design can be iden-
tified earlier in the development life cycle. Object models are more
compatible with the workings of human cognition. Humans find thinking in
terms of objects to be more natural than thinking in terms of functions. In
many application areas there is a clear mapping between real-world entities
and their controlling objects in a system. Objects may be understood and
modified as stand-alone entities, improving the understandability of the de-
sign. Maintenance of the system is made easier as the objects are independ-
ent. Changing the implementation of an object or adding services does not
affect other system objects. Despite all these claimed benefits the share of
projects carried out with object-oriented techniques is still rather small
[Yourdon 1994] and many of the benefits still need to be proven. But Your-
don asserts: "Object-Orientation is likely to become such a pervasive tech-
nology that we cannot escape it."
According to [Wegner 1987] an object-oriented language supports:
1. objects
2. classes
3. inheritance
Wegner further defines an object-based language to be a language that only
supports objects and a class-based language to be a language that only sup-
ports objects and classes.
An object consists of a state that remembers the effect of the operations.
Communication between objects is performed through message passing. A
class is a template from which objects may be created.
Chapter 1: Introduction
4
Figure 1.1 Wegner's language taxonomy
Inheritance is a mechanism for sharing and reusing code between classes. In-
heritance defines a hierarchy among classes in which a subclass inherits from
one or more generalised superclasses. Erlang does not explicitly support ob-
jects, however, classes can be easily modelled. An object can be modelled as
an Erlang process that has an internal state and a number of operations that
can act upon the data in the process. When a process is spawned it starts ex-
ecuting a function with a set of initial parameters. Thus a function may be re-
garded as a template, that is, a class from which objects (processes) are made.
Erlang does not explicitly support inheritance, however, it too can be mod-
elled. Section 1.1 deals with the costs associated with modelling inheritance.
Hence, Erlang can easily behave as it were a class-based language and, for a
cost, as an object-oriented language.
Abstraction, information hiding, modularity, dynamic binding, and polymor-
phism are identified as important concepts in object-orientation [Booch
1994], [Rumbaugh 1991], [Yourdon 1994]. Abstraction allows complex re-
ality to be represented in terms of a simplified model. Abstract data types are
handled through tuples and lists in Erlang. Data abstraction is the separation
of an object's specification from its body. The specification is the visible part
of the object and defines the operations that may be performed on the object.
The body of the object, its internal part, is hidden from other objects. Data
abstraction is handled through modules in Erlang. Information hiding, or en-
capsulation, is based on the principle that programmers should have only
controlled access to a data item. It enables the underlying implementation to
be changed without the knowledge of the user. Information hiding is handled
through processes in Erlang. If a function is exported from a module it can be
invoked from the outside but without knowledge of the actual implementa-
objects
classes
inheritance
object-oriented
class-based
object-based
Chapter 1: Introduction
5
tion. Abstraction and information hiding are complementary concepts: ab-
straction focuses on the observable behaviour of an object, whereas
information hiding focuses on the implementation that gives rise to this be-
haviour. Modularity is the property of a system that has been decomposed
into a set of cohesive and loosely coupled modules. Coupling is the degree of
connectivity between modules. Low coupling between modules is desirable.
Cohesion identifies the strength or unity within a module. High cohesion is
desirable. Erlang provides support for modularity with its module construct,
however, the grouping of functions into the modules is controlled by the de-
veloper. Erlang has dynamic binding, or late binding, which means that bind-
ing of variables and expressions is not made until the item designated by the
name is invoked. Variables do not have type declarations in Erlang and hence
may take any value. Therefore type errors are found at execution time. Poly-
morphism is the property that an operation may behave differently on differ-
ent types of objects. A single name (such as a pattern declaration) may denote
objects of different types that are related by some common superclass. Any
object denoted by this name is therefore able to respond to some common set
of operations. Polymorphism is intrinsic to Erlang as Erlang has dynamic
binding and pattern matching of arguments. This means that a function can
work on and recognise different types of objects. See the Erlang `member'
function on page 21 for an example on polymorphism.
Object-oriented development is of interest because of its claimed benefits: re-
use, understandability, and maintainability. Erlang can model a class-based
language supporting abstraction, information hiding, modularity, dynamic
binding, and polymorphism; the concepts associated with object-orientation.
Thus it can be assumed that Erlang would be suited for an object-oriented de-
velopment technique. Object-oriented development fits with the characteris-
tics of telephony and Ericsson's existing development techniques, and has
potential to make the transition from procedural languages to Erlang easier.
The following three approaches to object-orientation for Erlang will be
looked at in the rest of this chapter, followed by a discussion.
1. All objects implemented as Erlang processes [Skagervall 1993].
2. Concurrent objects implemented as processes and static objects imple-
mented as functions [Keisu 1995].
3. Objects grouped into subsystems, which are implemented as Erlang
processes [Hobbins 1995].
Chapter 1: Introduction
6
1.1 Objects as Processes
Skagervall suggests a direct mapping from an object-oriented design to
Erlang in [Skagervall 1993]. The notion of classes and inheritance in Erlang
can be programmed by:
* Each class being implemented by a module whose name is the same as
the class name.
* An instance of a class is represented by an Erlang process and the in-
stance identifier is the Pid of that process.
* Sending a message to an object is implemented by sending a message to
the object process.
[Skagervall 1993] lists several examples.
When an operation is inherited, that is, not contained within the object itself,
the object forwards the message representing the requested operation to the
process representing the immediate superclass. When the operation is located
it is applied to the object and the result is passed back down the inheritance
chain, see Figure 1.2.
Figure 1.2 Example of operation resolution
This technique can require a large number of processes. Keisu in [Keisu
1995] points out there would be a "significant overhead of memory." Al-
though, Erlang processes are less expensive than UNIX processes there is
still a significant overhead associated with them. Furthermore, Klas Eriksson
Super-superclass
Superclass
Object
Operation ?
Operation ?
Result
Result
Operation
Chapter 1: Introduction
7
[Eriksson 1996] at Ericsson Software Technology AB declares that "It will
hardly ever be realistic to represent every object [in an object model] as a
process." Furthermore, the mechanism for operation resolution, with messag-
es passed through the inheritance chain, requiring context switches, is less ef-
ficient than the function call mechanism and can be expected to be costly in
terms of execution time if the inheritance tree is deep.
1.2 Keisu
In Keisu's object-orientation model for Erlang [Keisu 1995] concurrent ob-
jects are implemented as Erlang processes and static objects are implemented
as functions.
Booch identifies two types of objects [Booch 1994]: active and passive. An
active object is an object that encompasses its own thread of control whereas
a passive object does not. An active object is generally autonomous. A pas-
sive object's operations are called by active objects. Keisu calls the passive
objects static passive objects and divides them into two groups: private and
shared objects. Keisu uses the term concurrent objects to indicate active ob-
jects that have a process assigned to the object. The concurrent objects trans-
late directly into Erlang processes.
Figure 1.3 Object types in Keisu's model
Static passive objects
Shared objects
Concurrent objects
Private objects
Objects
Chapter 1: Introduction
8
Static passive private objects
A private object is used to hide information. It provides an interface to its op-
erations, which are implemented as clauses. The state of the object is mod-
elled as a parameter.
An example of a generic class:
class(Operation, Arguments, State) -> {ReturnValue, NewState}
The classes have a consistent interface for the operation, arguments, and the
state. They return a tuple with a return value and a new state. When an object
of the class is created the following function is called:
New_object = class(new, Arguments, _).
(The underscore "_"indicates a "don't care" condition. It is used because the
state is not defined before the object is created). Below is an example of how
a generic class would be implemented [Keisu 1995]:
-module(class).
-export(class/3).
-import(parent, [parent/3]).
class(new, Args, _) ->
{MyArgs, ParentArgs} = Args,
{ParentRet, NewParent} = parent(new,ParentArgs,
dummy),
{my_ret_value, {set_mine(MyArgs), NewParent)};
;; ... local operations ...
class(Operation, Args, State) ->
{Myself, Parents} = State,
{ReturnValue, NewParent} = parent(Operation, Args,
Parents),
{Ret, {MySelf, NewParent}}.
The first operation new instantiates the class, initialises its state, and calls the
parent (superclass) to instantiate the parent class, which in turn may call on a
parent until the top level is reached. The following operations are the required
Chapter 1: Introduction
9
operations for all static passive classes. The last clause has arguments that
will match any calling argument and hence, is evaluated if an operation is not
found in the class. The last clause calls the parent class with the state required
by the parent class. This is similar to the resolution of operations in
Figure 1.2. This mechanism has functions calling functions instead of Erlang
processes sending messages. Function calls require less effort than passing
messages between Erlang processes. After the operation has been applied to
the state the result is passed back down the inheritance chain to the object.
Keisu describes the implementation of overloading, single inheritance and
multiple inheritance. Keisu's method provides data abstraction, interface sta-
bility and information hiding for the object's data. It does not provide type
control. If a class is called with an object that is not an object of that class
there will not be an error unless the state definition clashes with the definition
of the class. It would be desirable to have the data and the operations con-
tained within the object and only accessible through message passing.
Static passive shared objects
Occasionally it is desirable to share an object. An example of when a shared
object is required is a port to a resource which must be accessed by several
classes. Since Erlang has single assignment it is not feasible to implement
state as a parameter in this case. Keisu asserts that Erlang processes were in-
tended to be used for elements holding an internal state and interacting asyn-
chronously with the environment, and not with a single user. Synchronous
communication, which is desired in the example of a port, can be implement-
ed using asynchronous communication but the drawback with such an ap-
proach is that the process requesting service must wait for the reply.
Instead Keisu proposes the use of an event-driven programming style, where
programs are written to asynchronously await messages. Hence, abolishing
static passive shared objects and replacing them with Erlang processes and
another programming style. Then, Keisu says, the Erlang processes can be
used as they were intended.
Chapter 1: Introduction
10
1.3 Subsystems
At the Second Erlang User Conference Tony Hobbins [Hobbins 1995] pre-
sented a subsystem model he had used for a prototype implementation in
Erlang of a real-time system.
Hobbins used a standard object-oriented design methodology to design a sub-
system of the real-time problem to be solved. The subsystem responsibilities
were assigned and signals were identified. The object-oriented design meth-
odology consisted of going to one layer of decomposition of objects, that is,
finding `large' objects and then grouping them into subsystems. No finer ob-
ject decomposition was made and classes and inheritance were not taken into
account. After that a generic framework for implementing subsystems in
Erlang was designed. Each subsystem was modelled as a single Erlang proc-
ess. The subsystem model has three meta states:
1. init
2. running
3. stopping.
The init meta state consists of: initialisation routines, start-up confirmation
and synchronisation with other objects. The running meta state embodies the
subsystem behaviour and has an event loop (also called select or receive
loop) for messages. The stopping meta state consists of termination routines.
In the running meta state, the subsystem is executing its specified responsi-
bilities and communicating with other subsystems. Subsystems interacting
asynchronously in the running state implement the required system behav-
iour through finite state machines.
An overall process `System Manager' is responsible for managing the sub-
systems. Its responsibilities are to initiate and terminate subsystem execu-
tion; detect subsystems exiting by trapping the exit condition; handle alarms
and events; support user interaction with the system through a management
interface. At present the Hobbins' subsystem model has not been document-
ed and analysed further.
Chapter 1: Introduction
11
1.4 Discussion
The approach of implementing object-orientation on Erlang representing all
objects implemented as processes is appealing. Objects would be true ob-
jects: they are encapsulated, and their state and operations are contained with-
in the object itself. The overhead of having a process for each object is a
significant drawback. Keisu's model takes this problem into account and di-
vides objects into concurrent and passive objects. Static passive private ob-
jects are implemented as functions hiding information thus reducing the use
of processes. The disadvantage with Keisu's model is that it restricts the way
object-orientation is used by requiring an event-driven approach be used in-
stead of the static passive shared objects. Furthermore, there is no type con-
trol for passive shared objects.
I aim for to find an efficient way to go from an object-oriented design to an
implementation in Erlang. Efficiency is taken to mean: that programmers will
be able to use it without difficulty, there will not be any reduction of speed of
the program, or increase in memory usage when compared with a functional
design. It is not feasible to implement all the objects as Erlang processes due
to the costs associated with large numbers of Erlang processes [Eriksson
1996]. The alternative is to use function calls for some of the objects and to
find other ways of representing objects in Erlang. A balance between one ob-
ject per Erlang process and more than one object per Erlang process is re-
quired (Figure 1.4).
Figure 1.4 The number of objects per Erlang process
Identifying an optimal ratio is unlikely to be possible, especially since every
application is different. My objective, however, is to find a logical and coher-
ent way to decide when to use an Erlang process for an object and when to
use another mechanism.
Since Erlang can model a class-based language it appears as if the subsystem
approach of Hobbins could be used to go from object-oriented analysis and
design to implementation in Erlang. In other words, standard object-oriented
1 Object/Process >1 Objects/Process
Chapter 1: Introduction
12
techniques can be used and I describe a bridge from the design to an imple-
mentation in Erlang where classes are grouped into larger entities which are
implemented as Erlang processes. An implementation of an object-oriented
design will be shown in Chapter 3, followed by a generalisation of the results
in Chapter 4 and a discussion of the results in Chapter 5.
13
2 Erlang
This chapter gives a background to the development of Erlang, characteris-
tics of the language, examples of Erlang code, and reflections based on the
author's experiences with Erlang.
Erlang is a concurrent functional programming language for large industrial
real-time systems, influenced by Prolog, Strand, Parlog and Eri-Pascal (Pas-
cal extended with modules and features for concurrency). It has a pattern
matching syntax, which makes it a declarative language. Erlang has explicit
concurrency with asynchronous message passing. A module system allows
division of large programs into sets of modules. The language is weakly
typed and relatively free from side effects. Erlang is a symbolic programming
language with dynamic memory allocation and real-time garbage collection.
It is a single assignment language. There are built-in primitives for detecting
run-time errors. It has facilities for dynamic code replacement, that is, change
of code in running real-time system, without stopping system. Erlang has in-
terfaces to a number of foreign languages and it supports recursion equations.
The only mechanism for iteration is through recursive calls. Last call optimi-
sation is used to allow recursive functions to be evaluated in constant space.
Erlang has a transparent cross-platform distribution and supports distributed
programming. There are no pointers in Erlang.
The goal of the designers of Erlang was to "... produce a small, simple and
efficient language suitable for programming robust large-scale concurrent in-
dustrial applications." [Armstrong 1993].
Chapter 2: Erlang
14
2.1 Background
This section gives a background to Erlang and PLEX, which is Ericsson's
predecessor to Erlang for programming telephony exchanges. The subsection
about PLEX is not crucial for understanding the rest of the report but it puts
Erlang into a perspective.
Here is an extract from [Erlang overview] "Real-time systems have often
lagged behind other systems in the introduction of new technology. Indeed,
many real-time systems are still programmed using assembly languages. A
number of languages have, however, been developed specifically for pro-
gramming concurrent real time systems. Ada and Modula2 are perhaps the
best known. Declarative programming languages such as Prolog or ML are
now used for a wide range of industrial applications. Their use has resulted
in dramatic reductions both in the volume of source code and the effort re-
quired to design and maintain applications. These languages are not primarily
designed for use in concurrent real time systems. Erlang combines important
ideas from declarative languages with constructs to support concurrency, dis-
tribution and error detection to form a small but extremely powerful language
for programming concurrent real-time systems." The origins of Erlang are
summarised in Figure 2.1.
Figure 2.1 The origins of Erlang. Picture courtesy of [Erlang overview].
Chapter 2: Erlang
15
The main core in the Erlang programming environment is the Erlang run-
time system, also referred to as the kernel. It lies on top of the operating sys-
tem and must be run on all the machines in the network, see Figure 2.2.
Figure 2.2 Overview of the Erlang programming environment.
Picture courtesy of [Erlang overview].
Thus the operating systems and the computers can vary. On top of the Erlang
kernel are the Erlang software modules. Apart from the compiler there is an
interpreter, editor, debugging tools, module libraries etc. available, none of
which will be described further here.
The Erlang Tools have been designed for client/server applications, distrib-
uted real-time control systems, and telephony switching systems. An exam-
ple of a distributed non-homogeneous network is shown in Figure 2.3. Every
machine is running an Erlang kernel but on different architectures.
Figure 2.3 Type application for Erlang: A distributed non-homogeneous network of
computers. Picture courtesy of [Erlang overview].
Chapter 2: Erlang
16
PLEX
Ericsson's AXE-10 telephony switching system is written in the language
PLEX. When PLEX was developed in the late 1960's Ericsson had an exist-
ing expertise in technology, such as relays and switches, and Ericsson wanted
to be able to reuse that expertise. Hence cross-training for these people into
the new language should be possible. Previously all programming of switch-
es had been done in assembler code. PLEX is a procedural language from the
Algol family of languages, for example, Fortran and Pascal. PLEX was spe-
cially designed for a modular construction.
PLEX is hardware-based and built on a modular structure with physical soft-
ware abstraction plug-in blocks. The modules are fully encapsulated and hide
their information. The modules talk to each other through a general message
passing mechanism: send and receive constructs. A module is 64 kB and con-
tains both code and data. A small reference store contains the start address to
each module's code and the start address to its data. There is no global data
in PLEX. Signals are hardware supported. The interface back-end to PLEX
is independent so it does not matter if there is a module or a piece of hard-
ware on the other side. Debugging is done both in the software and the hard-
ware. In the hardware it is made by physically putting probes in the system
to monitor the messages between objects. It is possible to send and receive
data to and from the block during hardware debugging. New versions of a
module can be put into a running system. If the result is undesirable the old
module can be rolled back to an earlier, working version of the module.
PLEX is very well defined and does not have shared memory. PLEX has
pointers but they can only operate within the module. The only memory en-
tity is the module. Having all the data in RAM means no mismatches or re-
storing logging. The modules are protected by battery backups. All long term
store, for example program backups, goes through the IO module which op-
erates disc drives. PLEX is a stable, fast programming environment and easy
to change. The hardware supported interface made it easy to switch to digital
hardware because the PLEX code did not have to be changed. One of the
problems with the previous architecture, AKE, was that it was wide open and
not a black box machine, like PLEX. When PLEX was designed this and oth-
er problems from AKE were taken under consideration.
Chapter 2: Erlang
17
2.2 Characteristics of Erlang
This section describes the characteristics of Erlang. The majority of the ma-
terial is based on [Armstrong 1993], [Bird 1988], [Erlang], and [Erlang Sys-
tems].
A real-time system is an interactive, often complex, system with time con-
straints. The system has independent streams of input events and it produces
multiple outputs. The input may vary significantly and be unpredictable.
Real-time systems generally have concurrent processing. There are two types
of real-time systems: hard and soft. A hard real-time system has critical dead-
lines to meet, whereas for a soft real-time system it is desirable that the dead-
lines be met, but it is not fatal if they are occasionally missed. Typical
applications for real-time systems include: process control, device control,
data acquisition, overload relays and communication devices. Erlang is de-
signed for programming soft real-time systems where response times are in
the 5-15 ms. range.
Imperative programming is based on a sequence of commands that update
variables held in storage. Examples of imperative languages are Ada, Pascal,
and C++. Structured programming is programming without using goto state-
ments, programming using only while loops and if statements as control con-
structs and designing using a top-down approach.
Functional programming is a style of programming that emphasises the eval-
uation of expressions, rather than execution of commands. The expressions
are formed by using functions to combine basic values. Programming in a
functional language involves building definitions and using the computer to
evaluate expressions. In a strict functional language, the arguments to a func-
tion are always evaluated before it is invoked. As a result, if the evaluation of
an expression expr does not terminate properly (for example, because it gen-
erates a run-time error or enters an infinite loop), then neither will an expres-
sion of the form f(expr). ML and Scheme are both examples of this. In a non-
strict language, the arguments to a function are not evaluated until their val-
ues are actually required. For example, evaluating an expression of the form
f(expr) may still terminate properly, even if evaluation of expr would not, if
the value of the parameter is not used in the body of f. Miranda and Haskell
are examples of this approach. Erlang is a strict functional language. Lazy
evaluation means that the argument is evaluated only when it is first needed.
Chapter 2: Erlang
18
Declarative programming identifies what you want to do in contrast to im-
perative programming, which tells you explicitly how to do it. In declarative
programming the programmer specifies the logic and the machine takes care
of the control. Examples of declarative languages are Prolog and Parlog. Dis-
tributed programming involves the programming of applications that can run
simultaneously on several computers, in a network. Erlang supports distrib-
uted programming. In an event-driven sequential system, control resides
within a dispatcher or monitor provided by the language or operating system.
Erlang has a process-based model of concurrency with asynchronous mes-
sage passing. The process lives its own life after it has been spawned. In
Erlang processes are light-weight, which require little overhead memory, cre-
ating and deleting processes and message passing require little computational
effort (compared to for example UNIX processes).
Erlang has primitives which allow code to be replaced in a running system,
dynamic code replacement, and allow old and new versions of code to exe-
cute at the same time. The implementation for Erlang has two "slots" for
code. The first one is for the running module of code and the second one for
code to be "shifted" in. A robust system remains operational, either complete-
ly or in degraded mode, even in the presence of unforeseen faults or events
coming from the environment. Erlang provides three built-in mechanisms for
dealing with errors, which also work in distributed environments.
Memory allocation is not done by the programmers in Erlang and conse-
quently they do not need to free unused memory. There are no pointers in
Erlang, so memory leaks cannot occur. The Erlang garbage collector frees
unused memory according to real-time garbage collection techniques. Real-
time garbage collection means that the garbage collection is done in small
portions. The important feature is that the system is not stopped to execute
the garbage collection. Stopping the system would mean that events would
be subjected to long delays before they would get access to the processor.
Erlang is a symbolic language, which means that the programmer does not
need to specify how data is represented in the computer. Memory manage-
ment is done in the implementation of the language and not by the program-
mer.
Erlang has single assignment meaning that once a variable has been bound
with a value, it can not be rebound. Variables start with an upper-case letter.
Chapter 2: Erlang
19
Every Erlang process has a process dictionary, which is local to the process.
The dictionary is empty when an Erlang process is spawned. We can add a
new value by put(Key, Value) and fetch the value with get(Key). The
process dictionary allows the usage of global (although, local to the process)
data if many functions within the process need to access the same data. The
process dictionary should be used with care as it introduces destructive oper-
ations.
The Erlang atoms are constants with names. They start with a lower-case let-
ter or they are enclosed in single quotes, for example:
apple
`A quoted atom with blanks'
Erlang lists are structures used for storing variable numbers of elements. The
head and tail of a list can be retrieved by using the following notation with a
vertical bar: [Head|Tail] for example: [Head|Tail] = [a, b, c].
Head will be bound to a and Tail will be bound to the remainder of the list,
[b, c] . Erlang tuples are used for storing data structures with fixed numbers
of elements, for example: {john, 4, `123 Brunswick St', fitzroy}
Pattern matching is used to match patterns with terms, for example:
{Name, Age, Address} = {john, 37, `78 Gipps St'}
Erlang has two primitives for conditional evaluation: case and if and a
number of built-in functions (BIFs) that perform operations that would be im-
possible to program in Erlang itself, or are impossible to program efficiently
in Erlang, for example, date(), which returns the current date.
Erlang functions are grouped into modules. The module contains a module
declaration, export declarations, import declarations and code representing
the functions which are exported from the module, for example:
-module(math2).
-export([fac/1]).
An Erlang function is built from a number of clauses. The clauses are sepa-
rated by semicolons `;'. Each individual clause consists of a clause head, an
optional guard and a body. The clause head consists of a function name fol-
lowed by a number of arguments separated by commas. When a function call
is made, the call is sequentially matched against the set of clause heads which
define the function. See the examples below.
Chapter 2: Erlang
20
2.3 Program Examples
-module(math2).
-export([fac/1]).
fac(0) -> 1;
fac(N) -> N * fac(N-1).
The module is called math2 and exports the function fac that takes one ar-
gument. Erlang is weakly typed so only the number of arguments is specified.
The first function head is fac(0). If a match of the call to fac and the func-
tion head can be made then the clause is evaluated. 1 is evaluated to 1 and
returned. The clauses are separated by `;'. If the first clause cannot be
matched to the function call the following will be evaluated. An error mes-
sage is returned if no clause can be found that matches the function call. The
second clause is a recursive call to fac. Erlang is case sensitive and variables
start with an upper-case letter: N. n would be an atom in Erlang. Below is an
example of a an evaluation of fac(2).
4> fac(2).
2 * fac(2-1)¡
2 * fac(1)¡
2 * (1 * fac(1-1))¡
2 * (1 * fac(0))¡
2 * (1 * 1)¡
2 * (1)¡
5>2
The first line is the function call to the Erlang interpreter and the last line is
the return value. The rest would not be printed during an actual execution.
First a pattern matching of 2 to the clause fac(0) -> 1; is tried but since
0 and 2 do not match the second clause is tried. The second clause matches
N to 2 and 2 * fac(2-1) is returned to be evaluated, and so on. It is im-
portant that the recursive function call fac(N-1) comes last in the clause be-
cause otherwise last call optimisation can not be used and then the function
will not evaluate in constant space.
%% nth(N, L) returns the N th element of the list L
%% nthtail(N, L) returns the N th tail of the list L
nth(1, [H|T]) -> H;
nth(N, [_|T]) when N > 1 -> nth(N - 1, T).
Chapter 2: Erlang
21
A comment starts with % and ends when the line ends. There are two clauses
in this function. The [H|T] format means that H is bound to the first element
in the list, head, and T is bound to the remainder of the list, tail. This function
has a guard test: when N > 1 .
nthtail(1, [H|T]) -> T;
nthtail(N, [H|T]) when N > 1 -> nthtail(N - 1, T);
nthtail(0, L) when list(L) -> L.
%% member(X, L) -> (true | false)
%% test if X is a member of the list L
member(X, [X|_]) -> true;
member(X, [_|Y]) -> member(X, Y);
member(X, []) -> false.
If the first element in the list is X then the function returns true. The next
clause removes the first element of the list and applies member recursively
on the rest of the original list. If the last clause is triggered then the list is emp-
ty, X has not been found and false is returned. This is an example of a poly-
morphic function. It does not matter what type of objects the list L consists
of because member will work on any type of objects.
fac(N) ->
case N of
0 -> 1;
N when N > 0 ->
N * fac(N-1)
end.
This example uses the primitive case to instead of having two clauses as in
the first example. If the function argument N is 0 return 1, else-if N>0 call
fac recursively.
2.4 Reflections on Erlang
This section is divided into the language Erlang and the programming envi-
ronment for Erlang.
Chapter 2: Erlang
22
The language
The author has had prior experience with functional and declarative languag-
es and thought the step to Erlang was fairly easy. When a comparison is made
below, and it is not explicitly stated what is being compared, the implicit
comparison is then between Erlang and an imperative language, such as C.
The dynamic typing in Erlang gives the language strength. It is easy and quick
to make prototypes. It would, however, be convenient to have type checking.
A type checker is currently being built at Glasgow University.
Going from a structural to a recursive methodology takes a bit time at first
but it soon felt natural. The most difficult aspect of Erlang was probably sin-
gle assignment variables. It is of course good to do away with common pro-
gramming errors such as setting variables to incorrect values or functions
setting global variables that they should not. It is also a strength in distributed
programming as it eliminates the need to propagate variable's values over the
network. Instead of using the data dictionary the library ets (Erlang built-in
Term Storage) was used. It saves time not to having to declare variables and
their types. The notion from Unix that processes are heavy operations took
quite some time to make free from. Erlang's processes are light-weight and
can (and should) be used extensively.
The lack of pointers saves the programmer from having to allocate and de-
allocate memory, dangling pointers, and other problems associated with
pointers. On the other hand, pointers and other features in C, for example, can
be very powerful, and even needed for certain applications. Therefore it is
important with good interfaces to foreign languages, databases, graphics
packages, etc. The author has not used many of the interfaces to foreign en-
vironments and can not comment on their usefulness.
Recursion could consume memory if used carelessly and incorrectly. When
using recursion, tail recursive functions, that is, functions that do not accu-
mulate any pending operations before recursing, should be used. It is fairly
easy to identify when tail recursion has not been used. There are no warnings
from the compiler when tail recursion is not being used. When tail recursion
is used the compiler can do last call optimization.
The Erlang error handling mechanisms are useful to make robust programs.
The programmer can even construct his own error handling. The syntax is
Chapter 2: Erlang
23
easy and straight-forward. The language is small, simple, and easy to learn.
There is not much one has to know in order to start programming. There are
few primitives to learn, although a large number of BIFs, although it is a
smaller portion of them that are important on a daily basis. Pattern matching
is an excellent way of assigning values, or as [Watt 1990] writes about pattern
matching: "Defining several equations in this way is a popular idiom [in
functional languages], because it is concise, clear, and recalls familiar math-
ematical notation." Pattern matching's main strength is the clarity it gives to
the code.
Readability is very important in today's programs. A program is written once
but read a number of times. Functional programming is on a higher level than
imperative programming and hence functional programming has less details,
thus is more readable. Recursion may not be the most intuitive way for iter-
ation, so if a function is not completely clear it should have `over-explicit'
comments.
Lists are powerful data structures. Most imperative languages act on scalars
rather than structured objects and if list-processing is desired a library-func-
tion has to be used or the function must be implemented from scratch.
The programming environment
The programming environment xerl for Erlang is a start to create a develop-
ment environment. It cannot be compared with environments for established
languages like C. The functionality is good but the interface and help func-
tions need to be worked on. An example of an irritating bug is when compil-
ing the code and receiving incomprehensible error messages. After a while it
was realised that there must be a new line after the end of the last clause in
the module, in order for the module to go through the compiler.
The debugger and the tracer are very important in a language with concurrent
processes. They work well even if the number of windows on the screen
quickly explodes.
Chapter 2: Erlang
24
There is an Erlang mode for emacs from Ericsson, that with enhancement
could turn out to be a helpful tool. [Lindgren 1996] has enhanced the Erlang
mode and distributes his version for free. Among the enhancements are: fon-
tification (hilite)1, tags2, and an Erlang shell. It would be very convenient if
folding3 also would be available.
1. The feature when keywords are shown in a different font or colour on the screen.
2. Place the cursor on a function and press M-. RET, the file in which the function is defined is
loaded and the cursor is placed on the definition of the function.
3. Folding is when parts of a function is hidden, for example the body. The function can be ex-
panded by clicking on the function head.
25
3 Object-Modeling
Technique
This chapter defines some object-oriented concepts and describes OMT with
an example, resulting in an implementation in Erlang.
Object-orientation is beginning to take a part as one of the programming par-
adigms alongside structured programming, for real-time systems. It is one of
the more talked about areas in program development today and there are
many books on the subject. [Goldsmith 1993] says the main advantage of us-
ing object-oriented design in a real-time system is that the minimisation of
object dependencies leads to a system consisting of independent objects thus
making the system easier to maintain. In other words, maximising the bene-
fits of cohesion, minimising the disadvantages of coupling, and utilizing the
properties of inheritance. Object-orientation puts emphasis on modelling the
problem domain, information hiding, and inheritance.
3.1 OMT
There are a number of object-oriented design techniques available for soft-
ware development. Among the more recognised are [Booch 1994],
[Rumbaugh 1991], and [Yourdon 1994]. The reason Rumbaugh has been
chosen for this thesis is because it describes the path from analysis to imple-
mentation well and it has a step-by-step schema to follow. Rumbaugh is clear
to understand and it is straight-forward to apply. Booch's style of diagrams
Chapter 3: Object-Modeling Technique
26
is more esthetical more appealing than the common boxes and ovals in OMT.
However, Rumbaugh's style is easier to draw when no tool, such as Rational
Rose, is available thus Rumbaugh's diagram style has been used here.
Rumbaugh's Object Modeling Technique (OMT) [Rumbaugh 1991] com-
prises of three phases
1. Analysis
2. System design
3. Object design
The input to the analysis is a problem statement and the goal of analysis is to
develop a model of what the system will do. During analysis three models are
built:
* Object model
* Dynamic model
* Functional model
The analysis model is expressed in terms of objects and relationships, dy-
namic control flow, and functional transformations. The output of analysis is
a formal model that captures the objects and their relationships, the dynamic
flow of control and the transformation of data.
The OMT is described with an example below. The example will be used in
Chapter 4. For a complete description of the steps in the OMT see
Appendix A, and for a complete description of the OMT see [Rumbaugh
1991].
3.2 ATM
An Automatic Teller Machine (ATM), will be used to exemplify the OMT
An AMT has some interesting features, such as: a real-time application, sep-
arate processes, separate systems, a distinct flow of control, and examples of
objects, associations, aggregations and inheritance.
Chapter 3: Object-Modeling Technique
27
The main stages and diagrams in the OMT will be shown. Further detail has
been provided when it has been needed to understand the implementation lat-
er on. In the following text the object class ATM is referred to as ATM and
the term ATM network is used when the whole system is referred to. An im-
plementation in Erlang follows the analysis and design.
3.3 Analysis
The Analysis phase consists of the following steps:
1. Write or obtain an initial description of the problem (Problem State-
ment).
2. Build an Object Model.
3. Develop a Dynamic Model.
4. Construct a Functional Model.
5. Verify, iterate, and refine the three models.
Analysis Document = Problem Statement + Object Model + Dynamic Model
+ Functional Model.
Problem statement:
Design the software to support a computerised banking network with
ATMs to be shared by a consortium of banks. Each bank provides its
own computer to maintain its own accounts and process transactions
against them. ATMs communicate with a central computer which clears
transactions with the appropriate banks. An ATM accepts a cash card, in-
teracts with the user, communicates with the central system to carry out
the transaction, dispenses cash, and prints receipts. The system requires
appropriate record keeping and security provisions. The software to be
designed is for the ATMs and the network.
Chapter 3: Object-Modeling Technique
28
Object Model
To build the Object Model classes are identified, and a data dictionary is con-
structed. The data dictionary contains descriptions of classes, attributes, and
associations, Figure 3.1.
After the data dictionary has been completed associations between classes,
attributes for objects, and inheritance are added. Figure 3.2 describes the re-
sult, an object model diagram. It shows the relations between the three main
classes: Consortium, Bank, and ATM and a few accessory classes: Transac-
tion, Update and Accounts.
Data dictionary
Account - a single account in a bank against which transactions
can be applied. Accounts may be of various types, at least chequeing
and savings. A customer can hold more than one account.
ATM - a station that allows customers to enter their own transac-
tions using cash cards as identification. The ATM interacts with the
customer to gather transaction information, sends the transaction
information to the central computer for validation and processing,
and dispenses cash to the user. The ATM does not need to operate
independently of the network.
Bank - a financial institution that holds accounts for customers and
that issues cash cards authorising access to accounts over the ATM
network.
Consortium - an organisation of banks that commissions and oper-
ates the ATM network. The network only handles transactions for
banks in the consortium.
Transaction - a single integral request for operations on the
accounts of a single customer.
Figure 3.1 Part of the data dictionary for the ATM network.
Chapter 3: Object-Modeling Technique
29
Figure 3.2 Simplified class diagram for the ATM network.
The boxes denote classes and the diamonds denote aggregation. The filled
dots stand for `0 or more'. A Consortium is an organisation of banks that
commissions and operates the ATM network. The Consortium consists of
banks - aggregation. The Consortium owns the ATMs - association. The
Bank holds a number of accounts. The accounts have a superclass, Base Ac-
count; Cheque Account and Savings Account are subclasses - inheritance.
A Transaction is entered on an ATM. A Transaction consists of Updates. An
Update concerns accounts.
Dynamic Model
After preparing scenarios of interaction sequences event traces are made for
the object classes, see Figure 3.3.
Cheque
Account Savings
Account
Consortium Bank
ATM
Consists of
Base
Account
Owns
Holds
Entered on
Transaction Update
Consists of
Concerns
Chapter 3: Object-Modeling Technique
30
Figure 3.3 Part of an event trace for the ATM scenario
When a user, the customer, arrives at the ATM and inserts the card, the user
is asked to key in the password. Then the ATM asks the Consortium if the
number associated with the card and the password are correct. The Consorti-
um has contact with the banks and decides from the number of the card,
which bank the question should be sent to. The bank, where the customer has
the account, is asked to verify that the card is with that bank. The answer is
passed back to the Consortium, which passes it back to the ATM. The infor-
mation transfer always goes through the Consortium. The rest of the event
trace is not described here.
The next step is to construct an event flow diagram for the ATM, see
Figure 3.4. The event flow diagram shows the events passed between the
classes in the system.
User ATM Consortium Bank
insert card
enter password
request password
verify account
verify card with bank
bank account OK
request amount
account OK
Chapter 3: Object-Modeling Technique
31
Figure 3.4 Part of the event flow diagram for the ATM scenario.
Given the event trace diagram and the event flow diagram a state diagram is
constructed, Figure 3.5. This example is simplified and shows only the ideal
flow, that is, when no errors or mishaps occur in the interaction. When the
control is in state Main Screen it awaits the event insert card. When
the event is received the control goes to state Request password, and so
on. If, for example, the password is incorrect the control would go to Incor-
rect password (not illustrated in Figure 3.5) and appropriate measures
would be taken.
User ATM
Bank Consortium
request password
request amount
insert card
enter password
enter amount
verify card with bank
bank account OK
account OK verify account
Chapter 3: Object-Modeling Technique
32
Figure 3.5 Simplified state transition diagram for the ATM class.
Functional Model
At first input and output values, that is, parameters of events between the sys-
tem and the outside world, are listed. The input events that only affect the
flow of control were not taken into account, and nor were acknowledgment
events. Next the data flow diagrams are constructed. The data flow diagrams
show how each output value is computed from input values. A top level data
flow diagram for the ATM network is shown in Figure 3.6.
The ovals denote processes and the hollow arrow a data flow that results in a
data store. The rectangles are actor objects, that is, active objects that drive
the data flow graph by producing or consuming values. The text next to the
arrows signifies the name of data flowing through the system.
Main screen
Request password
Verify account
Request amount
Process transaction
Dispense cash
Request take cash
Eject card
Request take card
insert card
enter password
account ok
enter amount
transaction succeeded
wait
take cash
insert card
Chapter 3: Object-Modeling Technique
33
Figure 3.6 Top level data flow diagram for ATM.
3.4 System Design
During system design, the high-level structure of the system is chosen. The
first step in the system design phase is to organise the ATM network into sub-
systems. The ATM network has three major subsystems: ATM, Consortium
and Bank.
Figure 3.7 The system architecture for the ATM network.
In this problem it is natural to group the classes into the physical subsystems
that were present.
The next step is to identify concurrency. The event trace, Figure 3.3, helps us
find the concurrent objects. Two objects are inherently concurrent if they can
receive events at the same time without interacting. It turns out that all three
subsystems need to be concurrent classes. A permanent data store is needed
for the accounts and the Erlang library ets (Erlang built-in Term Storage)
was chosen. The data store resides in the bank computer, that is, the Bank
class. There can be only one transaction per ATM but there are many ATMs,
password,
amount,
account type
Cash
card
User
Account
read
inputs perform
transaction generate
outputs
bank code,
card code
messages,
cash,
receipt
balance
ATM Consortium Bank
User
Chapter 3: Object-Modeling Technique
34
therefore concurrency arises. The consortium must be able to serve several
requests simultaneously.
3.5 Object Design
During object design the analysis model is elaborated upon providing a de-
tailed basis for implementation. The decisions that are necessary to realise a
system without descending into the particular details of an individual lan-
guage are made. Object design starts a shift away from the real-world orien-
tation of the analysis model towards the computer orientation required for a
practical implementation.
After the data flow diagrams have been constructed the operations are deter-
mined and the constraints are identified resulting in class specifications, see
example in Figure 3.8 and Figure 3.9. Every class has the operation
Base Account
Responsibilities:
Provide the basic account services.
Subclasses: Cheque Account, Savings Account
Attributes:
* AccountNumber:integer
* PassWord:character string
* Balance:integer
* Log:[strings], the strings consist of date, time, transaction type,
amount, and a verification number.
Operations:
* withdraw(Amount:integer)-> NewBalance:integer
* getBalance()-> Balance:integer
Constraints: none.
Figure 3.8 Class specification Base Account
Chapter 3: Object-Modeling Technique
35
create(Args) but it is not listed in the class specifications unless it actually
uses Args.
Responsibilities describes the class's overall responsibilities and uses. Then
superclass and subclasses are listed, when applicable. The attributes are the
variables contained within the class.
Cheque Account
Responsibilities:
Cheque account, which checks that withdrawal is not higher than the
allowed limit. Add interest to the account once a month.
Superclass: Base Account
Attributes:
* CreditLimit:integer
* Interest:float
Operations:
* withdraw (Amount:integer)-> NewBalance:integer
* monthlyInterest()-> {NewBalance:integer, interest:integer}
Constraints:
Cannot withdraw more money than Balance+CreditLimit.
Figure 3.9 Class specification for Cheque Account
Chapter 3: Object-Modeling Technique
36
3.6 Implementation - Hobbins
This section describes an implementation of the ATM network in Erlang us-
ing Hobbins' concept [Hobbins 1995]. The identified subsystems from the
System Design (Section 3.4): ATM, Consortium, and Bank, were modelled
as single Erlang processes.
Figure 3.10 The subsystem architecture for the ATM network.
A system manager `System' was constructed, see Figure 3.10. Its responsi-
bilities are to start up, monitor, and shut down the subsystems.
Figure 3.11 The subsystems' class partition
When the ATM network was decomposed into subsystems the classes were
placed in the various subsystems, see Figure 3.11. Sometimes a class would
span over several subsystems, like Transaction, indicated with the dashed
line. The communication links between the subsystems are indicated with
ATM Consortium Bank
System
User
Account
Transaction
Update
User
ATM Consortium
Transaction Transaction
ATM Consortium Bank
Database
Chapter 3: Object-Modeling Technique
37
solid lines. The Account and Update classes have been grouped within the
Bank subsystem because they were saved in a database.
Each subsystem has three meta states: init, running, and stopping. The init
meta state consists of: initialisation routines, start-up confirmation, and syn-
chronisation with other objects when necessary. The running meta state em-
bodies the subsystem behaviour and has a receive loop catching messages
to the process. The stopping meta state consists of termination routines.
In the running meta state, the subsystem is executing its specified responsi-
bilities and communicating with other subsystems. Subsystems interacting
asynchronously in the running state implement the required system behav-
iour through finite state machines. The implementation of the three meta-
states is described below. The complete Erlang code to the ATM is found in
Appendix B.
Init
spawn(atm,atm,[{init,self()},{idle},5000])
The system monitor sys spawns an atm process.
atm(MetaState, State, Timeout) ->
case MetaState of
{init, Pid} ->
%% confirm startup
Pid ! {started,self()},
sys:writelog(`atm:atm()', `~w atm starting',
[self()]),
atm({running},{idle},infinity);
atm takes three arguments: MetaState, State and Timeout. If atm has
not received any messages after Timeout ms it will abort and send an error
message to sys. When atm has been spawned it initiates itself and then it
sends a message to sys, saying it has started. The last action atm takes in init
is to call itself and go into the running metastate and the idle state.
Running
{running} ->
%% Main loop for atm
receive
{cardInserted} when State=={idle} ->
Chapter 3: Object-Modeling Technique
38
requestCardNo(),
atm({running},{requestCardNo},10000);
When atm has called itself and gone into the running mode it goes into a re-
ceive loop and waits for a message. This is where the finite state machine
from the state transition diagram, Figure 3.5, comes in. The state machine is
implemented with receive loops and calls to atm with new states. atm
awaits the message {cardInserted}. When the message arrives the oper-
ation requestCardNo is triggered. requestCardNo is a function only ac-
cessible within the atm module. The operation is carried out and atm is
called again but now with a new state.
{message, OriginalMessage} ->
Message=filterNl(OriginalMessage),
case State of
{requestCardNo} ->
CardNo = list_to_integer(Message),
requestPwd(),
atm({running},{requestPwd,CardNo},10000);
{requestPwd,CardNo} ->
...
The rest of the finite state machine is an interactive interface. The user enters
information and the atm processes it and requests new information. The en-
tered information is OriginalMessage. Depending on the state it will be
converted from a list of characters to the appropriate type. As information is
added to the system it is passed on in the state tuple, for example
{requestPwd,CardNo} , first the state and then the data.
Stopping
{stopping} ->
sys:writelog(`atm:atm()', `~w stopping',
[self()]),
exit(atmStopping);
The last metastate is stopping. When it has been called atm writes in the sys-
tem log that it is leaving the system and then it exits and atm is terminated.
The exit call is caught by sys.
Chapter 3: Object-Modeling Technique
39
Other
Other->
sys:writelog(`atm:atm()',
`~w received unknown message [~w] in
state: ~w',
[self(),Other,MetaState]),
atm(MetaState,State,Timeout)
The last clause in every receive body is Other that catches all unrecognised
messages that are sent to the process. Action will be taken in accordance with
the present state. In the example above the message is printed on the system
log and then the receive loop is recommenced, hence disregarding the un-
known message. It is of course very important to empty unknown messages
from the process mailbox, so they do not fill the entire Erlang system's mail-
box, which could lead to unforeseen consequences.
after Timeout ->
sys:writelog(`atm:atm()', `~w timed out,
aborting and stopping in metastate: ~w',
[self(),State]),
abortTrans(`Transaction cancelled',[ ]),
atm(running,{stopping},10000)
end %%{running} receive%%
end. %%MetaState case%%
After Other comes an after clause that interrupts the receive loop after
Timeout ms. If for example consortium cannot make contact with atm af-
ter a request from atm then atm would wait for ever, if the after clause was
not there. Different actions can be taken depending on if the subsystem is in
a state where it can backtrack and re-send the request or if it can only abort,
like in the example above.
40
4 A Development
Technique for Erlang
This chapter proposes a technique for developing object-oriented programs
for Erlang. The mapping of the design to an implementation in Erlang is
shown.
The implementation of the ATM in Chapter 3 gave insights into Erlang and
object-orientation techniques, from which a general approach to implement
objects, classes and association in Erlang emerged. The model for implemen-
tation was Hobbins' subsystem model. After analysis it was determined that
working on a class level was preferable to working on a subsystem level. The
following assumes that the OMT has been used for the object-oriented
analysis and design. The technique should work with other `standard' object-
orientation development techniques, such as [Booch 1994] and [Yourdon
1994]. Below is an outline for the development technique.
The Analysis and the System Design phases in the OMT are carried out yield-
ing structuring of the information and an object model of the system. Not all
objects will be implemented as Erlang processes, for reasons discussed in
Chapter 1, such as memory overhead. The event flow diagram, Figure 4.1,
shows the classes that messages are being passed between. Since these class-
es employ the behaviour of sending and receiving messages it seems natural
to implement them as Erlang processes. Classes in the event flow diagram are
called active classes and the rest of the classes in the object model passive
classes. As stated earlier, an active object is an object that encompasses its
Chapter 4: A Development Technique for Erlang
41
own thread of control whereas a passive object does not [Booch 1994]. Ac-
tive objects are generally autonomous. A passive object's operations are
called by active objects. The active objects serve as the locus of execution.
After deciding upon the active classes each of the passive classes is assigned
to an active class. Active classes are implemented as Erlang processes in a
similar manner to the way Hobbins did with subsystems (Section 1.3). The
behaviour of the passive classes is coded into the active classes. Since Erlang
does not support inheritance of classes, the hierarchy is flattened out and all
the operations and behaviour from the superclasses are copied down to the
subclasses. Associations between the active classes are implemented as
Erlang links and communication is catered for by letting objects (processes)
have knowledge of each other's pids.
The technique is described in detail below and divided into Object Design
and Implementation in Erlang.
4.1 Object Design
In the Analysis phase of OMT the developer brainstorms and grasps the sys-
tem behaviour. Object, Dynamic, and Functional models are constructed. In
the System Design phase the high-level structure of the system is chosen.
During Object Design the developer elaborates the analysis model and pro-
vides a detailed basis for implementation.
Towards the end of the Object Design a system to be implemented in Erlang
has been generated but the system needs to be adjusted to a level where it is
feasible to implement the objects as Erlang processes. The aim is to reduce
the number of objects that will actually be implemented as Erlang processes.
During System Design concurrent objects have been defined. A concurrent
object is an active object whose semantics are guaranteed in the presence of
multiple threads of control [Booch 1994]. Two objects are inherently concur-
rent if they can receive events at the same time without interacting. The con-
current objects will naturally be implemented as Erlang processes. The
remaining objects could be grouped into subsystems and implemented as
Erlang processes but such a grouping is not fine enough. A subsystem en-
compasses aspects of the system that share some common property. Subsys-
tems are rather large components (in the OMT) and it is undesirable for
Chapter 4: A Development Technique for Erlang
42
Erlang processes to be too large and to contain too much information. If the
Erlang processes are large the state of all the enclosed classes will be likely
to be large. As a consequence of this the recursive function calls done at time
of state transformation may be costly in terms of parameter passing. It would
also be difficult to take in the whole picture of the Erlang process if it is large
and hence be difficult to maintain. The next and final level of abstraction in
the OMT is the module. A module is a logical construct for grouping classes,
associations, and generalisations. The module captures one perspective or
view of a situation. This level of abstraction is also too high as modules will
be too large to implement as single Erlang processes. In spite of these prob-
lems the idea of grouping or dividing the objects into some entity as done in
the subsystem approach seems appropriate. The event flow diagram,
Figure 4.1, shows that the classes display the properties associated with
Erlang processes, that is, the classes send and receive events (messages) be-
tween each other. All other classes in the object model are used as informa-
tion hiding objects or used as means of abstraction. The objects in the event
flow diagram are identified as active objects since they actually act and pass
messages to each other. The remaining objects are called passive objects.
Figure 4.1 Example of an event flow diagram
Figure 4.2 shows a class diagram where the active objects have dotted lines.
The passive objects must be involved in the active classes. The passive ob-
jects should not be processes of their own since they are not live objects.
User ATM
Bank Consortium
Chapter 4: A Development Technique for Erlang
43
Figure 4.2 Simplified class diagram for the ATM network, the active classes have dotted
lines.
After the active classes have been decided upon the passive classes are as-
signed to at least one active class. Some of the passive classes may need to
be assigned to several active classes. The data flow diagrams (for example
Figure 3.6) assist in showing where data flows through the active classes.
This data is used to guide decisions determining which passive classes should
be included in which active classes.
Data stores should be encapsulated within Erlang processes, even if they are
not included as a class in the event flow diagram. The Erlang process is re-
sponsible for managing the data store. This ensures that data is not changed
by mistake and all details are hidden from the user. Figure 4.3 shows the par-
titioning of active classes and which passive classes are included. Both the
active and the passive class boxes are depicted inside the smoothed rectan-
gles, which will become Erlang processes. The Erlang process will take the
name of the active class. The solid lines between Erlang processes state asso-
ciations between the processes. The dotted lines show that the passive class
`Transaction' is included in several active classes.
Cheque
Account Savings
Account
Consortium Bank
ATM
Consists of
Base
Account
Owns
Holds
Entered on
Transaction Update
Consists of
Concerns
Chapter 4: A Development Technique for Erlang
44
Figure 4.3 Example of class partitioning into active and passive classes, and Erlang
processes
4.2 Implementation in Erlang
The step from design to implementation should be straight forward as the dif-
ficult decisions were made during the design phase. This section describes
the implementation of classes, inheritance and association in Erlang. The
scheme used is similar to the subsystem model in Section 1.3. Active classes
will be implemented as Erlang processes and the passive classes' behaviour
will be included in the processes. Active classes will be controlled by a Class
Manager.
Class Manager
The Class Manager is an Erlang process used to implement control in the sys-
tem. Control is not implemented as a state machine engine that drives the ob-
jects. Instead, as we have access to real concurrent Erlang processes that
contain state machines themselves, the mechanism spawns Erlang processes,
initiates and starts them, monitors their activity, and terminates them. The re-
sponsibilities of the Class Manager are:
* initiating and terminating the active classes' execution
* detecting active classes exiting by trapping their Erlang exit condition
* handling alarms and events
The class management mechanism could also be used to create encapsula-
tion. This would be implemented by treating the Class Manager as a module
Transaction
ATM Consortium
Transaction Transaction
ATM Consortium Bank Account
Bank
Update
data base
Account
Chapter 4: A Development Technique for Erlang
45
(in the OMT sense: a logical construct for grouping classes, associations, and
generalisations) and having other modules communicate with it through
standard Erlang message passing. The messages are passed on to the active
objects by the Class Manager. The use of a Class Manager as an intermediary
incurs an overhead. If the overhead is considered too high it can be eliminated
by allowing messages to be sent directly to an active class. The price of al-
lowing direct communication is the elimination of the encapsulation offered
by implementing modules using the Class Manager.
Active classes
An active class is implemented as an Erlang process. The Erlang process for
an active class has three meta states: init, running and stopping. An active
class is constructed by creating a module with the same name as the active
class. The module must contain a function with the same name as the subsys-
tem and the function must be included in the export declaration. This function
is the only function included in the export declaration as the passive classes
do not send messages outside the Erlang process and should not be accessible
to objects outside the process.
-module(active_class).
-export([activeClass/3]).
activeClass(MetaState,State,Timeout) -> ...
The next step is to implement the meta states in the active class function. The
first meta state is init. The init meta state consists of:
* initialisation routines
* start-up confirmation
* synchronisation with other active classes
The initialisation routines are specific to the system being implemented.
Start-up confirmation is a message sent to the Class Manager stating that the
active class has started successfully. Synchronisation with other active class-
es, where necessary, is performed last and can involve informing other active
classes that the active class is ready. An alternative is to have the class man-
ager rebroadcast the start-up message.
Chapter 4: A Development Technique for Erlang
46
activeClass(MetaState,State,Timeout) ->
case MetaState of
{init, ClassManagerPid} ->
%% initialisation
ClassManagerPid ! {started,self()},
%% synchronisation
atm({running},{idle},infinity);
The first clause in the active class function checks what meta state the func-
tion has been called with. The actions associated with the init meta state are
shown above.
The second meta state is running. The running meta state consists of:
* a finite state machine, implemented as an Erlang receive loop
This code controlls the behaviour of the active class. Erlang's receive state-
ment enables it to implement state machines easily:
{running} ->
%% finite state machine
receive
{Event} when State=={SomeState} ->
operation(Args),
activeClass({running},{NewState,Data},
Timeout);
{AnotherEvent} when State=={OtherState} ->
...
The Erlang process performs a loop where it receives an event, acts on it,
transfers itself to a new state and makes a recursive call to itself with the new
state and the meta state running. The Erlang process then awaits a new in-
coming event. Operations are implemented as Erlang functions. These func-
tions are not to be included in the export declaration. They should only be
accessible through the process interface.
The third meta state, stopping, consists of:
* termination routines
The stopping meta state is invoked by the Class Manager when the system is
shutting down, when the active class is no longer needed, or when the active
class needs to be restarted. The stopping meta state provides defined proce-
dures for taking the system (or an active object) down. The code of the stop-
ping meta state is shown below.
Chapter 4: A Development Technique for Erlang
47
{stopping} ->
%% termination routines
exit(atmStopping);
The exit call is caught by the Class Manager that registers the loss of the ac-
tive class and takes measures accordingly.
Inheritance
The technique presented above has allowed Erlang to model the behaviour of
a class-based language. Skagervall [Skagervall 1993] has shown that inherit-
ance can be modelled with recursive messages passed up and down the inher-
itance hierarchy (Section 1.1). This scheme is rejected on the grounds
presented earlier: messages passed through the inheritance chain require con-
text switches before they can be processed by the recipient process and hence
are expected to be costly in terms of execution time if the inheritance hierar-
chy is deep.
The alternative is to flatten the inheritance tree and represent the hierarchy in
the active class process. This means that if a class inherits attributes, opera-
tions, and behaviour from a superclass, then those are copied down to the
class.
Figure 4.4 Example of operation resolution in an inheritance tree
The copying of superclasses' behaviour can be automated by a program or by
putting inheritance dependencies in a `make' file, so that the appropriate op-
erations will be copied before compilation.
The procedure for handling inheritance appears to indicate that inheritance is
not required as at the point of implementation inherited behaviour is pro-
Op?
Op?
Res
Res
Chapter 4: A Development Technique for Erlang
48
duced by duplication of code. However, inheritance is a useful tool for mod-
elling the system during analysis. Furthermore, inheritance encourages
programmers to look for similarities and even if the programmer cannot im-
plicitly take advantage of such mechanisms as sharing of code, an analysis
including inheritance will make the programmer aware of when and where
that is possible to do. If an explicit way of using inheritance in the system can
be found, significant advantages flow from its use. Another reason for going
through all the steps in the OMT is to get a complete model of the system.
One of the claimed advantages with object-orientation is to be able to reuse
complete designs and not only parts of code or certain libraries. It is essential
to be able to handle inheritance to be able to use a complete OMT model of
the system and hence ensure language independence. Reuse is discussed fur-
ther in Chapter 5.
Association
Association between active objects can be implemented by ensuring that
Erlang processes know each other's Pids and hence are able to send messages
to each other. If an object cannot exist without another object an Erlang link
can be created between them. An Erlang link is bidirectional. When either the
object or one of its constituent parts cease to exist, an Erlang exit signal will
be sent to all the linked Erlang processes. If the Erlang processes do not catch
the signal they will also terminate.
Another case is where the constituent parts can exist autonomously after the
object has ceased to exist. In this case the processes, representing the parts,
need to catch the exit signal (caused by the termination of the Erlang link) to
the parts from the object, when the object terminates itself, so that the parts
do not exit as well. The parts must take action that takes into account the de-
struction of the process that owned them. These mechanisms are at least as
safe as those used by object-oriented languages. Consider C++ where associ-
ations between classes are implemented using pointers to classes, incurring
the potential risk of `dangling pointers' after an object has terminated without
announcing its termination to the objects associated with it.
Chapter 4: A Development Technique for Erlang
49
Passive classes
Passive classes are information hiding entities that do not encompass their
own thread of control. Passive classes' operations are called by active class-
es. The control in a concurrent Erlang program resides in the Erlang process-
es (active classes). As passive classes do not encompass their own thread of
control they do not need to be implemented as Erlang processes. Therefore,
passive classes are embedded in active classes' Erlang processes. Passive
classes are thus local to active classes and can only be used within active
classes.
A passive object's behaviour is implemented as a function call with the cur-
rent state as argument, and the new state and the result as return value. A
mechanism is needed to preserve a passive object's state. Erlang has single
assignment variables and hence a variable cannot be used to store a passive
object's state. Active objects preserve their state by recursively calling them-
selves with the new state as an argument. Therefore, a passive object's state
is included in the active object's state. An alternative approach would be to
use the Erlang process dictionary (see page 18) to store a variable containing
the state of a passive object. However, in [Armstrong 1993] Armstrong
strongly discourages the use of the Erlang process dictionary as it introduces
destructive operations.
A different implementation approach is needed if a passive object is to be
shared between many active objects. One way to implement a shared passive
object is to have an `intermediary' Erlang process for a shared passive object,
see Figure 4.5. A passive object could be implemented as a stack (an Erlang
list). An active object could request the state from a shared passive object and
the state would be popped from the list and passed back as a message to the
requesting active object. Conversely, to set the state of a passive object, an
operation would be performed, and the new state would be pushed onto the
list. In order to obtain a state two messages would have to be sent and to set
the state one message would have to be sent. An alternative approach is to
pass the shared information between the processes as messages. This would
save one message being sent and one Erlang process. This is the approach
used in the ATM example. The shared object `Transaction', see Figure 4.3,
is passed between the active classes as an abstract data type in the form of a
tuple.
Chapter 4: A Development Technique for Erlang
50
Figure 4.5 Intermediary Erlang process as a shared passive object. The little circle depicts
the object's state.
Inheritance for passive classes is implemented in a similar way to the active
classes. The inheritance tree is flattened and the attributes, operations, and
behaviour of superclasses is copied down to a subclass.
Association between passive objects is not applicable as the passive objects
do not have their own thread of control and hence do not have the capability
to communicate with other passive objects. The implementation of associa-
tion between active objects and passive objects depends on the type of asso-
ciation. Association between active objects is implemented using Erlang
links. However, there is no construct for creating an Erlang link between an
active and a passive object as links only work between Erlang processes.
Thus association between an active object and passive objects is embedded
in the behaviour of the active object, that is, in the running metastate.
4.3 Discussion
The technique presented in this chapter is a general approach to implement
objects, classes, and association in Erlang. The objective of the thesis was to
find a logical and coherent way to decide when to use an Erlang process for
an object and when to use another mechanism. Such a logical and coherent
way has been found. This section compares this technique with Keisu's ap-
proach [Keisu 1995] and the subsystem approach [Hobbins 1995], presented
in Chapter 1.
As mentioned earlier, a subsystem is a relatively large component and hence
the Erlang process for implementing a subsystem is large. This may result in
difficulties in taking in the whole picture of an Erlang process for a program-
mer or maintainer as well as being costly in parameter passing. This tech-
Active object 1 Active object 2
Shared passive object
pop()
State
push(state)
Chapter 4: A Development Technique for Erlang
51
nique handles these difficulties by having smaller Erlang processes. The
Erlang processes include only one active object each. Furthermore, the sub-
system approach uses an object-based analysis and design and not an entire
object-oriented analysis and design. This technique takes the entire object-
oriented model into account during analysis and design and is hence more
complete. The implementation approach in this technique with a class man-
ager and metastates has been adopted from the subsystem model. It was
found that using a class manager and metastates maps well onto real-time
systems, which Erlang is aimed for.
The thesis was started off using the subsystem model in conjunction with a
complete object-oriented analysis and design. Although that was a different
direction from Keisu's, a concordance in the classification of objects was lat-
er found between this approach and Keisu's. Keisu differentiates between
static passive objects and concurrent objects, whereas this technique con-
trasts passive objects with active objects. Keisu addresses how to implement
inheritance for static passive objects but he does not give guidance for the im-
plementation of inheritance for concurrent objects. This technique addresses
how to implement inheritance for both passive and active objects.
Keisu does not address the implementation of association. Association is the
"glue" in the object model and hence important during implementation. The
implementation of association is described in this technique.
52
5 Discussion and
Conclusions
This chapter discusses the following aspects of the design technique in
Chapter 4: reuse, maintenance, efficiency, psychological aspects, measure-
ments, future work, and followed by the conclusions.
The following discusses aspects of the design technique from Chapter 4.
Reuse
Object-oriented design techniques' promise the ability to reuse previous
work. This discussion will cover several levels of reuse of code, analysis and
design. Traditionally reuse has been concerned with low-level functions, ab-
stract data types, and sometimes libraries of code. As Erlang is built on the
concept of modules, a further level of reuse is introduced as an existing and
tested module can be reused in another project.
Object-orientation focuses on the reuse of analysis specifications and de-
signs. Coding consumes a relatively small amount of time in a project com-
pared to analysis and design, hence there is more to gain from the reuse of the
latter. The proposed design technique builds on an object-oriented design and
hence does not change the possibility of reuse of design and analysis. Further
work on the development of CASE tools is required to make reuse of design
and analysis practical. These tools would enable software engineers to
browse previous projects and see if they can find material worthwhile for re-
Chapter 5: Discussion and Conclusions
53
use. These techniques would allow such a tool to be created and used in the
Erlang context.
Maintenance
Maintenance consumes a large proportion of the total effort during a system's
lifetime. Maintenance concerns the modification of a program after it has
been delivered and is in use. It is important that there is a mapping from the
implementation to the design to allow adequate maintenance documentation
to be written. The proposed approach where the inheritance tree is flattened
appears to impose a problem when updating designs, however this is not the
case. A change in an operation's behaviour may be updated since the class
descriptions are available and the maintainer knows what class the operation
belongs to. If a new operation is required it is included in one of the classes.
Since it is known what the operation is working on the class it belongs to is
easily deduced. Given a hierarchy of classes there may be some difficulty in
determining whether a new operation should be introduced higher up in the
class hierarchy, however this is a general problem when using an object-ori-
ented strategy.
Efficiency
A simple set of step-by-step instructions are presented in the design tech-
nique. They result in a functional decomposition into a number of functions
grouped in modules, and a number of processes to model concurrency. It is
difficult to equate the number of functions, modules, and processes that
would be in functional decomposition and the proposed design technique.
However, the number and type of elements is of the same order of magnitude.
(this contrasts with Skagervall's method [Skagervall 1993] which results in
a large amount of processes). Since the implementation complexity of the
two approaches are similar it is difficult to say that one or the other would run
faster or use more memory. Such properties are typically more dominated by
the skills of the programmer than determined by the paradigm.
Psychological aspects
Erlang is not an object-oriented language. This fact is a significant problem
problem for the promotion of Erlang as an implementation language for ob-
Chapter 5: Discussion and Conclusions
54
ject-oriented analysis and design. Programmers new to Erlang were asked
what they thought about using object-oriented design techniques with Erlang,
they felt it did not fit their picture of the language. This response was proba-
bly due to the fact that many programmers feel that they can only implement
object-orientation properly in a language with explicit object-oriented fea-
tures. Furthermore, Erlang introduces many new concepts for a programmer
used to imperative languages. This may make a programmer used to impera-
tive languages not realise the mechanisms Erlang provides for information
hiding, data abstraction, modularity, dynamic binding, and polymorphism.
Analysis and design should be language independent but often concerns
about the target language are taken into account too soon by the developers.
Such concerns should be ignored until the end of the development of the de-
sign. Programmers find it difficult not to take such concerns into account un-
less they have never implemented programs in the language before and hence
do not have any preconceptions. The problem derives from the fact that de-
sign and implementation often are not completely separate and transparent.
Object-orientation is an analysis and design technique and should not be
mixed with implementation decisions. Furthermore, Keisu stresses in [Keisu
1995] that object-oriented programming is a style of programming that is or-
thogonal to the implementation language.
Measurements
Two units of measurement are used in this thesis: cost of an Erlang process
and cost of communication. Statistically-based experimental verification is
potentially complex, futhermore, the actual measurement of the parameters
of the processes would be complicated. Running speed is often considered as
a parameter for these types of measurements. However, a system where proc-
esses interact with each other in a non-deterministic way does not lend itself
to accurate measurements. The non-determinism comes from the fact that the
order of events has a heavy impact on the running speed. Processes can be
recorded and scheduled differently from run to run yielding different results.
As there are no facilities to control scheduling, accurate and conclusive meas-
urements cannot be made. Thus qualitative and not quantitative statements
have been made about the efficiency of Erlang programs.
Chapter 5: Discussion and Conclusions
55
Future work
It would be desirable to apply the proposed design technique to larger
projects. This would preferably involve examples of a different character
than the server-client model that has been studied here.
It would be interesting to have interviews with developers with experiences
from larger projects carried out in Erlang. This has been done already [Car-
leson 1996] but not from an object-oriented view. It appears that the people
that have important experience and skills in the area do not have the time to
put their experience down on paper, for others to learn from.
Conclusions
The aim to find an efficient way to go from an object-oriented design to an
implementation in Erlang has been met. In the current implementation of
Erlang it is not feasible to implement all objects as Erlang processes and thus
only the active objects in the design are implemented as Erlang processes.
The passive objects are embedded in the active objects and their behaviour is
implemented as functions.
Although a different path was taken, a concordance in the classification of
objects was found between this approach and Keisu's.
The contribution of this thesis is to have followed a complete object-oriented
method and to have shown the appropriate bridges to a class-based imple-
mentation in Erlang. The whole cycle from analysis, design, to implementa-
tion has been considered. It has furthermore been found that Erlang is well
suited for an implementation of an object-oriented design.
56
6 References
The references are grouped into books and papers, WWW sources, and other
sources.
6.1 Books and papers
[Ahlberg 1993]
Ahlberg Ingemar, Bauner John-Olof, and Danne Anders. 1993. Prototyping
Cordless Using Declarative Programming, Ericsson Review, Vol: 70, Iss:2 ,
pp. 65-70.
[Armstrong 1993]
Armstrong J., Virding R., and Williams M. 1993. Concurrent Programming
in Erlang, Prentice Hall International, Hertfordshire, United Kingdom.
[Bird 1988]
Bird Richard and Wadler Philip. 1988. Introduction to Functional Program-
ming, Prentice Hall International, Hertfordshire, United Kingdom.
[Booch 1994]
Booch Grady. 1994. Object-Oriented Analysis and Design with Applications,
Benjamin/Cummings Publishing Company, Inc., Redwood City, California.
[Carleson 1996]
Carleson Johan. 1996. Industriella erfarenheter av programspråket Erlang,
(English: Industrial experiences of the programming language Erlang), B.A.
Minor Thesis, Linköping University, Department of Computer Science,
Linköping, Sweden.
Chapter 6: References
57
[Däcker 1993]
Däcker Bjarne. 1993. Erlang - A New Programming Language, Ericsson
Review, Vol: 70, Iss:2 , pp. 51-57.
[Goldsmith 1993]
Goldsmith Sylvia. 1993. A Practical Guide to Real-Time Systems Develop-
ment, Prentice Hall International, Hertfordshire, UK.
[Hobbins 1995]
Hobbins Tony. 1995. Subsystem Model. Presentation at: The Second Erlang
User Conference 11-12 October 1995, Ericsson Software Technology AB,
Erlang Systems,Sweden.
[Rumbaugh 1991]
Rumbaugh James, Blaha Michael, Premerlani William, Eddy Frederick, and
Lorensen William. 1991. Object-Oriented Modeling and Design, Prentice
Hall International, Englewood Cliffs, New Jersey.
[Sommerville 1992]
Sommerville Ian. 1992. Software Engineering, 4th Edition, Addison-Wesley
Publishing Company, Wokingham, England.
[Skagervall 1993]
Skagervall Roger, Strollo Sebastian. 1993. Chapter 15: Object-Oriented Pro-
gramming, in Concurrent Programming in Erlang by Armstrong J., Virding
R., and Williams M. 1993. Prentice Hall International, Hertfordshire, United
Kingdom.
[Watt 1990]
Watt David. 1990. Programming Language Concepts and Paradigms, Pren-
tice Hall International, Hertfordshire, United Kingdom.
[Wegner 1987]
Wegner Peter. 1987. Dimensions of Object-Based Language Design,
OOPSLA'87 Proceedings, October 4-8. [Check this]
[Yourdon 1994]
Yourdon Edward. 1994. Object-Oriented Systems Design: An Integrated Ap-
proach, Prentice Hall International Inc., Englewood Cliffs, NJ 07632.
Chapter 6: References
58
6.2 WWW Sources
[Keisu 1995]
Keisu Thorbjörn. 1995, OOP in Erlang, http://www.ericsson.se/erlang/pub-
lications/OOP.ps; E-mail: keisu@erlang.ericsson.se
[Erlang Systems]
The homepage for Erlang Systems, Ericsson, Sweden,
http://www.ericsson.se/erlang/
[Erlang]
The homepage for the Erlang language, Ericsson, Sweden,
http://www.ericsson.se/cslab/erlang/
[Erlang overview]
An overview of the Erlang development environment.
http://www.ericsson.se/erlang/products/overview.html
[Lindgren 1996]
Anders Lindgren's homepage. Lindgren has made an enhanced Erlang mode
for Emacs. http://www.csd.uu.se/~andersl/
6.3 Other Sources
[Eriksson 1996]
Klas Eriksson at Ericsson Software Technology AB, Sweden.
E-mail: eklas@erlang.ericsson.se
59
7 Glossary
This section contains glossary and abbreviations.
AMTAutomatic Teller Machine
OMTObject Modeling Technique
CASEComputer Aided Software Engineering
functional design
A method of design where the system is designed from a functional
viewpoint, starting with a high-level view and progressively refining this
into a more detailed design. The system state is centralised and shared
between the functions operation on that state. This strategy is exempli-
fied by `structured design' and `step-wise refinement'.
method
The implementation of an operation for a specific class.
object-oriented analysis
A method of analysis that examines requirements from the perspective
of the classes and objects found in the vocabulary of the problem do-
main.
object-oriented design
A design method where the system is viewed as a collection of objects
rather than as functions. The system state is decentralised and each ob-
ject manages its own state information. Objects have a set of attributes
Chapter 7: Glossary
60
defining their state and operations which act on these attributes. Objects
communicate by exchanging messages. Object-oriented design puts
emphasis on modelling the problem domain, information hiding, and in-
heritance.
object-oriented programming
A method of implementation in which programs are organised as coop-
erative collections of objects, each of which represents an instance of
some class, and whose classes are all members of a hierarchy of classes
united via inheritance relationships.
operation
A function or transformation that may be applied to objects in a class.
61
A OMT
Chapterintro
A.1 OMT
Rumbaugh's Object Modeling Technique (OMT) [Rumbaugh 1991] com-
prises of three phases
1. Analysis
2. System design
3. Object design
The input to the analysis is a problem statement and the goal of analysis is to
develop a model of what the system will do. During analysis three models are
built:
* Object model
* Dynamic model
* Functional model
The analysis model is expressed in terms of objects and relationships, dy-
namic control flow, and functional transformations. The output of analysis is
a formal model that captures the objects and their relationships, the dynamic
flow of control and the transformation of data.
Appendix A: OMT
62
A.2 Analysis
The analysis phase consists of the following steps:
1. Write or obtain an initial description of the problem (Problem State-
ment).
2. Build an Object Model.
3. Develop a Dynamic Model.
4. Construct a Functional Model.
5. Verify, iterate, and refine the three models.
Analysis Document = Problem Statement + Object Model + Dynamic Model
+ Functional Model.
Object Model
To build an Object Model:
* Identify object classes.
* Begin a data dictionary containing descriptions of classes, attributes, and
associations.
* Add associations between classes.
* Add attributes for objects and links.
* Organise and simplify object classes using inheritance.
* Test access paths using scenarios and iterate the above steps as neces-
sary.
* Group classes into modules, based on close coupling and related func-
tion.
Object Model = object model diagram + data dictionary
Dynamic Model
To develop a Dynamic Model:
Appendix A: OMT
63
* Prepare scenarios of typical interaction sequences.
* Identify events between objects and prepare an event trace for each sce-
nario.
* Prepare an event flow diagram for the system.
* Develop a state diagram for each class that has important dynamic be-
haviour. Check for consistency and completeness of events shared
among the state diagrams.
Dynamic Model = state diagrams + global event flow diagram + interaction
diagram
Functional Model
To construct a Functional Model:
* Identify input and output values.
* Use data flow diagrams as needed to show functional dependencies.
* Describe what each function does.
* Identify constraints.
* Specify optimization criteria.
Functional Model = data flow diagrams + constraints
Refining
To verify, iterate, and refine the three models:
* Add key operations that were discovered during preparation of the func-
tional model to the object model. Do not show all operations during anal-
ysis as this would clutter the object model; just show the most important
operations.
* Verify that the classes, associations, attributes, and operations are con-
sistent and complete at the chosen level of abstraction. Compare the
three models with the problem statement and relevant domain knowl-
edge, and test the models using scenarios.
Appendix A: OMT
64
* Develop more detailed scenarios (including error conditions) as varia-
tions on the basic scenarios. Use these `what-if' scenarios to further ver-
ify the three models.
* Iterate the above steps as needed to complete the analysis.
A.3 System Design
During system design, the high-level structure of the system is chosen.
1. Organise the system into subsystems (modules).
2. Identify concurrency inherent in the problem.
3. Allocate subsystems to processors and tasks.
4. Choose the basic strategy for implementing data stores in terms of data
structures, files, and databases.
5. Identify global resources and determine mechanisms for controlling ac-
cess to them.
6. Choose an approach to implementing software control:
*use the location within the program to hold state, or
*directly implement a state machine, or
*use concurrent tasks.
7. Consider boundary conditions.
8. Establish trade-off priorities.
System Design Document = structure of basic architecture for the system as
well as high level strategy decisions.
A.4 Object Design
During object design we elaborate the analysis model and provide a detailed
basis for implementation. We make the decisions that are necessary to realise
a system without descending into the particular details of an individual lan-
Appendix A: OMT
65
guage. Object design starts a shift away from the real-world orientation of the
analysis model towards the computer orientation required for a practical im-
plementation.
1. Obtain operations for the object model from the other models.
2. Design algorithms to implement operations.
3. Optimize access paths to data.
4. Implement software control by fleshing out the approach chosen during
system design.
5. Adjust class structure to increase inheritance.
6. Design implementation of associations.
7. Determine the exact representation of object attributes.
8. Package classes and associations into modules.
Design Document = Detailed Object Model + Detailed Dynamic Model +
Detailed Functional Model.
Obtain operations for the object model
* Find an operation for each process in the functional model.
* Define an operation for each event in the dynamic model, depending on
the implementation of control.
Design algorithms
* Choose algorithms that minimise the cost of implementing operations.
* Select data structures appropriate to the algorithms.
* Define new internal classes and operations as necessary.
* Assign responsibility for operations that are not clearly associated with
a single class.
Appendix A: OMT
66
Optimize access paths to data
* Add redundant associations to minimise access cost and maximise con-
venience.
* Rearrange the computation for greater efficiency.
* Save derived values to avoid recombination of complicated expressions.
Adjust class structure
* Rearrange and adjust classes and operations to increase inheritance.
* Abstract common behaviour out of groups of classes.
* Use delegation to share behaviour where inheritance is semantically
invalid.
Design implementation of associations
* Analyse the traversal of associations.
* Implement each association as a distinct object or by adding object-val-
ued attributes to one or both classes in the association.
A.5 Implementation
`Most executable languages are capable of expressing the three aspects of
software specification: data structure, dynamic flow of control, and function-
al transformation.'
`Even when a non-object-oriented language must be used, an object-oriented
design is beneficial. Object-oriented concepts can be mapped into non-ob-
ject-oriented language constructs.'
[Rumbaugh 1991] gives guidance on how to go from an object-oriented de-
sign to a non-object-oriented language, such as C and Ada but he does not
give guidance for functional languages.
Index
88
Index
A
active class 40, 45
active object 7
analysis 27
analysis (OMT) 62
ATM (Automatic Teller Machine) 26
ATM network 27
atom 19
B
BIF (built-in-function) 19
built-in function (BIF) 19
C
class 3
class diagram 29
class manager 44
class partition 36
class specification 34
class-based language 3
clause 19
code replacement (dynamic) 18
cohesion 5
conclusions 55
concurrency 18
concurrent object 7, 41
D
data dictionary 28
data flow diagram 33
declarative programming 18
distributed programming 18
dynamic binding 5
dynamic code replacement 18
dynamic model 29, 62
E
efficiency 53
event flow diagram 31
event trace 30
event-driven 18
F
functional design 59
functional model 32, 63
functional programming 17
future work 55
G
garbage collection 18
Index
89
H
human cognition 3
I
imperative programming 17
implementation - Hobbins 36
implementation (OMT) 66
implementation in Erlang 44
inheritance 4
init 37
integration 3
K
Keisu 7
L
last call optimisation 20
lazy evaluation 17
list 19
M
maintenance 3, 53
measurements 54
memory allocation 18
meta state 37
method 59
module 19
module (in OMT) 42
O
object 3
object design 34, 41
object design (OMT) 64
object model 28, 62
Object Modeling Technique 61
Object Modeling Technique (OMT) 26
object-based language 3
object-orientation 3
object-orientation advantages 3
object-oriented analysis 25, 59
object-oriented design 59
object-oriented language 3
object-oriented programming 60
objects as processes 6
OMT (Object Modeling Technique) 25,
61
operation 60
other 39
P
passive class 40
passive object 7
pattern matching 19
PLEX 16
polymorphism 5
primitive 19
problem statement 27
Index
90
process 2
process dictionary 19
program examples 20
psychological aspects 53
R
real-time garbage collection 18
real-time system 17
recursive call 20
reuse 3, 52
robustness 18
running 37
S
single assignment 18
state transition diagram 32
static passive object 7
stopping 38
structured programming 17
subsystem 41
symbolic language 18
system architecture 33
system design (OMT) 64
T
tuple 19
U
understandability 3