Module 3
Software Design
Software design encompasses the set of principles, concepts, and practices that lead to
the development of a high-quality system or product. Software design sits at the
technical kernel of software engineering and is applied regardless of the software
process model that is used. Beginning once software requirements have been analyzed
and modeled, software design is the last software engineering action within the
modeling activity and sets the stage for construction (code generation and testing).
1. Goals of good software design:
The goals of good software design are as follows:-
i. Correctness: Software design should be correct as per requirement. A good
design should be correct i.e. it should correctly implement all the functionalities
of the system.
ii. Completeness: The design should have all components like data structures,
modules, and external interfaces, etc.
iii. Efficiency: Resources should be used efficiently by the program. A good software
design should address the resources, time, and cost optimization issues.
iv. Flexibility: The design should be able to modify on changing needs.
v. Consistency: There should not be any inconsistency in the design.
vi. Maintainability: The design should be so simple so that it can be easily
maintainable by other designers. A good software design should be easily
amenable to change whenever a change request is made from the customer
side.
vii. Understandability: A good design should be easily understandable, for which it
should be modular and all the modules are arranged in layers.
2. Design strategies and methodologies:
Design strategies: System Design Strategy refers to the approach that is taken to design
a software system. There are several strategies that can be used to design software
systems, including the following:
i. Top-Down Design: This strategy starts with a high-level view of the system and
gradually breaks it down into smaller, more manageable components.
ii. Bottom-Up Design: This strategy starts with individual components and builds
the system up, piece by piece.
iii. Iterative Design: This strategy involves designing and implementing the system
in stages, with each stage building on the results of the previous stage.
iv. Incremental Design: This strategy involves designing and implementing a small
part of the system at a time, adding more functionality with each iteration.
v. Agile Design: This strategy involves a flexible, iterative approach to design,
where requirements and design evolve through collaboration between self-
organizing and cross-functional teams.
Design methodologies: Software design is a process to conceptualize the software
requirements into software implementation. Software design takes the user
requirements as challenges and tries to find optimum solution. While the software is
being conceptualized, a plan is chalked out to find the best possible design for
implementing the intended solution.
The design activities vary considerably based on the specific methodology being used. A
large number of software design methodologies are available. We can roughly classify
these methodologies into two types
i. Procedural/ function-oriented approach
ii. Object-oriented approach
These two approaches are two fundamentally different design paradigms. There are
multiple variants of software design methodologies which we discuss below briefly.
3. Data oriented software design: Data oriented software design can be classified into two
types:
i. Data Flow-Oriented Design/ Structured Design: In the data flow-oriented design
approach, information flow characteristic is used to derive program structure. In
the data flow-oriented approach, emphasis is on the processing or operations
performed on the da ta. Design is information driven. Information may be
represented as a continuous flow that is transformed, as it is processed from node
to node in the input-output stream. As software can ideally be represented by a
data flow diagram (DFD), a design model that uses a DFD can theoretically be
applied in the software development project. The data flow-oriented approach is
especially applicable when information is processed without hierarchical structure.
A DFD can be mapped into the design structure by two means - transform analysis
or transaction analysis. Transform analysis is applied when the data flow in the
input-output stream has clear boundaries. The DFD is mapped into a structure that
allocates control to three basic modules - input, process and output. Transaction
analysis is applied when a single information item causes flow to branch along one
of many paths. The DFD is mapped to a substructure that acquires and evaluates a
transaction; another substructure controls all the data processing actions based on
a transaction. A few examples of structured design or data flow-oriented design
methodologies are Structured Analysis and Design Technique (SADT), Systematic
Activity Modeling Method (SAMM) and Structured Design (SD).
ii. Data Structure-Oriented Design: The data structure-oriented design approach
utilizes the data structures of the input data, internal data (for example databases)
and output data to develop software. In the data structure-oriented approach, the
emphasis is on the object, which is the data. The structure of information, called
data structure, has an important impact on the complexity and efficiency of
algorithms designed to process information.
Software design is closely related to the data structure of the system, for example,
alternative data will require a conditional processing element, repetitive data will
require a control feature for repetition and a hierarchical data structure will require
a hierarchical software structure. Data structure-oriented design is best utilized in
applications that are a well-defined, hierarchical structure of information.
As both data flow and data structure oriented design approaches are based on
considerations in the information domain, there are similarities between both
approaches. Both depend on the analysis step to build the foundation for later
steps. Both attempt to transform information into a software structure; both are
driven by information. In data structure-oriented design information structure are
represented using hierarchical diagrams; DFD has little relevance; transformation
and transaction flows are not considered. Data structure-oriented design have a
few tasks - evaluate the characteristics of the data structure, represent the data in
its lowest form such as repetition, sequence or selection, map the data
representation into a control hierarchy for software, refine the control hierarchy
and then develop a procedural description of the software. Some examples of the
data structure-oriented design approach are the Jackson System Development
(JSD) and the Data Structured Systems Development (DDSD) which is also called
the Warnier-Orr methodology.
4. Coupling: Coupling between two modules is a measure of the degree of interaction (or
interdependence) between the two modules. Two modules are said to be highly
coupled, if either of the following two situations arise:
i. If the function calls between two modules involve passing large chunks of shared
data, the modules are tightly coupled
ii. 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.
The degree of coupling between two modules depends on their interface complexity.
The interface complexity is determined based on the number of parameters and the
complexity of the parameters that are interchanged while one module invokes the
functions of the other module.
Classification of Coupling: Between any two interacting modules, any of the following
five different types of coupling can exist. These different types of coupling, in increasing
order of their severities is shown below.
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.
5. Cohesion: Cohesion is a measure of the functional strength of a module. 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.
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. The
different modules of a design can possess different degrees of freedom. The
cohesiveness increases from coincidental to functional cohesion. That is, coincidental is
the worst type of cohesion and functional is the best cohesion possible.
Classification of cohesion
Coincidental cohesion: A module is said to have coincidental cohesion, if it performs a
set of tasks that relate to each other very loosely, if at all. In this case, we can say that
the module contains a random collection of functions. It is likely that the functions have
been placed in the module out of pure coincidence rather than through some thought
or design. The designs made by novice programmers often possess this category of
cohesion, since they often bundle functions to modules rather arbitrarily.
Logical cohesion: A module is said to be logically cohesive, if all elements of the module
perform similar operations, such as error handling, data input, data output, etc.
Temporal cohesion: When a module contains functions that are related by the fact that
these functions are executed in the same time span, then the module is said to possess
temporal cohesion.
Procedural cohesion: A module is said to possess procedural cohesion, if the set of
functions of the module are executed one after the other, though these functions may
work towards entirely different purposes and operate on very different data.
Communicational cohesion: A module is said to have communicational cohesion, if all
functions of the module refer to or update the same data structure.
Sequential cohesion: A module is said to possess sequential cohesion, if the different
functions of the module execute in a sequence, and the output from one function is
input to the next in the sequence.
Functional cohesion: A module is said to possess functional cohesion, if different
functions of the module co-operate to complete a single task.
6. Modular structure: A modular design is an effective decomposition of a problem. It is a
basic characteristic of any good design solution. A modular design, in simple words,
implies that the problem has been decomposed into a set of modules that have only
limited interactions with each other. Decomposition of a problem into modules
facilitates taking advantage of the divide and conquer principle. If different modules
have either no interactions or little interactions with each other, then each module can
be understood separately. This reduces the perceived complexity of the design solution
greatly. To understand why this is so, remember that it may be very difficult to break a
bunch of sticks which have been tied together, but very easy to break the sticks
individually.
Two design solutions to the same problem
A design solution is said to be highly modular, if the different modules in the solution
have high cohesion and their inter-module couplings are low. A software design with
high cohesion and low coupling among modules is the effective problem decomposition.
Such a design would lead to increased productivity during program development by
bringing down the perceived problem complexity.
7. Packaging: Packaging is a process of collecting various component of a modular
structure. Components can be packages, classes, objects, procedures, functions,
methods, etc., all of which are vehicles for packaging functionality at various levels of
abstraction. Components represent function or processing entities. Connectors
represent interfaces that provide the ability to “use” or “pass data to” a component.
Properties describe the nature of the components and the organization of the
interfaces. Connectors include the ability to pass data and control, share data, “use”,
and “is-an-instance-of.” Properties focus on quality characteristics (e.g., maintainability,
reusability) that result when the structure is implemented.
8. Structured Analysis: the structured analysis activity transforms the SRS document into a
graphic model called the DFD model. During structured analysis, functional
decomposition of the system is achieved. That is, each function that the system needs to
perform is analyzed and hierarchically decomposed into more detailed functions.
It is important to understand that the purpose of structured analysis is to capture the
detailed structure of the system as perceived by the user. The results of structured
analysis can therefore, be easily understood by the user. In fact, the different functions
and data in structured analysis are named using the user’s terminology. The user can
therefore even review the results of the structured analysis to ensure that it captures all
his requirements.
The structured analysis technique is based on the following underlying principles:-
i. Top-down decomposition approach.
ii. Application of divide and conquer principle. Through this each high-level
function is independently decomposed into detailed functions.
iii. Graphical representation of the analysis results using data flow diagrams (DFDs).
DFD: A DFD is a hierarchical graphical model of a system that shows the different
processing activities or functions that the system performs and the data interchange
among those functions.
The DFD (also known as the bubble chart) is a simple graphical formalism that can be
used to represent a system in terms of the input data to the system, various processing
carried out on those data, and the output data generated by the system. The main
reason why the DFD technique is so popular is probably because of the fact that DFD is a
very simple formalism— it is simple to understand and use. A DFD model uses a very
limited number of primitive symbols to represent the functions performed by a system
and the data flow among these functions.
Starting with a set of high-level functions that a system performs, a DFD model
represents the sub-functions performed by the functions using a hierarchy of diagrams.
Primitive symbols used for constructing DFDs: There are essentially five different types
of symbols used for constructing DFDs.
Symbols used for designing DFDs.
i. Function symbol: A function is represented using a circle. This symbol is called a
process or a bubble. Bubbles are annotated with the names of the corresponding
functions.
ii. External entity symbol: An external entity is represented by a rectangle. The
external entities are essentially those physical entities external to the software
system which interact with the system by inputting data to the system or by
consuming the data produced by the system. In addition to the human users, the
external entity symbols can be used to represent external hardware and
software such as another application software that would interact with the
software being modelled.
iii. Data flow symbol: A directed arc (or an arrow) is used as a data flow symbol. A
data flow symbol represents the data flow occurring between two processes or
between an external entity and a process in the direction of the data flow arrow.
Data flow symbols are usually annotated with the corresponding data names.
iv. Data store symbol: A data store is represented using two parallel lines. It
represents a logical file. That is, a data store symbol can represent either a data
structure or a physical file on disk. Each data store is connected to a process by
means of a data flow symbol. The direction of the data flow arrow shows
whether data is being read from or written into a data store. An arrow flowing in
or out of a data store implicitly represents the entire data of the data store and
hence arrows connecting t o a data store need not be annotated with the name
of the corresponding data items.
v. Output symbol: The output symbol is represented by a postcard. The output
symbol is used when a hard copy is produced
Synchronous and asynchronous operations: If two bubbles are directly connected by a
data flow arrow, then they are synchronous. This means that they operate at t h e same
speed. However, if two bubbles are connected through a data store, then the speed of
operation of the bubbles are independent and they are known as asynchronous
operation.
Synchronous and asynchronous data flow
Data Dictionary: Every DFD model of a system must be accompanied by a data
dictionary. A data dictionary lists all data items that appear in a DFD model. The data
items listed include all data flows and the contents of all data stores appearing on all the
DFDs in a DFD model.
A data dictionary lists the purpose of all data items and the definition of all composite
data items in terms of their component data items.
For the smallest units of data items, the data dictionary simply lists their name and their
type. Composite data items are expressed in terms of the component data items using
certain operators.
The dictionary plays a very important role in any software development process,
especially for the following reasons:
i. A data dictionary provides a standard terminology for all relevant data for use by
the developers working in a project. A consistent vocabulary for data items is very
important, since in large projects different developers of the project have a
tendency to use different terms to refer to the same data, which unnecessarily
causes confusion.
ii. The data dictionary helps the developers to determine the definition of different
data structures in terms of their component elements while implementing the
design.
iii. The data dictionary helps to perform impact analysis. That is, it is possible to
determine the effect of some data on various processing activities and vice versa.
Such impact analysis is especially useful when one wants to check the impact of
changing an input value type, or a bug in some functionality, etc.
Data definition: Composite data items can be defined in terms of primitive data items
using the following data definition operators.
i. +: denotes composition of two data items, e.g. a+b represents data a and b.
ii. [,,]: represents selection, i.e. any one of the data items listed inside the square
bracket can occur For example, [a,b] represents either a occurs or b occurs.
iii. (): the contents inside the bracket represent optional data which may or may not
appear. a+(b) represents either a or a+b occurs.
iv. {}: represents iterative data definition, e.g. {name}5 represents five name data.
{name}* represents zero or more instances of name data.
v. =: represents equivalence, e.g. a=b+c means that a is a composite data item
Developing the DFD model of a system: A DFD model of a system graphically represents
how each input data is transformed to its corresponding output data through a
hierarchy of DFDs. The DFD model of a problem consists of many of DFDs and a single
data dictionary.
The DFD model of a system is constructed by using a hierarchy of DFDs. The top level
DFD is called the level 0 DFD or the context diagram. This is the most abstract (simplest)
representation of the system (highest level). It is the easiest to draw and understand. At
each successive lower level DFD s, more and more details are gradually introduced. To
develop a higher-level DFD model, processes are decomposed into their subprocesses
and the data flow among these sub-processes are identified.
To develop the data flow model of a system, first the most abstract representation
(highest level) of the problem is to be worked out. Subsequently, the lower level DFDs
are developed. Level 0 and Level 1 consist of only one DFD each. Level 2 may contain up
to 7 separate DFDs, and level 3 up to 49 DFDs, and so on. However, there is only a single
data dictionary for the entire DFD model. All the data names appearing in all DFDs are
populated in the data dictionary and the data dictionary contains the definitions of all
the data items.
DFD model of a system consists of a hierarchy of DFDs and a single data dictionary
Context Diagram: The context diagram is the most abstract (highest level) data flow
representation of a system. It represents the entire system as a single bubble. The
bubble in the context diagram is annotated with the name of the software system being
developed (usually a noun). This is the only bubble in a DFD model, where a noun is
used for naming the bubble. The bubbles at all other levels are annotated with verbs
according to the main function performed by the bubble. This is expected since the
purpose of the context diagram is to capture the context of the system rather than its
functionality.
The context diagram establishes the context in which the system operates; that is, who
are the users, what data do they input to the system, and what data they received by
the system.
Level 1 DFD: The level 1 DFD usually contains three to seven bubbles. That is, the system
is represented as performing three to seven important functions. To develop the level 1
DFD, examine the high-level functional requirements in the SRS document. If there are
three to seven high-level functional requirements, then each of these can be directly
represented as a bubble in the level 1 DFD. Next, examine the input data to these
functions and the data output by these functions as documented in the SRS document
and represent them appropriately in the diagram.
Example: A software system called RMS calculating software would read three integral
numbers from the user in the range of –1000 and +1000 and would determine the root
mean square (RMS) of the three input numbers and display it.
Data dictionary for the DFD model of RMS software
data-items: {integer}3
rms: float
valid-data: data-items
a: integer
b: integer
c: integer
asq: integer
bsq: integer
csq: integer
msq: integer
Context diagram, level 1, and level 2 DFDs for RMS software
9. Structured Design: The aim of structured design is to transform the results of the
structured analysis into a structure chart. The purpose of structured design is to define
the structure of the solution that is suitable for implementation in some programming
language. During structured design, all functions identified during structured analysis are
mapped to a module structure. This module structure is also called the high-level design
or the software architecture for the given problem.
Structure chart: A structure chart represents the software architecture. The various
modules making up the system, the module dependency (i.e. which module calls which
other modules), and the parameters that are passed among the different modules.
The basic building blocks using which structure charts are designed are as following:
i. Rectangular boxes: A rectangular box represents a module. Usually, every
rectangular box is annotated with the name of the module it represents.
ii. Module invocation arrows: An arrow connecting two modules implies that during
program execution control is passed from one module to the other in the direction
of the connecting arrow.
iii. Data flow arrows: These are small arrows appearing alongside the module
invocation arrows. The data flow arrows are annotated with the corresponding
data name.
iv. Library modules: A library module is usually represented by a rectangle with
double edges. Libraries comprise the frequently called modules. Usually, when a
module is invoked by many other modules, it is made into a library module.
v. Selection: The diamond symbol represents the fact that one module of several
modules connected with the diamond symbol is invoked depending on the
outcome of the condition attached with the diamond symbol.
vi. Repetition: A loop around the control flow arrows denotes that the respective
modules are invoked repeatedly.
In any structure chart, there should be one and only one module at the top, called the
root. There should be at most one control relationship between any two modules in the
structure chart. This means that if module A invokes module B, module B cannot invoke
module A. The main reason behind this restriction is that we can consider the different
modules of a structure chart to be arranged in layers or levels. The principle of
abstraction does not allow lower-level modules to be aware of the existence of the high-
level modules. However, it is possible for two higher-level modules to invoke the same
lower-level module.
Examples of properly and poorly layered designs
Transformation of a DFD Model into Structure Chart: Systematic techniques are
available to transform the DFD representation of a problem into a module structure
represented by as a structure chart. Structured design provides two strategies to guide
transformation of a DFD into a structure chart:
i. Transform analysis
ii. Transaction analysis
Normally, one would start with the level 1 DFD, transform it into module representation
using either the transform or transaction analysis and then proceed toward the lower
level DFDs. At each level of transformation, it is important to first determine whether
the transform or the transaction analysis is applicable to a particular DFD.
Whether to apply transform or transaction processing?
Given a specific DFD of a model, how does one decide whether to apply transform
analysis or transaction analysis? For this, one would have to examine the data input to
the diagram. The data input to the diagram can be easily spotted because they are
represented by dangling arrows.
If all the data flow into the diagram are processed in similar ways (i.e. if all the input
data flow arrows are incident on the same bubble in the DFD) then transform analysis is
applicable. Otherwise, transaction analysis is applicable. Normally, transform analysis is
applicable only to very simple processing.
It is to be noted that the bubbles are decomposed until it represents a very simple
processing that can be implemented using only a few lines of code. Therefore,
transform analysis is normally applicable at the lower levels of a DFD model. Each
different way in which data is processed corresponds to a separate transaction. Each
transaction corresponds to a functionality that lets a user perform a meaningful piece of
work using the software.
Example: Structure chart for the RMS software
Structure chart for the RMS software
10. Object oriented design:
Data flow-oriented techniques evolved into object-oriented design (OOD) techniques in
the late seventies. Object-oriented design technique is an intuitively appealing
approach, where the natural objects (such as employees, pay-roll-register, etc.) relevant
to a problem are first identified and then the relationships among the objects such as
composition, reference, and inheritance are determined. Each object essentially acts as
a data hiding (also known as data abstraction) entity. Object-oriented techniques have
gained wide spread acceptance because of their simplicity, the scope for code and
design reuse, promise of lower development time, lower development cost, more
robust code, and easier maintenance.
In this technique, various objects that occur in the problem domain and the solution
domain are first identified and the different relationships that exist among these objects
are identified. The object structure is further refined to obtain the detailed design. The
OOD approach is credited to have several benefits such as lower development time and
effort, and better maintainability of the software.
The object oriented design approach is unique in its usage of the three software design
concepts: abstraction, information hiding and modularity. Objects are basically a
producer or consumers of information or an information item. The object consists o f a
private data structure and related operations that may transform the data structure.
Operations contain procedural and control constructs that may be invoked by a
message, that is, a request to the object to perform one of its operations. The object
also has an interface where messages are passed to specify what operation on the
object is desired. The object that receives a message will then determine how the
requested operation is to be performed. By this means, information hiding (that is, the
details of implementation are hidden form all the elements outside the object) is
achieved. Also objects and their operations are inherently modular, that is, software
elements (data and process) are grouped together with a well-defined interface
mechanism (that is, messages).
Object oriented design is based on the concepts of: objects and attributes, classes and
members, wholes and parts. All objects encapsulate data (the attribute values that
define the data), other objects (composite objects can be defined), constants (set
values), and other related information. Encapsulation means that all of this information
is packaged into a single name and can be re-used. The object oriented design is rather
new and as such it is still evolving even at this present moment. Object oriented design
encompasses data design, architectural design and procedural design. By identifying
classes and objects, data abstractions are created; by coupling operations to data,
modules are specified and a structure for the software is established; by developing a
mechanism for using objects (for example, passing of messages) interfaces are
described.
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 and is responsible for
managing it. The data internal to an object cannot be accessed directly by other objects
and only through invocation of the methods of the object. The system state is
decentralized since there is no globally shared data in the system and data is stored in
each 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 as explained below. Objects decompose a system into
functionally independent modules. Objects can also be considered as instances of
abstract data types (ADTs). The ADT concept did not originate from the object-oriented
approach. In fact, ADT concept was extensively used in the ADA programming language
introduced in the 1970s.
ADT is an important concept that forms an important pillar of object orientation.
Let us now discuss the important concepts behind an ADT. There are, in fact, three
important concepts associated with an ADT—data abstraction, data structure, data
type. We discuss these in the following subsection:
Data abstraction: The principle of data abstraction implies that how data is
exactly stored is abstracted away. This means that any entity external to the
object (that is, an instance of an ADT) would have no knowledge about how data
is exactly stored, organized, 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 organized 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.
In object-orientation, classes are ADTs. But, what is the advantage of developing an
application using ADTs? Let us examine the three main advantages of using ADTs in
programs:
i. The data of objects are encapsulated within the methods. The encapsulation
principle is also known as data hiding. The encapsulation principle requires that
data can be accessed and manipulated only through the methods supported by
the object and not directly. This localizes the errors. The reason for this is as
follows. 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. That is, the method that changes a data item,
making it erroneous can be easily identified.
ii. An ADT-based design displays high cohesion and low coupling. Therefore, object-
oriented designs are highly modular.
iii. Since the principle of abstraction is used, it makes the design solution easily
understandable and helps to manage complexity.
Similar objects constitute a class. In other words, each object is a member of some class.
Classes may inherit features from a super class. Conceptually, objects communicate by
message passing. Objects have their own internal data. Thus an object may exist in
different states depending the values of the internal data. In different states, an object
may behave differently.
Object-oriented versus function-oriented design approaches: The following are some
of the important differences between the function-oriented and object-oriented design:
i. 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-book-
details, 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-
employee-address, etc., but by designing objects such as employees,
departments, etc.
ii. 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.
iii. 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.
iv. In a function-oriented program, the system state (data) is centralized 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.
v. 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.
vi. 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.
At this point, we must emphasize that it is not necessary that an object-oriented design
be implemented by using an object-oriented language only. However, an object-
oriented language such as C++ and Java support the definition of all the basic
mechanisms of class, inheritance, objects, methods, etc. and also support all key object-
oriented concepts that we have just discussed. Thus, an object-oriented language
facilitates the implementation of an OOD. However, an OOD can as well be
implemented using a conventional procedural languages—though it may require more
effort to implement an OOD using a procedural language as compared to the effort
required for implementing the same design using an object-oriented language. In fact,
the older C++ compilers were essentially pre-processors that translated C++ code into C
code.
Even though object-oriented and function-oriented techniques are remarkably different
approaches to software design, yet one does not replace the other; but they
complement each other in some sense. For example, usually one applies the top-down
function oriented techniques to design the internal methods of a class, once the classes
are identified. In this case, though outwardly the system appears to have been
developed in an object-oriented fashion, but inside each class there may be a small
hierarchy of functions designed in a top-down manner.
11. Top-down and bottom-up approach
Level-Oriented Design: In the level-oriented design approach, there are two general or
broad strategies that can be used. The first strategy starts with a general definition of a
solution to the problem then through a step-by-step process produce a detailed solution
(this is called Stepwise Refinement). This is basically dependent on the system
requirements and is a top-down process. The other strategy is to start with a basic
solution to the problem and through a process of modeling the problem, build up or
extend the solution by adding additional features (this is called design by composition).
a. Function Oriented Design/ Design by Functional decomposition /Design by
Stepwise Refinement/design by top-down process: The top-down process starts
at the top level and by functional decomposition, breaks down the system into
smaller functional modules. Smaller modules are more readily analyzed, easier to
design and code. But, inherent in the top-down process is the requirement that
there must be a complete understanding of the problem or system at hand.
Otherwise, it could lead to extensive redesign later on. The top-down process also
is dependent on decisions made at the early stages to determine the design
structure. Different decisions made at the early stage will result in different design
structures. Functional decomposition is an iterative "break down" process called
stepwise refinement, where each level is decomposed to a more detailed lower
level. Thus, at each decomposition, there have to be a way to determine if further
decomposition is needed or necessary, that is, if the atomic level has been
achieved. There are no inherent procedure or guidelines for this. There is also a
possibility of duplication if stepwise refinement is not done carefully or "correctly";
this will occur toward the end of the process, that is, at the lower levels. This can
be costly, especially if there are many different designers or programming teams
working on a single system. As a result, the top-down process is often used in the
initial phase of the design process to break down the different components or
modules of a system. The top-down process has also been used as a preliminary
step in the other design methodologies. Once the modules of the system have
been determined, they can be divided amongst the different designers or design
teams.
b. Design by composition/Design by bottom-up process: The design by composition
strategy involves the evolution of a solution by building upon the solution from the
previous stage. Using this technique, additional features are added as the solution
evolves. This strategy uses as its origin, the basic or simple initial solution and
through an iterative composition process add or expand the solution to include
additional modules. This approach will also encompass the bottom-up design,
where the lowest level solution is developed first and gradually builds up to the
highest level.
12. UML
A model is constructed by focusing only on a few aspects of the problem and ignoring
the rest. The model of a problem is called an analysis model. On the other hand, the
model of the solution (code) is called the design model. The design model is usually
obtained by carrying out iterative refinements to the analysis model using a design
methodology. Note that any design is a model of the solution, whereas any model of the
problem is an analysis model.
In the context of model construction, we need to carefully understand the distinction
between a modelling language and a design process, since we shall use these two terms
frequently in our discussions.
Modelling language: A modelling language consists of a set of notations using
which design and analysis models are documented.
Design process: A design process addresses the following issue: “Given a
problem description, how to systematically work out the design solution to the
problem?” In other words, a design process consists of a step by step procedure
(or recipe) using which a problem description can be converted into a design
solution. A design process is, at times, also referred to as a design methodology.
In this text, we shall use the terms design process and design methodology
interchangeably.
A model can be documented using a modelling language such as unified modelling
language (UML). Over the last decade, UML has become immensely popular. UML has
also been accepted by ISO as a standard for modelling object-oriented systems. In this
Chapter, we primarily discuss the syntax and semantics of UML.
As the name itself implies, UML is a language for documenting models. As is the case
with any other language, UML has its syntax (a set of basic symbols and sentence
formation rules) and semantics (meanings of basic symbols and sentences). It provides a
set of basic graphical notations (e.g. rectangles, lines, ellipses, etc.) that can be
combined in certain ways to document the design and analysis results.
It is important to remember that UML is neither a system design or development
methodology by itself, nor is tied to any specific methodology. UML is merely a language
for documenting models. Before the advent of UML, every design methodology not only
prescribed entirely different design steps, but each was tied to some specific design
modelling language.
UML can be used to document object-oriented analysis and design results that have
been obtained using any methodology. One of the objectives of the developers of UML
was to keep the notations of UML independent of any specific design methodology, so
that it can be used along with any specific design methodology.
Model: A model is an abstraction of a real problem (or situation), and is constructed by
leaving out unnecessary details. This reduces the problem complexity and makes it easy
to understand the problem (or situation).
UML Diagrams: UML can be used to construct nine different types of diagrams to
capture different views of a system. Just as a building can be modelled from several
views (or perspectives) such as ventilation perspective, electrical perspective, lighting
perspective, heating perspective, etc.; the different UML diagrams provide different
perspectives of a software system to be developed and facilitate a comprehensive
understanding of the system. Each perspective focuses on some specific aspect and
ignores the rest. Some may ask, why construct several models from different
perspectives—why not just construct one model that captures all perspectives? The
answer to this is the following:
If a single model is made to capture all the required perspectives, then it would be as
complex as the original problem, and would be of little use.
Once a system has been modelled from all the required perspectives, the constructed
models can be refined to get the actual implementation of the system.
UML diagrams can capture the following views (models) of a system:
i. User’s view
ii. Structural view
iii. Behavioral view
iv. Implementation view
v. Environmental view
Different types of diagrams and views supported in UML
Figure above shows the different views that the UML diagrams can document. Observe
that the users’ view is shown as the central view. This is because based on the users’
view, all other views are developed and all views need to conform to the user’s view.
Most of the object oriented analysis and design methodologies, require us to iterate
among the different views several times to arrive at the final design. We first provide a
brief overview of the different views of a system which can be documented using UML.
Users’ view: This view defines the functionalities made available by the system
to its users. The users’ view captures the view of the system in terms of the
functionalities offered by the system to its users. The users’ view is a black-box
view of the system where the internal structure, the dynamic behavior of
different system components, the implementation etc. are not captured. The
users’ view is very different from all other views in the sense that it is a
functional model1 compared to all other views that are essentially object
models. The users’ view can be considered as the central view and all other
views are required to conform to this view. This thinking is in fact the crux of any
user centric development style. It is indeed remarkable that even for object-
oriented development, we need a functional view. That is because, after all, a
user considers a system as providing a set of functionalities.
Structural view: The structural view defines the structure of the problem (or the
solution) in terms of the kinds of objects (classes) important to the
understanding of the working of a system and to its implementation. It also
captures the relationships among the classes (objects). The structural model is
also called the static model, since the structure of a system does not change with
time.
Behavioral view: The behavioral view captures how objects interact with each
other in time to realize the system behavior. The system behavior captures the
time-dependent (dynamic) behavior of the system. It therefore constitutes the
dynamic model of the system.
Implementation view: This view captures the important components of the
system and their interdependencies. For example, the implementation view
might show the GUI part, the middleware, and the database part as the different
parts and also would capture their interdependencies.
Environmental view: This view models how the different components are
implemented on different pieces of hardware.
For any given problem, should one construct all the views using all the diagrams
provided by UML? The answer is No. For a simple system, the use case model, class
diagram, and one of the interaction diagrams may be sufficient. For a system in which
the objects undergo many state changes, a state chart diagram may be necessary. For a
system, which is implemented on a large number of hardware components, a
deployment diagram may be necessary. So, the type of models to be constructed
depends on the problem at hand.
USE CASE MODEL: The use case model for any system consists of a set of use cases.
Intuitively, the use cases represent the different ways in which a system can be used by
the users. A simple way to find all the use cases of a system is to ask the question,
“What all can the different categories of users do by using the system?”
A use case can be viewed as a set of related scenarios tied together by a common goal.
The main line sequence and each of the variations are called scenarios or instances of
the use case. Each scenario is a single path of user events and system activity.
In contrast to all other types of UML diagrams, the use case model represents a
functional or process model of a system.
Representation of Use Cases: A use case model can be documented by drawing a use
case diagram and writing an accompanying text elaborating the drawing. In the use case
diagram, each use case is represented by an ellipse with the name of the use case
written inside the ellipse. All the ellipses (i.e. use cases) of a system are enclosed within
a rectangle which represents the system boundary. The name of the system being
modeled (e.g., library information system) appears inside the rectangle.
The different users of the system are represented by using stick person icons. Each stick
person icon is referred to as an actor. An actor is a role played by a user with respect to
the system use. It is possible that the same user may play the role of multiple actors. An
actor can participate in one or more use cases. The line connecting an actor and the use
case is called the communication relationship. It indicates that an actor makes use of the
functionality provided by the use case.
Both human users and external systems can be represented by stick person icons. When
a stick person icon represents an external system, it is annotated by the stereotype
<<external system>>.
At this point, it is necessary to explain the concept of a stereotype in UML. One of the
main objectives of the creators of the UML was to restrict the number of primitive
symbols in the language. It was clear to them that when a language has a large number
of primitive symbols, it becomes very difficult to learn use. To convince yourself,
consider that English with 26 alphabets is much easier to learn and use compared to the
Chinese language that has thousands of symbols. In this context, the primary objective
of stereotype is to reduce the number of different types of symbols that one needs to
learn.
The stereotype construct when used to annotate a basic symbol, can give slightly
different meaning to the basic symbol— thereby eliminating the need to have several
symbols whose meanings differ slightly from each other. We can stereotype the stick
person icon symbol to denote an external system. If the developers of UML had
assigned a separate symbol to denote things such as an external system, then the
number of basic symbols one would have to learn and remember while using UML
would have increased significantly. This would have certainly made learning and using
UML much more difficult.
You can draw a rectangle around the use cases, called the system boundary box, to
indicate the scope of your system. Anything within the box represents functionality that
is in scope and anything outside the box is not. However, drawing the system boundary
is optional.
Text description: Each ellipse in a use case diagram, by itself conveys very little
information, other than giving a hazy idea about the use case. Therefore, every
use case diagram should be accompanied by a text description. The text
description should define the details of the interaction between the user and the
computer as well as other relevant aspects of the use case. It should include all
the behavior associated with the use case in terms of the mainline sequence,
various alternate sequences, and the system responses associated with the use
case, the exceptional conditions that may occur in the behavior, etc. The
behavior description is often written in a conversational style describing the
interactions between the actor and the system. The text description may be
informal, but some structuring is helpful. The following are some of the
information which may be included in a use case text description in addition to
the mainline sequence, and the alternate scenarios.
Contact persons: This section lists of personnel of the client organization with
whom the use case was discussed, date and time of the meeting, etc.
Actors: In addition to identifying the actors, some information about actors using
a use case which may help the implementation of the use case may be recorded.
Pre-condition: The preconditions would describe the state of the system before
the use case execution starts.
Post-condition: This captures the state of the system after the use case has
successfully completed.
Non-functional requirements: This could contain the important constraints for
the design and implementation, such as platform and environment conditions,
qualitative statements, response time requirements, etc.
Exceptions, error situations: This contains only the domain-related errors such
as lack of user’s access rights, invalid entry in the input fields, etc. Obviously,
errors that are not domain related, such as software errors, need not be
discussed here.
Sample dialogs: These serve as examples illustrating the use case.
Specific user interface requirement: These contain specific requirements for the
user interface of the use case. For example, it may contain forms to be used,
screen shots, interaction style, etc.
Document references: This part contains references to specific domain related
documents which may be useful to understand the system operation.
13. Design patterns:
While working out the design solution to a problem, experienced designers consciously
or unconsciously reuse solutions that they might have worked out in the past. Such
reuse of the design solutions is systematized by the concept of patterns. In fact, patterns
allow commonly accepted solutions to be reused by everybody familiar with the
patterns. We shall soon see that while working out the design solution to a problem, a
knowledge of some important design patterns can go a long way to improve the design
quality and at the same time reduce the total effort.
Design patterns are commonly accepted solutions to some problems that recur during
designing different applications. Design patterns are nowadays being used extensively
and have been found to make the design process efficient. Use of patterns reduces the
number of design iterations, and at the same time improves the quality of the final
design solution. This makes a thorough study of the patterns worthwhile. Once we
become familiar with a few important patterns, we can spot them in the designs we try
to work out and shall be able to reuse the pattern solutions.
The basic idea behind patterns is that if you can master a few important patterns, you
can easily spot them in application development problems and effortlessly use the
pattern solutions.
Patterns can be viewed as helping designers to make certain important design decisions.
At a basic level, patterns can also be viewed as well-documented and well thought-out
building blocks for software design.
In addition to providing model solutions, patterns document clear specifications of the
problems, and also explain the circumstances in which a solution would work and would
not work. A pattern documentation usually consists of four important parts:
i. The problem.
ii. The context in which the problem occurs.
iii. The solution.
iv. The context within which the solution would work and would not work.
Types of Patterns: Different types of patterns have been identified for use in different
stages of design. Starting from use in very high-level designs termed as architectural
designs, pattern solutions have been defined for use in concrete designs and even in
code. We discuss some basic concepts about these three types of patterns as follows.
i. Architectural patterns: The architectural patterns identify and provide solutions
to problems that are identifiable while carrying out architectural (or very high-
level) designs. Architectural designs concern the overall structure of software
systems. Architectural designs cannot directly be translated to code, but form
the basis for more detailed design. Each architectural pattern suggests a set of
predefined subsystems, specifies their responsibilities, and includes rules and
guidelines for organizing the relationships among them. Architectural designs
are usually constructed for very large problems. Naturally therefore,
architectural patterns are relevant while working out the high-level solutions to
very large problems.
ii. Design patterns: A design pattern usually suggests a scheme for structuring the
classes in a design solution and defines the required interactions among those
classes. In other words, a design pattern describes some commonly recurring
structure of communicating classes that can be used to solve some general
design problems. Design pattern solutions are typically described in terms of
classes, their instances, their roles and collaborations.
iii. Idioms: Idioms are a set of low-level patterns that are programming language-
specific. An idiom describes how to implement a solution to a particular problem
using the features of a given programming language. In any natural language
such as English, an idiom means a group of words that together have a meaning
that is different from the one obtained by a simple juxtaposition of the
dictionary definitions of the individual words.
Comparison of different types of patterns: The main differences among the three kinds
of patterns discussed above lie in the levels of abstraction and details they deal with.
Architectural patterns are high-level strategies that concern the overall solutions to
large-scale problems. Design patterns are solutions for specific parts of medium-scale
problems and recommend certain structures and behavior of the participating entities.
Idioms are paradigm-specific and language-specific programming solutions that
recommend using appropriate code segments for solving low-level programming
problems.
Patterns versus algorithms: Beginners often confuse between patterns and algorithms
and ask questions such as—“Are patterns and algorithms identical concepts? After all,
both target to provide reusable solutions to problems!” In fact, patterns and algorithms
are in some respects similar since both attempt to provide reusable solutions. However,
algorithms primarily focus on solving problems with reduced space and/or time
requirements, whereas patterns focus on understandability and maintainability of
design and easier development. In contrast to algorithms, patterns are more concerned
with aspects such as maintainability and ease of development rather than space and
time efficiency.
Pros and cons of design patterns: Before using design patterns, it is desirable to be
familiar with the pros (advantages) and cons (disadvantages) of design patterns.
The following are the main pros (strengths) of design patterns:
i. Design patterns provide a common vocabulary that helps to improve
communication among the developers.
ii. Design patterns help to capture and disseminate expert knowledge.
iii. Use of design patterns help designers to produce designs that are flexible,
efficient, and easily maintainable.
iv. Design patterns guide developers to arrive at correct design decisions and help
them to improve the quality of their designs.
v. Design patterns reduce the number of design iterations, and help improve the
designer productivity.
Important cons (shortcomings) of design patterns are the following:
i. Design patterns do not directly lead to code reuse. Since a design pattern is
tailored for a specific circumstance of reuse, and therefore it is difficult to
associate a fixed code segment with a pattern.
ii. At present no methodology is available that can be used to select the right
design pattern at the right point during a design exercise.