You are on page 1of 12

1

Mekelle University Faculty of Business & Economics

Computer Science Department

ICT122: Object-Oriented Programming

Handout 5 – Object-Oriented Design

Handout Overview

This handout describes the object-oriented design process, and the way in which it
differs from the conventional design process. The four phases of the object-oriented
design process are described and then illustrated with a case study.

1. Object-Oriented Design

Before beginning to write a piece of software it is always necessary to design the


program first. Designing an object-oriented program involves a different way of
thinking to designing a traditional procedural program.

1.1. The object-oriented view of the world

In object-oriented programming an application is viewed as a system of


interacting objects. The objects each represent a thing in the real world, and
interact by sending messages to each other and responding in certain ways when
they receive such messages.

The object-oriented design process can be divided into four main stages:
• Identify the objects
• Determine the relationships between the objects
• Determine the attribute/behaviours of the objects
• Design the driver

1.1.1.Identify the objects

In order to identify what objects your program should have you will need to
review the problem specification. Remember that classes represent things: a
student is a thing, as is a foreign student, etc. Try to work out what things
your program will need to deal with and note them down as potential classes.
2

1.1.2.Determine the relationships

Next analyse the relationships between these potential classes: for example a
foreign student and a student are clearly related. But what type of
relationship is it? In Handout 1 three types of relationship were introduced:
is-a relationships, has-a relationships and uses-a relationships.

Remember that you should use is-a relationships when one object is a type
of another object. You should use has-a relationships when one object
contains another object. Uses-a relationships are less easy to define and less
common. As an example, suppose we have a Clock class that has a public
member function currentTime() that returns the current system time. If
another object in the program wanted to know the system time it would need
to use the Clock class, so it would send a message to a Clock object asking it
to execute the currentTime() function. The Clock object would then
send a message back indicating the current time. Uses-a relationships are
generally implemented by classes sending messages to each other, as in this
example.

Once you have identified potential classes and the relationships between
them, this should help you to sketch out an inheritance hierarchy for your
program.

1.1.3.Determine the attributes and behaviours of the objects

The operation of an object-oriented program is defined by the way in which


its objects interact. By identifying the interactions that are necessary to
make a program work correctly we can then decide what behaviours and
attributes each object should have. The interactions between objects are
defined by their public interfaces. The public interface to an object is the set
of public data members and member functions. Think about whether a
particular operation is common to an entire hierarchy or is specific to a
particular subtype. This should help you to decide which object should
contain the operation. If it is common to an entire hierarchy is it a type-
dependent virtual operation or will it be the same for every type in the
hierarchy? Finally ask yourself if the operation should be available to the
entire program, restricted to the class hierarchy, or restricted to the
individual class (i.e. public, protected or private)?

Once we have decided how the objects will interact, we need to think about
what responsibilities object will have. For example, if the interaction
between object A and object B involves object A sending a message
requesting a particular operation from object B, then it is the responsibility
of object B to perform that operation. The responsibilities of an object can
3

involve both behaviours (i.e. operations) and attributes (i.e. storing data).
These equate to data members and member functions in C++.

1.1.4.Design the driver

Finally, now that we have defined the objects, their public interfaces and
their behaviours and attributes, we need to design the driver. You can think
of the driver as being the glue that binds the objects together, or the main
algorithm of the program that makes use of the objects. In C++ the driver
corresponds to the main function.

1.1.5.Program design is an iterative process

Once you have completed and reviewed these four steps, you can produce a
prototype implementation. Often in producing this prototype you may realise
that you need to go back to the first two steps and modify your class
hierarchy. Program design is always an iterative process: you will go through
a number of cycles, or iterations, before you reach a design and
implementation you are happy with.

Like traditional program design you only really become skilled and
confident at object-oriented design by practice, so do not worry too much if
it does not come naturally at first. Practice makes perfect …
4

2. Case study – A Vehicle Database

The concepts describe above may become clearer if we go through an example.


Consider the program requirements for a vehicle database program given below.

2.1. Program Requirements

A large company manufactures a range of different vehicles. They would like to


have some computer software that stores information about the vehicles they
produce. The following information may be useful in designing the program:
• The company produces both wheeled vehicles and boats. If a vehicle is a
wheeled vehicle it can be either a car or a bicycle.
• For all vehicles the company would like to store the following
information: the number of people the vehicle can hold, its top speed,
model name and cost.
• If a vehicle is a wheeled vehicle we should also store the number of
wheels.
• For all cars, we should store the fuel tank capacity (in litres) and the fuel
efficiency (in km/litre).
• For all bicycles we should store the number of gears, and a category
(mountain bike or racing bike).
• For all boats we should store a category (rowing boat, speedboat, dinghy
or yacht).
• For all vehicles, there should be a function that calculates the registration
cost. The actual cost is different for each vehicle type:
o Bicycles: 55 Birr
o Cars: 10 Birr x fuel tank capacity
o Boats: 100 Birr for rowing boats, 1000 Birr for speedboats, 200
Birr for dinghies, 10000 Birr for yachts

2.2. Identifying the Objects

The first stage in the design of our program is to identify the objects that our
application will consist of. Looking through the program requirements and
choosing the nouns is usually a good start. Doing this with our requirements gives
us the following potential objects:
company vehicle computer software
wheeled vehicle boat car
bicycle people top speed
model name cost wheel
fuel tank capacity fuel efficiency gears
mountain bike racing bike rowing boat
5

speedboat dinghy yacht


It is likely that not all of these nouns will become objects in our program, so let us
examine them a bit more closely. A number of the candidates are clearly not
relevant to our solution: for example objects based on the company, people and
computer software would not have any useful properties or operations for us.

2.3. Interaction/Relationships Between Objects

Next we must determine what interactions and relationships there are between our
potential objects. A glance through the remaining candidates reveals a number of
obvious is-a relationships,
a wheeled vehicle is-a vehicle;
a boat is-a vehicle;
a car is-a wheeled vehicle;
a bicycle is-a wheeled vehicle;
a mountain bike is-a bicycle;
a racing bike is-a bicycle;
a rowing boat is-a boat;
a speedboat is-a boat;
a dinghy is-a boat;
a yacht is-a boat;
and also a number of has-a relationships,
a vehicle has-a top speed;
a vehicle has-a model name;
a vehicle has-a cost;
a wheeled vehicle has-a wheel;
a car has-a fuel tank capacity;
a car has-a fuel efficiency;
a bicycle has-a gears.

We know from the discussion in Handout 2 regarding inheritance and composition


that generally is-a relationships imply inheritance, and has-a relationships imply
composition. However, we have not yet finally decided if all of our candidates
will become objects in our program. We need to decide if they have any properties
or operations that will be useful for the program, or are they simply data that need
to be stored. For example, the requirements state that we need to store the number
of gears for all bicycles, but there is no requirement to include any other
information or operations about gears, so it would seem that defining a gear
object is unnecessary in this case. Similarly, mountain bike and racing bike are
types of bicycle, but defining objects of these types would not be useful to us. For
boats, on the other hand, we need to store a category and be able to calculate the
registration cost.

Bearing all this in mind, we can sketch out an initial inheritance hierarchy for our
program. Figure 1 shows such a hierarchy. The is-a relationship between boats
6

and vehicles means that the boat class inherits, or derives, from the vehicle class.
Similarly wheeled vehicle derives from vehicle, and both car and bicycle derive
from wheeled vehicle. Notice that we have now selected five of the candidates to
be objects in our solution domain. Many of the remaining candidates will
reappear when we start to add data members and member functions to these
objects in the next phase.

Figure 1 – An inheritance hierarchy for the vehicle database program

2.4. Determining Attributes and Behaviours

Now we must decide what information each of the 5 objects needs to store, and
what operations they need to perform. To determine this, we can use the
remaining nouns from our list of candidates, and refer to the initial program
requirements. For example, for the top speed the requirements state that this value
must be stored for every vehicle, so this item should be added as a data member in
the vehicle class. All classes that derive from vehicle, whether directly or
indirectly, will then inherit this data member. The mountain bike and racing bike
items are really just alternative values for a category data member, which should
be stored in the bicycle class. The requirements also specify that for every vehicle
we should be able to calculate the registration cost. Therefore we should add a
member function to the vehicle class. However, the requirements also state that
the nature of this calculation will be different for cars, bicycles and boats, so in
this case the function should be a virtual function. (Remember from Handout 2
that virtual functions define type-dependent operations in an inheritance
hierarchy.) In addition, we do not want the vehicle class to provide an
implementation of this function (only car, bicycle and boat should provide
implementations) so it should be a pure virtual function. We can now expand our
inheritance hierarchy to include attributes (i.e. data members) and behaviours
(member functions).
7

Class Attributes Behaviours


Number of people,
Top speed, Calculate registration cost
Vehicle
Model name, (pure virtual function)
Cost
Wheeled
Number of wheels
Vehicle
Fuel tank capacity,
Car
Fuel efficiency
Number of gears,
Bicycle Category (racing bike or
mountain bike)
Category (rowing boat,
Boat
speedboat, dinghy or yacht)

2.5. Design the Driver

The final stage of the design process is to design the driver of the program. For
C++ programs, this means deciding what the main function will do, and how it
will use the classes that we have defined. In our case, the program requirements
do not state what the database should be used for, so this stage is not important.
We could, if we wanted to, design a user-interface that lets a user interact with out
database of vehicles. However, for the purposes of demonstration we will just
design a simple main function that creates a few objects and calls the member
functions.

2.6. Code Listing

The full code listing for the vehicle database case study is shown below. The
source code is split into 3 files: “Vehicle.h” contains the class definitions;
“Vehicle.cpp” contains the function bodies; and “VehicleTest.cpp” contains the
main function.

Notice that we have used information hiding to hide the implementation details of
the classes from the rest of the program. The data members are all defined as
protected, and public member functions are used to assign values to them.
These public member functions define the public interface of the class.
8

“Vehicle.h”

class Vehicle {
protected:
int people;
float speed;
char *model;
float cost;
public:
void SetPeople (int p) {people = p;}
void SetSpeed (float s) {speed = s;}
void SetModel (char *m) {model = m;}
void SetCost (float c) {cost = c;}
virtual float CalcRegistration() = 0;
};

class WheeledVehicle: public Vehicle {


protected:
int wheels;
public:
void SetWheels (int w) {wheels = w;}
};

class Car: public WheeledVehicle {


protected:
float capacity;
float efficiency;
public:
void SetTankCapacity(float c) {capacity = c;}
void SetFuelEfficiency(float e) {efficiency = e;}
float CalcRegistration();
};

enum BikeCat {mountain, racing};


class Bicycle: public WheeledVehicle {
protected:
int gears;
BikeCat category;
public:
void SetGears (int g) {gears = g;}
void SetCategory (BikeCat c) {category = c;}
float CalcRegistration();
};

enum BoatCat {rowing, speedboat, dinghy, yacht};


class Boat: public Vehicle {
protected:
BoatCat category;
public:
void SetCategory (BoatCat c) {category = c;}
float CalcRegistration();
};
9

“Vehicle.cpp”
#include "Vehicle.h"

float Car::CalcRegistration () {
return (10 * tank_capacity);
}

float Bicycle::CalcRegistration () {
return 55;
}

float Boat::CalcRegistration () {
float reg = 0;
switch (category) {
case rowing: reg = 100;
break;
case speedboat: reg = 1000;
break;
case dinghy: reg = 200;
break;
case yacht: reg = 10000;
break;
};
return reg;
}

“VehicleTest.cpp”
#include <iostream.h>
#include "Vehicle.h"

main () {
Car c; //test out the car class
c.SetPeople(4);
c.SetSpeed(95);
c.SetModel("Lada");
c.SetCost(20000);
c.SetWheels(4);
c.SetTankCapacity(100);
c.SetFuelEfficiency(10);
cout << "Registration cost for Lada = "
<< c.CalcRegistration() << endl;

Bicycle b; //test out the bicycle class


b.SetPeople(1);
b.SetSpeed(20);
b.SetModel("Dolphin");
b.SetCost(120);
b.SetWheels(2);
b.SetGears(15);
b.SetCategory(mountain);
cout << "Registration cost for Dolphin = "
<< b.CalcRegistration() << endl;
10

Boat bt; //test out the boat class


bt.SetPeople(1500);
bt.SetSpeed(45);
bt.SetModel("Titanic");
bt.SetCost(1000000);
bt.SetCategory(yacht);
cout << "Registration cost for Titanic = "
<< bt.CalcRegistration() << endl;
}
11

Summary of Key Points

• In object-oriented programming an application is viewed as a system of


interacting objects. Each object represents a thing in the real world.
• Objects interact by sending and receiving messages and responding in certain
ways when they receive such messages.
• The object-oriented design process can be divided into four main phases:
identify the objects, determine the relationships between the objects,
determine the attributes and behaviours of the objects, and design the driver.
• As objects correspond to things in the real world, a good first attempt and
identifying the objects is to look for the nouns in the program requirements.
• Relationships between objects can be is-a, has-a or uses-a relationships.
• Is-a relationships imply an inheritance relation between two objects.
• Has-a relationships imply that composition should be used.
• Uses-a relationships indicate that the relationship should be modelled by
sending messages between the classes.
• The logical properties of an object are defined by the public interface to the
class (i.e. the set of public data members and member functions).
• The driver is the code that determines what objects will be created and what
messages will be sent. In C++ the driver is the main function.
• Program design is an iterative process. After completing the four stages of the
object-oriented design process, it may be necessary to review earlier stages
and modify the decisions made.

Note: The full source code listings for the example in this handout can be found on the
FBE network server: to access them, open My Network Places, double-click on
MU-FBE, then FBE-SERVER and then browse to:
Courses\ICT122 – Object-Oriented Programming\src\Handout 5

Notes prepared by: FBE Computer Science Department.


12

You might also like