1.1 Programming language
1.2 The key: Data
1.3 The routine as a module
1.4 The class as a module
1.5 Code layout
1.6 Building a system from classes
1.7 Running the system
1.8 Case study/Main points
1.9 Exercise

Chapter 1: Look and feel

Keywords: data, code, routine, class, system, object

This chapter presents the look and feel of object-oriented systems in Eiffel.

Computer code or instructions are placed in a set of small routines in the class.
A class contains both data and the routines that change and use this data, so a class encapsulates both data and code.
The class is designed around the data it contains, and the routines define the behaviour of the class.
An object is an instance of a class; each object has it's own data but shares the routines for that class.

1.1 Programming Languages

A programming language consists of a set of instructions, that can store and retrieve data.
A problem specification defines one or more goals to achieve, plus constraints on the methods or plans that can be used to achieve these goals.
A program is thus a sequence of instructions that produce the data values defined in the problem specification, so we say that the program is a solution to the problem. When the program is run, the code (instructions) in the program read in data values if needed, calculate new values, and store or display the final values.
This is true for any programming language.

There are three main types of programming languages:
   1. Procedural     2. Functional     3. Object-Oriented (OO)
Each (type of programming?) language is based on a different way of grouping actions (instructions in the language) into larger units, so each type of language provides a different way to cut a task into parts.
Each approach provides a different way to see and analyze the problem so each approach defines a different paradigm, a different way of looking at the world, a different way to carve the world up into pieces.

The basic way to define a "larger" action that contains other, detailed actions, is to place the actions or instructions into a set of routines.
A routine is a chunk of code that is executed as a single unit.
A routine is given a name and whenever that name is mentioned in the code, the routine definition is found and all the code inside the routine is executed.
Routines are essential to building any solution, because they allow the programmer to divide a problem into pieces, solve each piece of the problem, and then combine the pieces to solve the overall problem.
Routines provide a basic level of abstraction in problem-solving.

Procedural languages such as Pascal, COBOL, Basic and C, group instructions together into procedures. A procedure changes the value of one or more items of data, and procedures are linked together to define the control flow of the program; procedures are called in serial order and each procedure changes the data as needed, until the final procedure is executed and the final value has been calculated.
Functional languages such as ML, Miranda and Lisp group their instructions into functions, where each function produces a new data value. The functions are connected via their data flow, where one function produces a value that is then used by another function.
In both paradigms, all the data is defined in one part of the program and then the routines are defined in another part of the program, so these paradigms divide the world into two primary parts, data and code; the code is then divided into a set of procedures or functions.

Object-oriented languages such as Eiffel, C++, Smalltalk and CLOS also have procedures and functions so the programmer can group a set of instructions together and execute a routine as a single operation.
In Eiffel, the distinction between procedures and functions is very precise: a procedure changes one or more values, and a function calculates a new value and changes nothing.
Object-oriented languages go beyond the basic level of abstraction, however, because they group routines into a larger chunk called a class. A class consists of a small amount of data, and the routines that (user ..use or?) change this data. An OO system is built by defining the data in the problem, placing each element of data in a class, and defining the routines that use or change the data in the appropriate class.
This approach divides the world into a set of classes and objects.

We use the idea of class every day, without thinking about it.
A class is a way to describe a set of objects that all behave the same way and can thus be used in the same way. We can talk about the way that people behave, for example, without mentioning any particular person. We can talk about planets, moons, stars, ice cream and points without mentioning a particular instance of the class. The class provides a concise way to describe a set of objects and in this approach the world consists of objects and classes, and OO languages provide a formal model for the intuitive ideas of class and object.

A class consists of a set of data and the code that uses or changes that data.
An object is an instance of a class, so each object has its own data but shares the behavior (code). A point, for example, will have a location defined by its x and y values; say the point located at (1, 1). All points share the same behavior and can be used in the same way; we can find the distance between points, display their location, and so on.
All instances of a type or class behave in the same way; that is what we mean by the word "class". The trick in building an OO system is to precisely define and capture that shared behaviour.

It is said that OO languages provide a different approach to programming, and this is true; OO languages provide the high level structure of a class,a level of organisation higher than the function or procedure.
An OO language uses routines like procedural and functional languages, and then wraps the routines in with the data to define a set of classes.
To understand and use an OO language, you need to understand the other approaches and then integrate them into a class structure. OO is not different; it is more.

1.2 The Key: Data

A class is built around the data in that class. In system design, the first and most important decision is to place the data in a class. Once an item of data is defined in a class, the code that uses or changes that data is defined in that class; this is what is meant by the phrase "the code lives with the data". There is no choice about code that changes a data value; in Eiffel, a data value can only be changed by code that is in the same class as the data.
There is a great deal of choice about where to place code that uses a data value, however.

Data is stored in variables. A variable consists of three parts: name, type, and value. The name and (basic) type of a variable do not change, but its value can change as different values are calculated and stored in the variable. The structure of a variable can be drawn like this:

A simple two-dimensional point has a location, described by two real numbers. The data structure of a point is shown to the right below: two variables of type REAL, with names x and y, and values that define the location of the point (say x = 3.0 and y = 4.5). The Eiffel code to define these variables is shown to the left below. The code consists of a class header and a data declaration. The class header defines the name of the class, and the declarations define the form of the data in that class.

When a point (an instance of the class POINT) is created, the computer reserves enough storage to store two real values, and gives the two areas of storage the names x and y.
At some later time, values are then stored in these two variables, to define the location of the point.
Exactly how the computer creates an object and assigns values to the variables is explained in later chapters.

A variable that is defined to store data for the class is called an attribute of the class. Data declarations are normally written at the top of the class, after the Eiffel keyword feature. In Eiffel, both data and routines are called features of the class, so a full class definition consists of both the attributes and the routines in the class.

1.3 The Routine As A Module

A class consists of a small amount of data and a large number of routines that use or change that data.
The data for a class are defined by a set of data declarations, and the routines are defined by a set of routine definitions.
A routine is a chunk of code that has a name, and can be executed as a single unit; this is known as calling the routine.
When the routine is called or executed, all the code inside the routine is executed.
In Eiffel, every line of executable code is placed in some routine; there is no code outside of routines.

Consider a simple bank account. A bank account has a balance, so the data consists (at least) of the balance of the account. The Eiffel code to define the class name and data structure is:-

class  ACCOUNT

creation
      make

feature
      balance: REAL
The routines in an ACCOUNT would then do such things as create an account and set its initial value, deposit money into the account, withdraw money from the account, and show the balance of the account. An Eiffel routine named make to read and store the initial balance of a bank account is shown below, then a routine named deposit that deposits money into the account.
make is
      -- read the initial balance from the user and store it
      do
          io.putstring ("Enter the initial balance: $")
          io.readreal
          balance := io.lastreal

      end   -- make

The name of this routine is make. The routine consists of a routine header (the name and is) followed by a routine comment, followed by a routine body. A comment in Eiffel starts with two minus signs "--"; after this comment marker, any text up to the end of the line is ignored by the computer, so comments are used to communicate with people. The routine body is then coded, enclosed in the keywords do and end. The make routine contains three lines of code to read in a value from the user and store that value in the variable balance.

deposit is
      -- read an amount to deposit, add it to the balance
      do
         io.putstring ("Enter the amount to deposit: $")
          io.readreal
          balance := balance + io.lastreal

      end   -- deposit

The name of this routine is deposit, because it contains the code to deposit money into the account. The deposit routine reads an amount to be deposited, and adds this amount to the current balance.

In Eiffel, routines are small and do a single thing; that is how you get code reuse.
A routine may contain a single line of code, but usually contains several lines of code.
A routine larger than a dozen lines of code is unusual in Eiffel because large routines are often not reusable, although it is common in procedural programming. If you want to execute only part of a routine, you have to re-write the code; it is not possible to call part of a routine.
Small routines are the key to software reuse, because they can be called and combined as needed. Large routines are a very visible and clear indicator that your code is not reusable, and should be re-written as a set of small, reusable routines.

1.4 The class as a module

Both data and code are called features in Eiffel.
A feature can be data, in which case it is called an attribute of the class and stores some value.
A feature can be a routine, in which case it changes or uses an attribute's value; a routine may be a procedure or a function.
A class is composed of a small amount of data and a large number of small routines.

A class definition begins with the keyword class, followed by the name of the class.
The next entry in the class definition is the creation clause, that names the routine used to set any initial values; by convention, the name of this routine is make.
The rest of the class consists of a set of feature's, first the data and then the routines.
The class is terminated by an end statement. A complete Eiffel class listing for a simple ACCOUNT is:

class ACCOUNT

creation
       make

feature
       balance: REAL
       make is
                    -- set the initial balance from user input
             do
                    io.putstring("Enter the initial account balance: ")
                    io.readreal
                    balance := io.lastreal
             end -- get_balance

        deposit is
                     -- read an amount to deposit, add it to the balance
             do
                     io.putstring ("Enter the amount to deposit: $")
                     io.readreal
                     balance := balance + io.lastreal
              end -- deposit

        show is
                     -- display the balance
              do
                      io.putstring ("The account balance is $")
                      io.putreal (balance)
              end -- show

end -- class ACCOUNT
Note that this single class ACCOUNT is not a full system; it cannot be executed by itself. Some other class is needed to call the routines; the class ACCOUNT supplies these routines, but some other class (such as CUSTOMER or BANK) actually uses the account.

A class has the following basic mechanism. The make routine is executed to give the class variables (attributes) some useful value. Once the variables have been given useful values, the other routines in the class are called and executed to use or to change this value. When a system is run, the make routine for the root class is executed, and that routine calls other routines, in its own or in other classes, until the Eiffel system has completed its task. Control then returns to the operating system.

An Eiffel system is built from a set of classes. A class is named as the root class for the system, and the make routine in this class is executed first. That routine calls other routines in the same class or in other classes, and these routines call other routines, until the system has finished execution. An Eiffel system is built by writing a set of classes, then compiling the code into an executable form and executing the compiled system.

The class definition exists when the code has been written and compiled, so we say that the class exists at compile time; it is a compile-time entity. When the compiled code is executed, objects are created and used so we say that an object is a run-time entity. Each object stores its own data, and uses the routines from its class. This is the power of OO languages, that we can define the behaviour of a class of objects, and then create instances of the class - objects - as needed. Each instance has its own data, and all instances share the code of the class. We can thus define the behaviour of an object once, in the class definition, and reuse that code every time we create and use an instance of the class, an object.

A separate text file must be used for each class. The code for a class is stored in its own text file. The Eiffel compiler looks for a text file containing the string class <NAME>, to find the class definition, and assumes there is one class per file. By convention, the name of the text file uses the name of its class; the class ACCOUNT is stored in the file "account.e". This is not necessary - ISE Eiffel searches all the text files in your directory for the class name - but calling the class by one name and the text file by another is sure to lead to confusion.

Common error: A text file contains several classes.
Effect: Eiffel can only find the first class in the text file.
What to do: Use a separate text file for each class definition.

Common error: The name of the class is different from the name of the text file.
Effect: In some versions, Eiffel uses the name of the file to match, so it can't find the class.
What to do: When you have a class X, store it in a file named x.e

Common error: Two classes in your directory have the same name, creating a name clash giving Error code: VSCN.
Error: cluster has two classes with the same name.
What to do: If both classes are needed, change the name of one of them.


1.5 Code layout

Eiffel was designed to support software engineering, and has developed a standard format for coding an Eiffel class. This format is used by Eiffel programmers world-wide. There is no need to invent your own conventions, and in fact it is dangerous to do so.

The Eiffel conventions for class layout are:-

1. The keywords class, creation, and feature are written at the left margin.
2. The name of a class is CAPITALISED. This is true both for classes that you write and for classes in the Eiffel library.
3. A space line separates attributes from routines, and routines in the class.
4. An attribute declaration is indented four spaces from the left margin.
5. A routine header is indented four spaces from the left margin; call this a step. A routine header consists of the routine name, followed by any arguments and terminated by is.
6. A routine header comment is indented three steps from the left margin, to the level of the code. A header comment describes what the routine does, not how it does it.
7. The keywords do and end are indented one step from the header.
8. The code in a routine is indented one step from the do and end.
9. The name of the routine is written as a comment at the end of the routine.

The code in a routine is thus indented on the code listing with the following format:-

routine header: 4 spaces
routine comment: 12 spaces
do: 8 spaces
routine code: 12 spaces
end: 8 spaces
In terms of steps, the format of a routine is 1, 3, 2, 3, 2 steps. This is the international convention.

10. A space is written after every punctuation mark (comma, colon, semi-colon).
11. A space is written before and after an assignment, and a comment marker.
12. The name of the class is written as a comment at the end of the class.

These conventions are the standard solution to the problem of code formatting, and are designed to make the code easy to read. Experienced Eiffel programmers expect Eiffel systems to follow this format, and find it difficult to understand code written in some other notation. Good indenting is the most important of these conventions; good indenting makes the structure of the code obvious to the reader.

The typefaces in this book follow the standard Eiffel manuscript format (Meyer, 1992). Eiffel keywords are shown in bold face, comments are shown in plain text, and the executable code is shown in italics. This is the convention used to write about Eiffel; the conventions used to format Eiffel code are given above.

1.6 Building a system from classes

The basic interaction in an Eiffel system is captured in a client chart (Meyer, 1992). The client-supplier relationship is the most basic relation between classes, and reflects the common-sense idea of client and supplier. When you use the services of someone else, such as a lawyer, a doctor, or a plumber, then you are a client of that person. In the same way, one class is a client of another if it uses the services provided by that second class. In the example here, class CUSTOMER is a client of class ACCOUNT because it uses or calls the account features. This is known as a client-supplier relationship, in which class CUSTOMER is the client, that uses the services or features supplied by the class ACCOUNT.

The "top" level of control in an Eiffel system is provided by the root class, the class that starts and then controls the execution of an Eiffel system. We can describe the class structure of a very simple banking system with a client chart such as that shown below. An oval contains a class name, and an arrow is drawn from left to right, from client to supplier, to indicate that the client calls or uses one or more features defined in the supplier.

A system of three classes is shown in the chart: BANK, CUSTOMER, and ACCOUNT. The BANK class is the root class for this system, shown to the far left of the diagram. When the system is run, code (instructions) in the BANK class calls routines in the CUSTOMER class, then code in these routines call routines in the ACCOUNT class. The code in the ACCOUNT class is executed, then control returns back to the CUSTOMER, then back to the BANK; after all the code has been executed, the system terminates and returns control back to the computer system.

Informally, a client relation means that the client "has", "uses", or "contains" the supplier; a bank has customers, and a customer uses a bank account. In terms of Eiffel code, we can say that a client-supplier relation is defined when a client class C uses features of a supplier class S, but this is still an informal definition. Formally, a client arrow is drawn from the client to the supplier if and only if a class C declares a variable of type S.

1.7 Running an Eiffel system

The code in a text file is a series of characters; a computer only speaksbinary, so the text is not executable by the computer. It is converted to executable code by compiling the system.
To compile an Eiffel system, you need to define a separate file, called an Ace file (Assemblyof classes in Eiffel) in ISE Eiffel.
In the Ace file, you tell the compiler the name of your root class, the name of the creation routine in that class, and the directory where you have stored your Eiffel text files. When you then run the Eiffel compiler, it looks in the Ace file in your current directory to get the starting information, finds the file for the root class, and from the root class automatically finds and links all the connected classes into a single executable file for the whole system.
The name of this executable file is also specified in the Ace file.

The Eiffel compiler first checks the syntax of your system, then converts the Eiffel code to C code, and then converts the C code to executable code. The C code is kept in a special file created by the system, so a compilation can create many new files on your system. Eiffel has a smart compiler, so a class is recompiled only if it has been changed; any existing, unchanged classes are not recompiled. This is known as "melting ice" technology, where most of the system can be thought of a frozen (unchanged) and only a small part has to be recompiled.

The system is executed when the executable file is run on your computer.
When you run the system, Eiffel creates an object for the root class and executes the creation routine of the root class, that then creates the other objects and calls their features as necessary.

1.7.1 A simple class

The simplest Eiffel system that does something visible is a single class with one output.
The single class is, of course, the root class for the system; in fact, it is the whole system.
In programming, the sample program that prints a message is usually called the "Hello world" program. Here's the Australian version:

class HELLO

creation
       make

feature
      make is
                   -- say hello to the world
             do
                   io.putstring ("%NG'day mate%N")
             end -- make

end -- class HELLO

When this system executes, Eiffel runs the creation routine of the root class.
Usually, this routine then creates other objects and calls other routines; here, the creation routine outputs a message and calls no other routines. The effect of coding, compiling, and running this system is to produce the message, "G'day mate" on the display screen.

1.7.2 A simple Ace file

To create an Ace file, first make a directory named eiffel to store your Eiffel files.
To get an Ace file, copy the file /pub/psda/Ace into your eiffel directory as Ace.
Edit this full Ace file so it looks like that shown below. This minimal Ace file tells the compiler that the name of the root class is HELLO, that the creation routine in that class is named make, and that the final executable file will be called "gday". It also tells the compiler to find the root class and all your Eiffel classes in your working directory (eiffel: "./"), to look for any other Eiffel files in the Eiffel kernel library, and to use the precompiled Eiffel files.
Make your Ace file look exactly likethis: indent four spaces, no extra space lines.

system
         gday
root
         HELLO: "make"
default
         assertion (require);
         precompiled ("$EIFFEL3/precompiled/spec/$PLATFORM/base")
cluster
         eiffel: "./";
         kernel: "$EIFFEL3/library/base/kernel";
end

An Ace file contains the following information:

1. After the keyword system, write the name of your executable system file (lower case).
2. After the keyword root, write the name of your root class (upper case) and the name of its creation routine (lower case); by convention, a creation routine has the name "make".
3. After the keyword default, the Ace file lists the assertion checking status and any pre-compiled libraries.
4. After the keyword cluster, the Ace file lists where to find the files to compile; a cluster is to a directory that contains a set of Eiffel files. The first line in the example below (eiffel: "/";) tells the compiler to look in your current directory for your files.
The second line says to use the Eiffel kernel files found in the given directory; for the first lab, you only need the kernel Eiffel files.
An Ace file should have only the clusters that you need, because more clusters means a longer compile.

The default and cluster sections can usually be ignored when you edit an Ace file. Basically, you need to tell the Eiffel compiler

and Eiffel can then find your code and compile it, when you tell Eiffel to compile using eifstart.

1.7.3 eifstart

The eifstart command is a special command written for the SoCS computer system. When you enter this command, it gets your Ace file (from your current directory) and uses it to compile a new system. Because Eiffel uses a "melting ice" approach to compilation, you only run eifstartto get an initial compilation. Once your system compiles and you have an executable file, you then use the SoCS command eif to re-compile a changed system, so almost all the time you will use eif to add new changes to your existing system. eifstart can take a very long time to run because it compiles every line of code in the system, where eif is very quick.

When you run a compile command (eifstart or eif), you start a long sequence of actions. The Eiffel compiler will write a display to your screen such as:


$ eifstart
SoCS Eiffel Compilation Suite - eifstart
Starting compile
Eiffel compilation manager
    (Version 3.3.7)
Degree 6: cluster eiffel
Degree 5: class HELLO
Degree 4: class HELLO
Degree 3: class HELLO
Degree 2: class HELLO
Degree 1: class HELLO
Melting changes
System recompiled.
Moving executable gday to current directory <your current directory>
Done.

The eifstart and eif commands look in your Ace file to find your root class and creation routine, and compile the rest of the system from there. The eifstart command creates a subdirectory EIFGEN in your working directory, and below that COMP, F_code and W_code. Eiffel puts various files in these directories; it puts the executable system file in the directory /EIFGEN/W_code and then the SoCS command moves it from there to your current directory.

eifstart and eif only exist on the SoCS computer system; they are not a standard part of Eiffel. If you use other compilers or other computers, then you should go through similar actions and see similar output, but it will probably be more complex and take a lot longer because the SoCS system translates Eiffel directly into byte code and skips the normal C compilation.

Common errors

1. No Ace file. You are told: No Ace file in current directory. Giving up.

2. No root class, or it is stored under some strange name so Eiffel can't find it. You are told:
    Error code: VD30
    Lace error: Root clause lists improper identifier as root class name

You need to change either
3.Class with this name cannot be found. Your code has referred to a class named X, but there is no class X definition
      in your current directory,or in the Eiffel library. You are told:
        Error code: VTCT
      Error: Type is based on unknown class
      What to do: use an identifier that is the name of a class in the universe.

"The universe" consists of the directories named in the Ace file; the class definitions are the universe for an Ace file.
 These are usually the current    directory and the Eiffel library directories.
4. The Ace file specifies a class that is not the root class. Eiffel will do exactly what you have told it do: compile a system starting at the specified class. The compilation may even succeed, but the system will be smaller than you expect when you execute it.
1.7.4 The system file

You can now run the system by typing the name of the executable file, here gday.

$ gday

The system will execute, ask for any input data (none in this case) and show the message

G'day mate

1.7.5 eif

To compile a changed system (new code, same root class),eif melts (re-compiles) the changed code and merges the old and new compiled code.
A re-compilation has the same passes as eifstart, but it is quicker.
After a lot of changes, eif becomes inefficient and you need to delete the system files (including EIFGEN), produce a new executable file (with eifstart) and then later add any new changes (with eif) to that new version.

1.8 Case study: look and feel

Each chapter in this text has a corresponding case study, that showshow the ideas in the chapter are used to develop a working system.
The first part of the case study sets and changes the balance of an account, to illustrate the look and feel of a class with simple data flow.

Main points in this chapter

• A traditional language cuts the world into two parts, data and code, and keeps the data separate from the code. An OO system cuts the world into a set of classes, where each class contains both data and code.

• A class is designed around its data (attributes), and contains both the data and the code (routines) that uses or changes that data. A routine may be a procedure or a function.

• A class consists of a small number of attributes, and a large number of small routines.

• The Eiffel code layout convention was designed to make code easier to read.

• The class defines the behaviour of all objects of that type. An object is an instance of the class. Each object stores its own data values, and all objects of that type share the code in the class definition.

• An Eiffel system is compiled from the Ace file in the directory. The Eiffel class (text) files are also in the current directory.

• An Eiffel system is run by typing in the name of the executable file.The system starts by executing the make routine for the root class, and following any routine calls from there.

Exercises

1. Define the following terms:

• code
• attribute
• routine
• class
• object
• supplier class
• client class
• root class
• client chart
• system

2. What is the format of a class definition?

3. What are the three parts of a variable?

4. What is the format of a data declaration?

5. What is the format of a routine definition?

6. Why is indentation important? How far is a header comment indented? What does a header comment describe?

7. What is the difference in behaviour between a procedure and a function? How are procedures connected in a program? How are functions connected in a program?

8. How is a routine called?

9. Run the "hello world" system.