Software Design Principles and Models
Software Design Principles and Models
It's like creating a blueprint for building software — just like an architect designs a building
before it's constructed.
1. Architecture Design
2. Component Design
3. Interface Design
4. Data Design
Level Description
Low-Level Design Describes internal logic of each module, functions, and class
(LLD) details.
Principle Meaning
Encapsulation Keep data and behavior bundled together in one unit (class/object).
1. Structured Design
● UML (Unified Modeling Language): Common language for design using diagrams like:
○ Class Diagram
○ Sequence Diagram
○ Use Case Diagram
○ Activity Diagram
● ER Diagram: For designing databases.
● Flowcharts: For visualizing logic.
● Complicated code.
● High development and maintenance costs.
● Hard-to-find bugs.
● Poor performance and scalability issues.
Architectural Design
The software needs an architectural design to represent the design of the software. IEEE defines
architectural design as “the process of defining a collection of hardware and software
components and their interfaces to establish the framework for the development of a computer
system.” The software that is built for computer-based systems can exhibit one of these many
architectural styles.
System Category Consists of
● A set of components(eg: a database, computational modules) that will perform a
function required by the system.
● The set of connectors will help in coordination, communication, and cooperation
between the components.
● Conditions that defines how components can be integrated to form the system.
● Semantic models that help the designer to understand the overall properties of the
system.
The use of architectural styles is to establish a structure for all the components of the system.
Taxonomy of Architectural Styles
● A data store will reside at the center of this architecture and is accessed frequently by
the other components that update, add, delete, or modify the data present within the
store.
● The figure illustrates a typical data-centered style. The client software accesses a
central repository. Variations of this approach are used to transform the repository
into a blackboard when data related to the client or data of interest for the client
change the notifications to client software.
● This data-centered architecture will promote integrability. This means that the
existing components can be changed and new client components can be added to the
architecture without the permission or concern of other clients.
● This kind of architecture is used when input data is transformed into output data
through a series of computational manipulative components.
● The figure represents pipe-and-filter architecture since it uses both pipe and filter and
it has a set of components called filters connected by lines.
● Pipes are used to transmitting data from one component to the next.
● Each filter will work independently and is designed to take data input of a certain
form and produces data output to the next filter of a specified form. The filters don’t
require any knowledge of the working of neighboring filters.
● If the data flow degenerates into a single line of transforms, then it is termed as batch
sequential.
It is used to create a program that is easy to scale and modify. Many sub-styles exist within this
category. Two of them are explained below.
● Remote procedure call architecture: This components is used to present in a main
program or sub program architecture distributed among multiple computers on a
network.
● Main program or Subprogram architectures: The main program structure
decomposes into number of subprograms or function into a control hierarchy. Main
program contains number of subprograms that can invoke other components.
4] Object Oriented architecture
The components of a system encapsulate data and the operations that must be applied to
manipulate the data. The coordination and communication between the components are
established via the message passing.
Characteristics of Object Oriented architecture:
● Object protect the system’s integrity.
● An object is unaware of the depiction of other items.
5] Layered architecture
● A number of different layers are defined with each layer performing a well-defined
set of operations. Each layer will do some operations that becomes closer to machine
instruction set progressively.
● At the outer layer, components will receive the user interface operations and at the
inner layers, components will perform the operating system
interfacing(communication and coordination with OS)
Modularization
Modularization diagram
In this current age of software, you would be hard-pressed to find a program that isn't
continuously growing and evolving. Designing a program all at once, with all required functions,
would be difficult due to its size, complexity and constant changes. This is where modularization
comes in.
With modularization, we can easily work on adding separate and smaller modules to a program
without being hindered by the complexity of its other functions. In short, it’s about being flexible
and fast in adding more software functions to a program. In a software engineering team, we
could easily work independently on each module without affecting others’ work.
It is the backbone of the microservice architecture, whose basic idea is also the simplicity of
developing applications that are easier to extend and maintain when disassembled into small and
independent parts. On the other hand, in monolithic architecture, there’s always the risk of
bringing down the whole program with a simple update.
Without modularization, this will lead to an increase in development time, the number of bugs
and the duration it takes to test and release a program.
Benefits of modularization
Why should we be decomposing our projects into modules? As shown in my experience with a
single-file program, programs without proper modularization would be a nightmare to maintain
and extend.
In modularization, the modules have minimal dependency on other modules. So, we can easily
make changes in a module without affecting other parts of the program.
The following are just the gist of how modularization would improve the development process
for a program.
A module should have only a single responsibility, that is the Single Responsibility Principle.
Thus, it should depend minimally on other modules. The independence of a module can be
measured using coupling and cohesion.
Coupling: Coupling is the measure of the degree of interdependence between the modules. A good
software will have low coupling.
Cohesion: Cohesion is a measure of the degree to which the elements of the module are functionally
related. It is the degree to which all elements directed towards performing a single task are
contained in the component. Basically, cohesion is the internal glue that keeps the module together.
A good software design will have high cohesion.
Cohesion and coupling
Each module should have a clear and focused purpose, such that its developers have a clear idea
of the requirement for each function. Its interface should be easy to understand and use, even
without understanding its implementation details. Thus, leading into our next point, is that its
implementation details, while not only correct, should be encapsulated and private, and that it
should be changeable without affecting another module. Furthermore, the dependency between
modules should be minimised.
Structure Chart
Structure Chart represents the hierarchical structure of modules. It breaks down the
entire system into the lowest functional modules and describes the functions and
sub-functions of each module of a system in greater detail. This article focuses on
discussing Structure Charts in detail.
1. Inputs are given to the black boxes and appropriate outputs are generated.
2. Modules at the top level are called modules at low level.
3. Components are read from top to bottom and left to right.
4. When a module calls another, it views the called module as a black box,
1. Module
It represents the process or task of the system. It is of three types:
● Sub Module: Sub Module is a module which is the part (Child) of another
module.
● Library Module: Library Module are reusable and invokable from any
module.
2. Conditional Call
It represents that control module can select any of the sub module on the basis of
some condition.
It represents the repetitive execution of module by the sub module. A curved arrow
represents a loop in the [Link] the submodules cover by the loop repeat execution
of module.
4. Data Flow
5. Control Flow
Example
Structure chart for an Email server
PSEUDOCODE
A Pseudocode is defined as a step-by-step description of an algorithm. Pseudocode does not use
any programming language in its representation, instead it uses the simple English language text
as it is intended for human understanding rather than machine reading.
Pseudocode is the intermediate state between an idea and its implementation(code) in a
high-level language.
● Use standard programming structures such as if-else, for, while, and cases the way
we use them in programming. Indent the statements if-else, for, while loops as they
are indented in a program, it helps to comprehend the decision control and execution
mechanism. It also improves readability to a great extent. Example:
IF “1”
print response
“I AM CASE 1”
IF “2”
print response
“I AM CASE 2”
● Use appropriate naming conventions. The human tendency follows the approach of
following what we see. If a programmer goes through a pseudo code, his approach
will be the same as per that, so the naming must be simple and distinct.
● Reserved commands or keywords must be represented in capital letters. Example: if
you are writing IF…ELSE statements then make sure IF and ELSE be in capital
letters.
● Check whether all the sections of a pseudo code are complete, finite, and clear to
understand and comprehend. Also, explain everything that is going to happen in the
actual code.
● Don’t write the pseudocode in a programming language. It is necessary that the
pseudocode is simple and easy to understand even for a layman or client, minimizing
the use of technical terms.
Pseudocode Examples:
Example: Given a sorted array Arr[] and a value X, The task is to find the index at which X is
present in Arr[].
Below is the pseudocode for Binary search.
BinarySearch(ARR, X, LOW, HIGH)
repeat till LOW = HIGH
MID = (LOW + HIGH)/2
if (X == ARR[mid])
return MID
else if (x > ARR[MID])
LOW = MID + 1
else
HIGH = MID – 1
QuickSort is a Divide and Conquer algorithm. It picks an element as a pivot and partitions the
given array around the picked pivot.
Say last element of array is picked as pivot then all elements smaller than pivot element are
shifted on the left side of pivot and elements greater than pivot are shifted towards the right of
pivot by swapping, the same algorithm is repeatedly followed for the left and right side of pivot
until the whole array is sorted.
Here, LOW is the starting index and HIGH is the ending index.
Difference between Algorithm and Pseudocode
Algorithm Pseudocode
An algorithm only uses simple English Pseudocode also uses reserved keywords
words like if-else, for, while, etc.
Flowchart Pseudocode
A Pseudocode is a step-by-step
A Flowchart is a pictorial representation
description of an algorithm in code like
of flow of an algorithm.
structure using plain English text.
This is a way of visually representing These are fake codes as the word
data, these are nothing but the graphical pseudo means fake, using code like
representation of the algorithm for a structure but plain English text instead
better understanding of the code of programming language
A good design is the one that has low coupling. Coupling is measured by the number of relations
between the modules. That is, the coupling increases as the number of calls between modules
increase or the amount of shared data is large. Thus, it can be said that a design with high
coupling will have more errors.
In this case, modules are subordinates to different modules. Therefore, no direct coupling.
2. Data Coupling: When data of one module is passed to another module, this is called data
coupling.
3. Stamp Coupling: Two modules are stamp coupled if they communicate using composite data
items such as structure, objects, etc. When the module passes non-global data structure or entire
structure to another module, they are said to be stamp coupled. For example, passing structure
variable in C or object in C++ language to a module.
4. Control Coupling: Control Coupling exists among two modules if data from one module is
used to direct the structure of instruction execution in another.
5. External Coupling: External Coupling arises when two modules share an externally imposed
data format, communication protocols, or device interface. This is related to communication to
external tools and devices.
6. Common Coupling: Two modules are common coupled if they share information through
some global data items.
7. Content Coupling: Content Coupling exists among two modules if they share code, e.g., a
branch from one module into another module.
Module Cohesion
In computer programming, cohesion defines the degree to which the elements of a module
belong together. Thus, cohesion measures the strength of relationships between pieces of
functionality within a given module. For example, in highly cohesive systems, functionality is
strongly related.
Coupling Cohesion
Coupling is also called Inter-Module Cohesion is also called Intra-Module
Binding. Binding.
Coupling shows the relationships between Cohesion shows the relationship within the
modules. module.
Coupling shows the relative independence Cohesion shows the module's relative
between the modules. functional strength.
While creating, you should aim for low While creating you should aim for high
coupling, i.e., dependency among modules cohesion, i.e., a cohesive component/
should be less. module focuses on a single function (i.e.,
single-mindedness) with little interaction
with other modules of the system.
In coupling, modules are linked to the other In cohesion, the module focuses on a single
modules. thing.
Design Notations
Design Notations are primarily meant to be used during the process of design and are used to
represent design or design decisions. For a function-oriented design, the design can be
represented graphically or mathematically by the following:
Data Flow Diagram
Data-flow design is concerned with designing a series of functional transformations that convert
system inputs into the required outputs. The design is described as data-flow diagrams. These
diagrams show how data flows through a system and how the output is derived from the input
through a series of functional transformations.
Data-flow diagrams are a useful and intuitive way of describing a system. They are generally
understandable without specialized training, notably if control information is excluded. They
show end-to-end processing. That is the flow of processing from when data enters the system to
where it leaves the system can be traced.
Data-flow design is an integral part of several design methods, and most CASE tools support
data-flow diagram creation. Different ways may use different icons to represent data-flow
diagram entities, but their meanings are similar.
Data Dictionaries
A data dictionary lists all data elements appearing in the DFD model of a system. The data items
listed contain all data flows and the contents of all data stores looking on the DFDs in the DFD
model of a system.
A data dictionary lists the objective of all data items and the definition of all composite data
elements in terms of their component data items. For example, a data dictionary entry may
contain that the data grossPay consists of the parts regularPay and overtimePay.
For the smallest units of data elements, the data dictionary lists their name and their type.
A data dictionary plays a significant role in any software development process because of the
following reasons:
○ A Data dictionary provides a standard language for all relevant information for use by
engineers working in a project. A consistent vocabulary for data items is essential since,
in large projects, different engineers of the project tend to use different terms to refer to
the same data, which unnecessarily causes confusion.
○ The data dictionary provides the analyst with a means to determine the definition of
various data structures in terms of their component elements.
Structured Charts
It partitions a system into block boxes. A Black box system that functionality is known to the
user without the knowledge of internal design.
Pseudo-code
Pseudo-code notations can be used in both the preliminary and detailed design phases. Using
pseudo-code, the designer describes system characteristics using short, concise, English
Language phases that are structured by keywords such as If-Then-Else, While-Do, and End.
1. Objects: All entities involved in the solution design are known as objects. For example,
people, banks, companies, and users are considered as objects. Every entity has some
attributes associated with it and has some methods to perform on the attributes.
2. Classes: A class is a generalized description of an object. An object is an instance of a
class. A class defines all the attributes, which an object can have and methods, which
represents the functionality of the object.
3. Messages: Objects communicate by message passing. Messages consist of the integrity of
the target object, the name of the requested operation, and any other action needed to
perform the function. Messages are often implemented as procedure or function calls.
4. Abstraction In object-oriented design, complexity is handled using abstraction.
Abstraction is the removal of the irrelevant and the amplification of the essentials.
5. Encapsulation: Encapsulation is also called an information hiding concept. The data and
operations are linked to a single unit. Encapsulation not only bundles essential
information of an object together but also restricts access to the data and methods from
the outside world.
6. Inheritance: OOD allows similar classes to stack up in a hierarchical manner where the
lower or sub-classes can import, implement, and re-use allowed variables and functions
from their immediate [Link] property of OOD is called an inheritance. This
makes it easier to define a specific class and to create generalized classes from specific
ones.
7. Polymorphism: OOD languages provide a mechanism where methods performing similar
tasks but vary in arguments, can be assigned the same name. This is known as
polymorphism, which allows a single interface is performing functions for different
types. Depending upon how the service is invoked, the respective portion of the code gets
executed.
In the top-down model, an overview of the system is formulated without going into detail for any
part of it. Each part of it then refined into more details, defining it in yet more details until the
entire specification is detailed enough to validate the model. if we glance at a haul as a full, it’s
going to appear not possible as a result of it’s so complicated For example: Writing a University
system program, writing a word processor.
3. We Continue this process until every part is simple enough to implement.
This approach is particularly useful for solving complex problems, like developing a University
System Program or a Word Processor. By starting with a high-level design and gradually
focusing on smaller details, the complexity of the system becomes more manageable.
In contrast, the Bottom-Up Design Model is started by defining the system’s individual parts
first. Once the individual components are detailed, they are integrated into larger modules. This
process is continued till the system is fully integrated. The Bottom-Up approach is often used in
Object-Oriented Programming (OOP) languages like C++, Java, and Python, where individual
objects are identified and developed first.
This method focuses on creating well-defined and reusable low-level components before
deciding how to integrate them into higher-level systems.
1. focus on breaking the problem Solves smaller problems and integrates them
into smaller, more manageable into a complete system.
parts.
9. Pros Pros
● We need to develop large and complex systems where high-level architecture is defined
early.
● The overall system’s structure is crucial before dealing with individual components.
● You are working in a more procedural or structured programming environment.
● You want to focus on individual components and gradually build them into a complete
system.
● You are working with Object-Oriented Programming (OOP) languages and want to take
advantage of modularity and object reusability.
Software measurement is the process of collecting, analyzing, and interpreting data related to
software development. It helps in evaluating software quality, performance, and progress.
Think of it like measuring speed, fuel efficiency, and mileage in a car. These numbers help us
understand how well the car is performing. Similarly, in software engineering, software
measurement helps in improving software development and maintenance.
For example, if you are developing software, you may want to measure:
✔ How many lines of code (LOC) are written?
✔ How many defects (bugs) were found?
✔ How much time was spent on coding and testing?
Software metrics are classified into different categories based on what they measure:
These metrics help measure how efficiently the software development process is running.
🔹 Example Metrics:
✔ Defect Rate: Number of bugs found per 1000 lines of code.
✔ Development Time: How long it takes to develop a software module.
✔ Team Productivity: Number of tasks completed per developer in a sprint.
Example: If a team completes a project in 6 months but has 200 defects, the process might need
improvement.
These metrics measure the quality and complexity of the software itself.
🔹 Example Metrics:
✔ Lines of Code (LOC): Total number of lines in the program.
✔ Cyclomatic Complexity: Measures how complex the software code is.
✔ Code Maintainability Index: How easy it is to modify and maintain the software.
These metrics help in managing time, cost, and resources in a software project.
🔹 Example Metrics:
✔ Budget Variance: Difference between planned and actual cost.
✔ Schedule Variance: Difference between planned and actual completion time.
✔ Resource Utilization: How efficiently human resources are used.
Advantages of LOC:
✔ Easy to measure
✔ Helps in estimating project effort
✔ Used for productivity comparison
Disadvantages of LOC:
Example:
A mobile banking app has 50,000 LOC, while a calculator app has only 2,000 LOC. The
banking app is more complex and requires more effort.
Advantages of FP:
Disadvantages of FP:
Example:
4. Number of Modules
A module is an independent unit in a software system that performs a specific function.
Counting modules helps in understanding how modular and maintainable a system is.
It tells you:
Why is it useful?
● Tells you how many test cases you need to cover all logic paths.
Where:
Example:
Where:
● M = Cyclomatic complexity
Example:
How many paths?
3. If x == 0 → "Zero"
Which means:
SOL. M=E-N+2P
M=7-7+2*1=2
HALSTEAD’S SOFTWARE METRICS
Halstead’s Software metrics are a set of measures proposed by Maurice Halstead to evaluate the
complexity of a software program. These metrics are based on the number of distinct operators
and operands in the program and are used to estimate the effort required to develop and maintain
the program. These metrics provide a quantitative assessment of software complexity, aiding in
software development, maintenance, and quality assurance processes. They include measures
such as program length, vocabulary, volume, difficulty, and effort, calculated based on the
number of unique operators and operands in a program.
Token Count
In Halstead’s Software metrics, a computer program is defined as a collection of tokens that can
be described as operators or operands. These tokens are used to analyze the complexity and
volume of a program. Operators are symbols that represent actions, while operands are the
entities on which the operators act. All software science metrics can be specified using these
basic symbols. These symbols are referred to as tokens.
3. Volume (V)
V = N * log₂(n)
→ Represents the size of the program in bits. Think of it like how much “mental effort”
it takes to understand the code.
4. Difficulty (D)
D = (n₁ / 2) * (N₂ / n₂)
→ How hard it is to write or understand the program.
5. Effort (E)
E = D * V
→ The total effort needed to write or understand the program. Measured in mental
work units.
6. Time (T)
T = E / 18
→ Estimated time to code it, in seconds.
7. Bugs (B)
B = E^(2/3) / 3000
→ Estimated number of errors in the program
Question :
Solution:
Int 4 sort 1
() 5 x 7
, 4 n 3
[] 7 i 8
If 2 j 7
< 2 save 3
; 11 im1 3
For 2 2 2
= 6 1 3
– 1 0 1
<= 2 – –
++ 2 – –
Return 2 – –
{} 3 – –
n=n1+n2=14+10=24
N=N1+N2=53+38=91
3. Volume (V)
V=N×log2(n)=91×log2(24) ≈ 91×4.585=417.24
4. Difficulty (D)
D=n1/2×N2/n2=214×1038=7×3.8=26.6
5. Effort (E)
E=D×V=26.6×417.24=11100.58
B=E^2/3/3000≈ (11100.58)2/3/3000≈0.76