Unit 3 Software Engineering Notes
Unit 3 Software Engineering Notes
5 MARKS
1. A design solution that is difficult to understand would lead to increased
development and maintenance cost. Give reasonings for your answer.
Unless a design solution is easily understandable, it would be difficult to
implement and maintain it.
A design solution is understandable, if it is modular and the modules are arranged
in distinct layers.
The better design solution should have the following characteristics to be easily
understandable:
It should assign consistent and meaningful names to various design
components.
It should make use of the principles of decomposition and abstraction in good
measures to simplify the design.
Layered design
A layered design is one in which when the call relations among different modules
are represented graphically, it would result in a tree-like diagram with clear
layering.
A layered design can make the design solution easily understandable, since to
understand the working of a module, one would at best have to understand how
the immediately lower layer modules work without having to worry about the
functioning of the upper layer modules.
In a layered design solution, the modules are arranged in a hierarchy of layers.
A module can only invoke functions of the modules in the layer immediately
below it.
The higher layer modules can be considered to be similar to managers that invoke
(order) the lower layer modules to get certain tasks done. A layered design can be
considered to be implementing control abstraction, since a module at a lower
layer is unaware of (about how to call) the higher layer modules.
When a failure is detected while executing a module, it is obvious that the
modules below it can possibly be the source of the error.
This greatly simplifies debugging since one would need to concentrate only on a
few modules to detect the error.
Preliminary (or high-level) design, - The outcome of high-level design is called the
program structure or the software architecture. When the high-level design is complete, the
problem should have been decomposed into many small functionally independent modules
that are cohesive, have low coupling among themselves, and are arranged in a hierarchy. The
control relationships and the interfaces among the modules are identified. Different types of
notations have been used to represent a high-level design are,
structure chart for procedural development,
UML that is being used to document object-oriented design,
Jackson diagram or Warnier-Orr diagram to document a software design,
Detailed design:- The outcome of the detailed design stage is called module specification
(MSPEC) document. During detailed design each module is examined carefully to design its
data structures and the algorithms are described using MSPEC and can be easily grasped by
programmers for initiating coding.
1.3. Classification of Design Methodologies
Design methodologies are classified into
procedural and
object-oriented approaches.
Coupling:
Two modules are said to be highly coupled, if either of the following two situations
arise:
If the function calls between two modules involve passing large chunks of shared
data, the modules are tightly coupled.
If the interactions occur through some shared data, then also we say that they are
highly coupled.
If two modules either do not interact with each other at all or at best interact by
passing no data or only a few primitive data items, they are said to have low coupling.
Cohesion:
When the functions of the module co-operate with each other for performing a single
objective, then the module has good cohesion.
If the functions of the module do very different things and do not co-operate with
each other to perform a single piece of work, then the module has very poor cohesion.
Functional independence
A module that is highly cohesive and also has low coupling with other modules is said to be
functionally independent of the other modules.
Advantages
Error isolation:
(An error existing in the module is very unlikely to affect the functioning of other
modules because interactions among the modules are very low in a functionally
independent module.
Once a failure is detected, error isolation makes it very easy to locate the error. )
Scope of reuse: (A functionally independent module performs some well-defined and precise
task and the interfaces of the module with other modules are very few and simple. A
functionally independent module can therefore be easily taken out and reused in a different
program.)
Understandability: (When modules are functionally independent, complexity of the design
is greatly reduced. This is because of the fact that different modules can be understood in
isolation, since the modules are independent of each other. )
5.3.1 Classification of Cohesiveness
Cohesiveness of a module is the degree to which the different functions of the module co-
operate to work towards a single objective. Classes of cohesiveness are:-
Classification of cohesion.
Classification of coupling.
Data coupling: Two modules are data coupled, if they communicate using an elementary
data item that is passed as a parameter between the two, e.g. an integer, a float, a character,
etc. This data item should be problem related and not used for control purposes.
Stamp coupling: Two modules are stamp coupled, if they communicate using a composite
data item such as a record in PASCAL or a structure in C.
Control coupling: Control coupling exists between two modules, if data from one module
is used to direct the order of instruction execution in another. An example of control
coupling is a flag set in one module and tested in another module.
Common coupling: Two modules are common coupled, if they share some global data
items.
Content coupling: Content coupling exists between two modules, if they share code. That
is, a jump from one module into the code of another module can occur. Modern high-level
programming languages such as C do not support such jumps across modules.
The following are the salient features of the function-oriented design approach:
Top-down decomposition:
In top-down decomposition, starting at a high-level view of the system, each high-
level function is successively refined into more detailed functions.
For example, consider a function create-new-library member which essentially
creates the record for a new member, assigns a unique membership number to
him, and prints a bill towards his membership charge. This high-level function
may be refined into the following subfunctions:
1. assign-membership-number
2. create-member-record
3. print-bill
Each of these subfunctions may be split into more detailed subfunctions and so on.
Centralised system state: The system state can be defined as the values of certain
data items that determine the response of the system to a user action or external
event. For example, the set of books (i.e. whether borrowed by different users or
available for issue) determines the state of a library automation system. Such data
in procedural programs usually have global scope and are shared by many
modules.
For example, in the library management system, several functions such as the
following share data such as member-records for reference and updation:
1. create-new-member
2. delete-member
3. update-member-record
2. Object-oriented Design
In the object-oriented design (OOD) approach, a system is viewed as being made up
of a collection of objects (i.e., entities).
Each object is associated with a set of functions that are called its methods. Each
object contains its own data.
The data internal to an object cannot be accessed directly by other objects and only
through invocation of the methods of the object.
For example, in a library automation software, each library member may be a separate
object with its own data and functions to operate on the stored data. The methods
defined for one object cannot directly refer to or change the data of other objects.
The object-oriented design paradigm makes extensive use of the principles of
abstraction and decomposition.
Three important concepts associated with an ADT are data abstraction, data
structure, data type.
Data abstraction:
The principle of data abstraction implies that how data is exactly stored is
abstracted away, that is any entity external to the object (that is, an instance of
an ADT) would have no knowledge about how data is exactly stored,
organised, and manipulated inside the object.
The entities external to the object can access the data internal to an object only
by calling certain well-defined methods supported by the object. (Consider an
ADT such as a stack. The data of a stack object may internally be stored in an
array, a linearly linked list, or a bidirectional linked list. The external entities
have no knowledge of this and can access data of a stack object only through
the supported operations such as push and pop.)
Data structure: A data structure is constructed from a collection of primitive data
items. (Just as a civil engineer builds a large civil engineering structure using
primitive building materials such as bricks, iron rods, and cement; a programmer can
construct a data structure as an organised collection of primitive data items such as
integer, floating point numbers, characters, etc.
Data type: A type is a programming language terminology that refers to anything that
can be instantiated. (For example, int, float, char, etc., are the basic data types
supported by C programming language. Thus, we can say that ADTs are user defined
data types.)
Advantages of using ADTs in programs:
The data of objects are encapsulated within the methods. This localises the errors.
That is, no program element is allowed to change a data, except through invocation
of one of the methods. So, any error can easily be traced to the code segment
changing the value.
An ADT-based design displays high cohesion and low coupling. Therefore, object-
oriented designs are highly modular.
Since the principle of abstraction is used, it makes the design solution easily
understandable and helps to manage complexity.
Object-oriented versus function-oriented design approaches
Unlike function-oriented design methods in OOD, the basic abstraction is not the
services available to the users of the system such as issue-book, display-bookdetails,
find-issued-books, etc., but real-world entities such as member, book, book-register,
etc. For example in OOD, an employee pay-roll software is not developed by
designing functions such as update-employee-record, get-employeeaddress, etc., but
by designing objects such as employees, departments, etc.
In OOD, state information exists in the form of data distributed among several objects
of the system. In contrast, in a procedural design, the state information is available in
a centralised shared data store. For example, while developing an employee pay-roll
system, the employee data such as the names of the employees, their code numbers,
basic salaries, etc., are usually implemented as global data in a traditional
programming system; whereas in an object-oriented design, these data are distributed
among different employee objects of the system. Objects communicate by message
passing. Therefore, one object may discover the state information of another object by
sending a message to it. Of course, somewhere or other the real-world functions must
be implemented.
Function-oriented techniques group functions together if, as a group, they constitute a
higher level function. On the other hand, object-oriented techniques group functions
together on the basis of the data they operate on.
Example: Automated fire-alarm system—customer requirements
The owner of a large multi-storied building wants to have a computerised fire alarm system
designed, developed, and installed in his building. Smoke detectors and fire alarms would
be placed in each room of the building. The fire alarm system would monitor the status of
these smoke detectors. Whenever a fire condition is reported by any of the smoke detectors,
the fire alarm system should determine the location at which the fire has been sensed and
then sound the alarms only in the neighbouring locations. The fire alarm system should
also flash an alarm message on the computer console. Fire fighting personnel would man
the console round the clock. After a fire condition has been successfully handled, the fire
alarm system should support resetting the alarms by the fire fighting personnel.
Function-oriented approach: In this approach, the different high-level functions are first
identified, and then the data structures are designed.
determine_neighbour_alarm();
determine_neighbour_sprinkler();
ring_alarm();
activate_sprinkler();
reset_alarm();
reset_sprinkler();
report_fire_location();
Object-oriented approach: In the object-oriented approach, the different classes of objects
are identified. Subsequently, the methods and data for each object are identified. Finally,
an appropriate number of instances of each class is created.
class detector
attributes: status, location, neighbours
operations: create, sense-status, get-location, find-neighbours
class alarm
attributes: location, status
operations: create, ring-alarm, get_location, reset-alarm
class sprinkler
attributes: location, status
operations: create, activate-sprinkler, get_location, reset-sprinkler
We can now compare the function-oriented and the object-oriented approaches based
on the two examples discussed above, and easily observe the following main differences:
In a function-oriented program, the system state (data) is centralised and several
functions access and modify this central data. In case of an object-oriented program,
the state information (data) is distributed among various objects.
In the object-oriented design, data is private in different objects and these are not
available to the other objects for direct access and modification.
The basic unit of designing an object-oriented program is objects, whereas it is
functions and modules in procedural designing. Objects appear as nouns in the
problem description; whereas functions appear as verbs.