0% found this document useful (0 votes)
15 views48 pages

9 SOLID New 23052025 113904am

The document discusses software design improvements through SOLID principles, emphasizing the importance of cohesion and coupling in system components. It outlines each of the five SOLID principles—Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion—along with their definitions, benefits, and examples. The principles aim to create more maintainable, flexible, and reusable code in software development.

Uploaded by

M sami Shahid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views48 pages

9 SOLID New 23052025 113904am

The document discusses software design improvements through SOLID principles, emphasizing the importance of cohesion and coupling in system components. It outlines each of the five SOLID principles—Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion—along with their definitions, benefits, and examples. The principles aim to create more maintainable, flexible, and reusable code in software development.

Uploaded by

M sami Shahid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 48

Improving

Software
Design with
Solid
Principles
Outline

Cohesion & Coupling


SOLID Design Principles
Cohesion & Coupling
Coupling: Degree of Dependence Among Components

No dependencies Loosely coupled-some dependencies

High coupling makes


modifying parts of the
Highly coupled-many dependencies system difficult, e.g.,
modifying a component
affects all the components to
which the component is
Coupling

Content Coupling
 One component references contents of another
 One component modifies or relies on the internal workings
of another module

Common Coupling
 Two components share the same global data
Coupling

Control Coupling
 One Component controls the flow of another, by passing it
information on what to do
 Component passes control parameters to coupled
components

Message Coupling (low)


 Modules are not dependent on each other, instead they use
a public interface to exchange parameter-less messages
Cohesion
• A component is cohesive if all elements of the component are
directed toward and essential for performing the same task
• Several forms of cohesion:
Cohesion

Communicationa
l
Cohesion
Coincidental Cohesion
Coincidental cohesion is when parts of a module are grouped
arbitrarily, without any real, meaningful relationship, leading to
a poorly organized and difficult-to-manage code.
Logical Cohesion
Elements of component are related logically and not
functionally
Temporal Cohesion
Temporal cohesion is when parts of a module are grouped
according to the time in which they are processed
Cohesion

Procedural Cohesion
Procedural cohesion is when parts of a module are
grouped because they always follow a certain sequence
of execution (e.g., a function that checks file permissions
and then opens the file).
Communicational Cohesion
 Module performs a series of actions related by a
sequence of steps to be followed by the product and
all actions are performed on the same data
Cohesion

Sequential Cohesion
 The output of one component is the input to another.
Occurs naturally in functional programming languages
Functional Cohesion
 Functional cohesion is when parts of a module are
grouped because they all contribute to a single well-
defined task of the module
S.O.L.I.D. Design Principles
Software “Smell”
Another perspective
• The system is rigid
• Hard to change because everything has to change at
once
• The system is fragile
• Changes cause the system to break in the strangest of
places.
• The system is immobile
• That is, not reusable.
• The system is opaque
• Hard to understand.
• The system is needlessly complex
• The system contains needless repetition.
SOLID Design Principles

• Introduced by Robert C. Martin


• Agile Principles, Patterns, and Practices in
C#
 Single Responsibility Principle
 Open/Closed Principle
 Liskov Substitution Principle
 Interface Segregation Principle
 Dependency Inversion Principle
Single Responsibility Principle
(SRP)

A class should
have one and only
one reason to
change, meaning
that a class should
have only one job. Just because you can, doesn’t mean you should.
Single Responsibility Principle
(SRP)

 A class should have only one reason to change


 A responsibility is “a reason for change.”
 The responsibilities of a class are axes of change.
 If it has two responsibilities, they are coupled in the

design and so have to change together.


 If a class has more that one responsibility, it may
become fragile when any of the requirements change
SRP – Example

Report

GetData()
FormatReport()
Print()
SRP – Example cnt.
SRP – Example cnt.

Report ReportPrinter

Print() Print()
Report

GetData()
FormatReport()
Print() ReportFormater DataAccess

FormatReport() GetData()
Benefits of SRP
1. Code is smaller

• easier to read

• easier to understand

• easier to maintain

2. Code is potentially easier to test

3. Change is easier to manage

• code is easier to replace


Open/Closed Principle (OCP)

 Classes should be written so


that they can be extended
Software entities without requiring
(module, classes, modification.
functions, etc.)  extend the behaviour of a
should be open for system (in response to a
requested change)
extension but
 add new code
closed for
modification  But not modifying the
existing code
Open/Closed Principle (OCP)

• Once completed, the implementation of a class should only


be modified to correct errors; new or changed features
would require that a different class be created

• Mechanism: Abstraction and subtype polymorphism


are the keys to the OCP
• Introducing Abstract Base Classes
• Implementing common Interfaces
• Deriving from common interfaces or abstract classes
OCP – Example
• Changing the print code
• Format the report into tabloid (instead of 8-1/2 X 11)
• Print the report to a dot-matrix (instead of laser)
printer
Report ReportPrinter

Print() Print()

ReportFormater DataAccess

FormatReport() GetData()
Report ReportPrinter

OCP – Example ct. Print() Print()

ReportFormater DataAccess

FormatReport() GetData()
OCP – Example cnt.
OCP – Example cnt.
DataAccess

Report ReportPrinter GetData()

ReportFormater
Print() Print()

Format()

TabloidReport
TabloidReportPrinter TabloidReportFormater

Print() Print() Format()


OCP – Example cnt.

Note the extension of the system behaviour without making modification to


existing code
Benefits of OCP
1. Design is more stable
• existing (working) code does not change
• changes are made by adding, not modifying, code
• changes are isolated and do not cascade throughout
the code
2. Code is potentially easier to test
3. Change is easier to manage
• code is easier to replace
• design is extensible
4. Code is potentially reusable
Liskov Substitution Principle (LSP)

Subclasses
should be
substitutable
for their base
classes
Liskov Substitution Principle (LSP)
• LSP states that if a program module is using a Base
class, then the reference to the Base class can be
replaced with a Derived class without affecting the
functionality of the program module.

• “A derived class should have some kind of specialized


behaviour (it should provide the same services as the
superclass, only some, at least, are provided
differently.)”

• The contract of the base class must be honoured by


the derived class.

• If this principle is violated, then it will cause the Open-


LSP – Benefits

• Design is more flexible


• a base type can be confidently substituted for a derived
type
• Code is potentially easier to test
• Required to support the Open/Closed Principle
LSP –
Example public class Green {
public void getColor() {
System.out.println("Green");
}
}

public class Blue extends Green {


public void getColor() {
System.out.println("Blue");
}
}

public class Main{


public static void main(String[] args) {
Green green = new Blue();
green.getColor();
}
}
LSP – public interface IColor{
public void getColor();
Example }

public class Green implements IColor {


public void getColor() {
System.out.println("Green");
}
}

public class Blue implements IColor {


public void getColor() {
System.out.println("Blue");
}
}
public class Main{
public static void main(String[] args) {
IColor color = new Blue();
color.getColor();
//output: Blue
}
}
LSP – Implementation

• In which of the following patterns you have seen


its implementation?

1. Façade
2. Strategy
3. Adapter
Interface Segregation Principle
(ISP)
• Clients should not depend on
interfaces that they do not use
Many client-  Interfaces should be thin and not
specific fat
interfaces are
better than one  e.g. if you have an interface
general purpose with 20 methods, then not all
implementers of that interface
interface might not implement all of
those methods
 Bring large and fat interfaces
into smaller ones which classify
the related methods
Interface Segregation Principle
(ISP)
• If you have a class with several different uses, create
separate (narrow) interfaces for each use.

• The purpose is to make clients use as small and as


coherent an interface as possible.

• Fat interfaces lead to inadvertent couplings and


accidental dependencies between classes.
ISP Example public class PDFDocument implements
Document {
public void open() {
public interface // Logic for opening a PDF document
Document { }
void open();
void save(); public void save() {
void print(); // Logic for saving a PDF document
void sendViaEmail(); }
}
public void print() {
// Logic for printing a PDF document
}

public void sendViaEmail() {


// Logic for sending a PDF document via
email
}
ISP Example public class WordDocument implements
Document {
public void open() {
public interface // Logic for opening a Word document
Document { }
void open();
void save(); public void save() {
void print(); // Logic for saving a Word document
void sendViaEmail(); }
}
public void print() {
// Logic for printing a Word document
}

public void sendViaEmail() {


// Logic for sending a Word document via
email
}
ISP Example - Improve
public class PDFDocument implements
public interface OpenSave, Print {
OpenSave { public void open() {
void open(); // Logic for opening a PDF document
void save();
}
}
public interface Print {
void print(); public void save() {
} // Logic for saving a PDF document
public interface }
SendViaEmail {
void sendViaEmail(); public void print() {
} // Logic for printing a PDF document
} }
}
ISP Example - Improve
public class WordDocument implements
public interface OpenSave, SendViaEmail {
OpenSave { public void open() {
void open(); // Logic for opening a Word document
void save();
}
}
public interface Print {
void print(); public void save() {
} // Logic for saving a Word document
public interface }
SendViaEmail {
void sendViaEmail(); public void sendViaEmail() {
} // Logic for sending a Word document via
} email
}
}
ISP – Benefits
• Cohesion is increased
• clients can demand cohesive interfaces
• Design is more stable
• changes are isolated and do not cascade
throughout the code
• Supports the Liskov Substitution Principle
Dependency Inversion Principle
(DIP)
High level • Dependency upon lower-level
components limits the reuse
modules should opportunities of the higher-level
not depend on components
low level
modules, both • Abstractions should not depend
on details
should depend
upon • Change the relation between
abstractions concrete classes to relationships
among abstractions
• Abstraction mechanism:
Abstract base classes or
Interfaces
Dependency Inversion Principle
(DIP)
 The goal of the dependency inversion principle is to:
 decouple high-level components from low-level
components
 such that reuse with different low-level component
implementations becomes possible
 High level classes should contain the “business logic”,
low level classes should contain the details of the
(current) implementation.
 Access instances using interfaces or abstract classes
to avoid dependency inversion.
public class Book {
public class Shelf { void seeReviews()
Book book; { ... }
void addBook(Book book) void readSample()
{ ... } { ... }
void customizeShelf() { }
... } Shelf Depends on Book Class
}

public class DVD {


void seeReviews() {
New Requirement to add DVDs .. }
To shelf now void watchSample() {
.. }
}
public class Book {
public class Shelf { void seeReviews()
Book book; { ... }
void addBook(Book book) void readSample()
{ ... } { ... }
void customizeShelf() { }
... } Shelf Depends on Book Class
}

public class DVD {


void seeReviews() {
New Requirement to add DVDs .. }
To shelf now? void watchSample() {
.. }
What needs to be changed?
}
public class Shelf {
Product product;
public interface Product
void addProduct(Product product){
{ void seeReviews();
... }
void customizeShelf(){ void getSample(); }
... }
} Shelf now depends on an Abstraction

public class Book implements public class DVD implements


Product{ Product{
@Override @Override
public void seeReviews(){ public void seeReviews(){
.. } .. }
@Override @Override
public void getSample(){ public void getSample(){
.. } .. }
} }
Dependency Inversion Principle
(DIP)

DataAccess

Report ReportPrinter GetData()

ReportFormater
Print() Print()

Format()

TabloidReport
TabloidReportPrinter TabloidReportFormater
Print()
Print() Format()
DIP – Benefits
 Enables design by contract
 change is easier to manage
 code is easier to replace
 design is extensible
 Code is potentially easier to test

You might also like