# 2 Application Development

Chapter 1 used a rather simple application as example. This chapter shows how to use functors for the modular development of larger applications.

## 2.1 Functors for Modular Applications

Principles of good software engineering suggest that larger applications should be designed and assembled from a collection of smaller modules. In Oz, this decomposition can be realized in terms of several functor definitions.

The primary purpose of a functor is to compute a module: It takes modules as input and computes a new module as output. As we have seen already, the `import` section of a functor specifies its inputs as a list of module names. In addition, functors may also have an `export` section which is basically a list of feature/value pairs that describes the module computed by the functor.

As demonstrated in Section 1.5 an application is run by executing the root functor. In our particular example, the root functor was rather simple in that it only imported system modules. However, larger applications will typically import modules computed by other application functors.

## 2.2 Example: Last Minute Flights

In the following we will build a trivial flight booking system featuring three components:

1. A data base server: It maintains a data base that contains available flights, where each flight has a unique id by which it can be identified. At first, the data base is not even persistent, but as we incrementally refine and improve our application, the data base evolves into a persistent and distributed data base server.

2. A graphical flight booking form, where a travel-minded user can choose a flight, enter her name, her E-mail address and so on. Later we will show how to build a web-based interface serving the same purpose.

3. The main component of our application that manages user requests to the data base and sets up the application.

All components are programmed as functors.

## 2.3 The Data Base

Let us start with the data base, which is the most straightforward part of our application. The data will be held in a dictionary that uses integers as keys, and arbitrary data structures as entries. The functor definition resides in file `DB.oz` and its toplevel structure is as follows:

<DB.oz>=
  `functor
  ` < Export specification for DB.oz >`
  ` < Body for DB.oz >`
  end`

The functor has no import specification, and its export specification is as follows:

<Export specification for DB.oz>=
  `export
  add: Add
  get: Get
  getAll: GetAll
  remove: Remove`

The specification determines that the functor's module provides the features `add`, `get`, `getAll`, and `remove`, where the value of each feature is given by the variable after the following colon. The values of these variables are then computed by the functor's body.

For convenience, the export specification above may also be written more succinctly as follows:

<Export specification for DB.oz (with syntactic sugar)>=
  `export
  Add
  Get
  GetAll
  Remove`

The shortcut to just use a variable identifier starting with a capital letter, defines both the variable identifier as well as the feature. The feature is the variable identifier with its first character changed to lowercase.

The functor body is of less importance to us here, however, you can find it in Section A.1. One advantage of modular program development is that during the design of an application one may concentrate first on finding the right interfaces, and only then provide corresponding implementations.

Even though the functor does not import any module, it uses predefined procedures (for example, `Dictionary.new` to create a new dictionary). The compiler provides a set of variable identifiers, that refer to the basic operations on all primitive Oz data types. This set of identifiers is known as the base environment and is documented in detail in ``The Oz Base Environment''.

When a functor definition is compiled, all free variable identifiers must be bound by the base environment.

## 2.4 The Graphical Input Form

The functor that implements the graphical form to book flights has the following structure, and its definition resides in file `Form.oz`:

<Form.oz>=
  `functor
  import
  Tk
  export
  Book
  define
  proc {Book Fs ?Get}
  %% Takes a list of flights and returns the booked flight
  %% and information on the booking user
  ` < Implementation of Book >`
  end
  end
  `

## 2.5 The Root Functor

The root functor for our last minute flights application uses the previously defined functors that maintain the data base and that provide the user form. The root functor's definition resides in file `LMF.oz`:

<LMF.oz>=
  `functor
  import
  DB Form % User defined
  System Application % System
  define
  %% Enter some flights
  {ForAll` < Sample flights >`DB.add}
  %% Book until all flights sold out
  proc {Book}
  case {DB.getAll}
  of nil then
  {System.showInfo 'All flights sold.'}
  [] Fs then
  O={Form.book Fs}
  in
  {System.showInfo ('Booked: '#O.key#
  ' for: '#O.first#
  ' '#O.last#
  ' ('#O.email#')')}
  {DB.remove O.key}
  {Book}
  end
  end
  {Book}
  {Application.exit 0}
  end
  `

## 2.6 Compilation

Functors also are compilation units. Each functor definition is compiled separately. For our example, the following sequence of commands

> `ozc -c DB.oz -o DB.ozf
> ozc -c Form.oz -o Form.ozf
> ozc -c LMF.oz -o LMF.oza`

compiles our example functor definitions. If you now change the functor definition in, say, `DB.oz` but the interface of the created functor remains the same, none of the other functor definitions need recompilation.

Note that we have chosen as file extensions for pickled functors that are not supposed to be run as applications the string `ozf`. For the root functor of our application we chose `oza`. This is completely transparent as it comes to the semantics of our program, it is just a convention that makes it easier to tell apart which pickled functors are root functors of applications.

## 2.7 Execution

As before, we just execute the root functor of our application by applying the `ozengine` command to `LMF.oza`:

> `ozengine LMF.oza`

The next chapter (Chapter 5) explains how applications that consist of several functors are executed.