Software Engineering I

Introduction to Modules & Objects

 

 

 

To understand the concept of an object we must first be clear about the concept of a module. The desirable features for a module overlap with the formulation of objects.

 

A module is defined as

 

“A set of one or more contiguous program statements having a name by which other parts of the system can invoke it, and preferably having its own distinct set of variable names. ” – Stevens, Myers & Constantine

 

To rate a module we examine two factors: -

 

Coupling - This is the degree of interaction between modules; i.e. their inter-relationships

 

Cohesion – This is the degree of interaction between statements in a module.

 

* Good modules exhibit low coupling but high cohesion

 

We will address these two factors as follows,

 

 

Cohesion

 

There are several types of cohesion. We rank them going from the worst form of cohesion to the best

 

·        Coincidental                      (bad)

·        Logical

·        Temporal

·        Procedural

·        Communicational

·        Informational

·        Functional                            (good)

 

Note. This scale is a relative one; a module may contain some or all of these types to one extent or another.

 

Coincidental Cohesion: This is the worst form of cohesion. This is where a module performs multiple unrelated tasks. This may occur if modules are not properly designed.

 

Logical Cohesion: Here modules can perform a series of related tasks, however only one is selected by the calling module.

 

Temporal Cohesion: The module performs a series of actions that are related in time. E.g. all startup/shutdown activities are brought together.

 

Procedural Cohesion: Here elements in a module perform a sequence of steps to be followed by the product. The elements in the module thus make up a single control sequence and must be executed in specific order.

 

Communicational Cohesion: All elements operate on the same input data set or produce the same output data set.

 

Informational (Sequential) Cohesion: Output from one element in the module serves as input for some other element. Unlike logical cohesion the code for each action is completely independent. A module with informational cohesion is essentially an ADT (abstract data type) and all the benefits of using an ADT are gained when this type of cohesion is employed in a module. Such a module operates on the same data structure. Objects (when well designed) are modules that exhibit informational cohesion.

 

Functional Cohesion: Module contains elements that perform exactly one function or achieves a single goal.

 

 

 

Coupling

 

There are also several kinds of coupling, which we rate as follows -:

 

·        Content       (bad)

·        Common

·        Control

·        Stamp

·        Data            (good)

 

 

 

Content Coupling: This occurs when one module directly references the contents of another module. E.g. module x branches to a local label in module y or module x modifies a statement of module y. Such modules are inextricably linked to each other.

-         Content coupling is quite dangerous.

 

 

Common Coupling: This occurs when several modules have access to the same global data. E.g. use of the C++ modifier public

-         Common coupling contradicts the structured programming concept and is quite undesirable

 

 

Control Coupling: This occurs when one module has control over the logic of another. If module x calls module y and y determines what action x must take then control coupling is present. The passing of a control switch statement as an argument is an example of control coupling.

 

Stamp Coupling: This is the case where entire data structures are passed to the called module but only some individual fields are used. E.g. pointer passing in C. Note. Not all the elements in the data structure are acted upon by the called module.

 

Data Coupling: Two modules are data coupled if all arguments are homogeneous data items. If a data structure is passed then the called module must use all the fields. Data coupling is a desirable goal. Modules which are data coupled are easier to maintain since changes in one is less likely to cause a regression fault in the other.

 

Key Terms

 

The following terms are important when considering modules and objects.

 

Encapsulation – gathering together into one unit all aspects of the real world entity modeled by that unit

 

Abstract Data Type – Entity that combines a data type with actions performed on instances of that type

 

Information Hiding – Designing a module in such a way that the implementation details are hidden from other modules

 

Class – An abstract data type that supports inheritance e.g. a rocking chair may be a class, derived from the class chair, which in turn may be derived from the class furniture

 

Object – An instance of a class e.g. your grandma’s rocking chair would be an instance of a class or (put another way) an object of the rocking chair class

 

Method – This is the name given to any function that belongs to a particular class.

 

Note. Terms class and object sometimes used interchangeably in certain texts

 

 

Objects

 

An object may be thought of as a module exhibiting informational (sequential) cohesion but also having other properties as well.

Objects support data hiding and encapsulation but have an extended characteristic called inheritance. The basic idea of inheritance is that newly defined data types can be made as extensions of existing ones, rather than having to be defined from scratch.

 

Inheritance

 

Objects attempt to model the real world so let us consider an example from the real world. For example, a passenger car is an object. More abstractly we could say that a passenger car is a motor vehicle. We might also say that a motor vehicle is a vehicle. This “is a “ relationship is known as inheritance.

 

We can place the information in a diagram by drawing the inheritance hierarchy:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Inheritance Hierarchy

 

 

 

 

We say that Vehicle is the parent (or base) class. Boat would be an example of a child class (with respect to Vehicle) and also a parent (with respect to Sail Boat). Note that a Sail boat ISA Boat and a Boat ISA Vehicle.

Consider the C++ code segment below

 

class HumanBeing

{

 private:

 

          int age;

          float height;

          float weight;

          enum {male,female} gender;

 

  public: // find here the declaration of operations on human beings

 

 

}; // class HumanBeing

 

class Parent:public HumanBeing // Parent inherits from HumanBeing

{

   private:

             char nameoffirstborn[30];

             int numberofchildren;

   public:

           // find here the declaration of operations on Parent

 

 

 

}; // class Parent

 

C++ Implementation

 

 

Class Parent inherits all the attributes of the HumanBeing Class because Parent is derived from HumanBeing. If Ted is an instance of class Parent (i.e. an object) then Ted has all the attributes of a Parent, but also inherits all the attributes of a human being. In other words Ted the Parent ISA HumanBeing.

 

·        We may say a Parent is a specialization of a HumanBeing, or a HumanBeing is a generalization of a Parent.

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Diagram of two classes demonstrating an inheritance relationship

 

 

 

 

 

Polymorphism & Dynamic Binding

 

This is another key feature of Object Oriented programming. The word polymorphism means many (“Poly”) forms (“morph---“).

 

 

Consider the following –

 

A base class called FileManager is created which allows files to be added, deleted, updated etc. on a computer system.

 

Later three derived classes are added (i.e. they inherit properties of the base class)

 

See Diagram below…

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Diagram of 3 classes inheriting from a base class

 

 

Suppose we need to implement an open() method (i.e. a function to handle file opening in the class) we have a number of options including the 3 following major ones: -

 

1)      Implement an open() method for each class giving 4 distinct open() methods …

 

 

2)      Implement an open() method for the base class only and allow the three derived classes to inherit it from the base.

 

3)      Make the open() function polymorphic

 

 

 

 

 

 

 

Option 1:  To pursue this option would mean ignoring the power of inheritance. The open() methods in this case would all be tied to a particular object when the program is compiled. There might also be a difficulty in providing an open() for the FileManager (ancestor/parent object) since this would represent a generic (i.e. abstract) open().

 

Option 2: This option is more attractive than the first one except that three distinct types of storage media may require different actions to be carried out. E.g. a tape needs to be wound forwards/backwards while a disk must be spun etc.

 

Option 3: To use polymorphism in C++ a dummy open() method would be declared in the base class  (.. this method specified as virtual in C++) . For each of the derived classes a distinct corresponding open() would be provided, each with its own unique code.

Now suppose we declare an object called Filer of type FileManager. When Filer.open() is run the system at that point in time will determine dynamically (this is called dynamic binding) which of the three open() methods (for Disk, CD-R or Tape) to run.

This strategy works because a derived class object “IS A” base class object. Note. The open() in FileManager is only a placeholder (and cannot actually run) due to the present of the keyword virtual.

Due to the open() method being applied to objects (i.e. instances) of different classes we say it is polymorphic or exhibits polymorphism. (Note. In C++ all virtual methods in a base class must be redefined in the derived class. The compiler will enforce this constraint.)

 

Caveat: Polymorphism/dynamic binding may cause a negative impact on maintenance. Determining which method (..in the case where many derived classes of the same base class are in existence.) was invoked can be a time consuming process.