0% found this document useful (0 votes)
25 views

SOLID

SOLID is a set of principles for object-oriented design that aims to make software more understandable, flexible and maintainable. It consists of 5 principles: Single Responsibility Principle (SRP), Open-Closed Principle (OCP), Liskov Substitution Principle (LSP), Interface Segregation Principle (ISP) and Dependency Inversion Principle (DIP). Following these principles helps create modular, reusable and testable code that is less prone to bugs and easier to maintain.
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)
25 views

SOLID

SOLID is a set of principles for object-oriented design that aims to make software more understandable, flexible and maintainable. It consists of 5 principles: Single Responsibility Principle (SRP), Open-Closed Principle (OCP), Liskov Substitution Principle (LSP), Interface Segregation Principle (ISP) and Dependency Inversion Principle (DIP). Following these principles helps create modular, reusable and testable code that is less prone to bugs and easier to maintain.
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/ 23

 What is SOLID

 SOLID is a structured design approach that ensures your


software is modular and easy to maintain, understand,
debug, and refactor.
 Following SOLID also helps save time and effort in both
development and maintenance. SOLID prevents your code
from becoming rigid and fragile, which helps you build
long-lasting software.
 When it comes to designing flexible, scalable,
maintainable, and reusable code in software development,
Object-Oriented Design is critical.
The SOLID Principles

 S — Single Responsibility
 A class should have a single responsibility
 Goal
 Thisprinciple aims to separate behaviours so that if
bugs arise as a result of your change, it won’t affect
other unrelated behaviours.

IMPLIMENTATION :

 Example: Think of a mobile phone. A mobile phone


has multiple components like a camera, a touchscreen, a
speaker, etc. Each of these components has its own
distinct function. Applying SRP in code, you would
create separate classes for each component rather than
having a single class that handles all functionalities.
 // Before SRP
class MobilePhone {
void makeCall() { /* ... */ }
void takePhoto() { /* ... */ }
void playMusic() { /* ... */ }
}

// After SRP
class Call {
void makeCall() { /* ... */ }
}
class Camera {
void takePhoto() { /* ... */ }
}

class MusicPlayer {
void playMusic() { /* ... */ }
}
 O — Open-Closed
 Classes should be open for extension, but closed for
modification
Goal
 This principle aims to extend a Class’s behaviour without
changing the existing behaviour of that Class. This is to
avoid causing bugs wherever the Class is being used.

Example

 Consider a geometric shapes library. Instead of modifying


the existing shape classes when adding new shapes, you
could create a common interface for all shapes and extend
that interface to create new shapes. This way, existing
code remains unchanged while new shapes can be easily
added.
 // Before OCP

class Circle {
double radius;

double area() {
return Math.PI * radius * radius;
}
}
 // After OCP

interface Shape {
double area();
}

class Circle implements Shape {


double radius;

@Override
public double area() {
return Math.PI * radius * radius;
}
}

class Rectangle implements Shape {


double width;
double height;

@Override
public double area() {
return width * height;
}
}
 L — Liskov Substitution
 If S is a subtype of T, then objects of type T in a program
may be replaced with objects of type S without altering
any of the desirable properties of that program.
 When a child Class cannot perform the same actions as
its parent Class, this can cause bugs.

 Goal
 This principle aims to enforce consistency so that the parent
Class or its child Class can be used in the same way without
any errors.

 Example

Imagine a scenario where you have a base class “Bird” and


derived classes “Sparrow” and “Ostrich”. If you follow LSP,
you should be able to use any instance of a derived class (e.g.,
“Sparrow”) wherever an instance of the base class (“Bird”) is
expected, without causing unexpected behavior.
 class Bird {
void fly() { /* ... */ }
}

class Sparrow extends Bird {


@Override
void fly() { /* ... */ }
}

class Ostrich extends Bird {


// This class doesn't override fly()
}
 I — Interface Segregation
 Clients should not be forced to depend on methods that they
do not use.
 When a Class is required to perform actions that are not
useful, it is wasteful and may produce unexpected bugs if
the Class does not have the ability to perform those actions.
 Goal
 This principle aims at splitting a set of actions into smaller
sets so that a Class executes ONLY the set of actions it
requires.
 Example

 In a messaging application, you might have interfaces for


sending, receiving, and displaying messages. Instead of
having a single large interface for all messaging operations,
you would split it into smaller interfaces so that classes only
need to implement the methods relevant to them.
 // Before ISP
interface Messaging {
void send();
void receive();
void display();
}

// After ISP
interface Sender {
void send();
}

interface Receiver {
void receive();
}

interface Displayable {
void display();
 D — Dependency Inversion
 - High-level modules should not depend on low-level
modules. Both should depend on the abstraction.
 - Abstractions should not depend on details. Details should
depend on abstractions.
 Goal
 This principle aims at reducing the dependency of a high-level
Class on the low-level Class by introducing an interface.

// Before DIP
class MusicPlayer {
void playMP3() { /* ... */ }
}

class AudioApp {
private MusicPlayer musicPlayer = new MusicPlayer();

void playAudio() {
musicPlayer.playMP3();
}
}
 // After DIP

interface AudioPlayer {
void play();
}

class MP3Player implements AudioPlayer {


@Override
public void play() { /* ... */ }
}

class AudioApp {
private AudioPlayer audioPlayer;

AudioApp(AudioPlayer audioPlayer) {
this.audioPlayer = audioPlayer;
}

void playAudio() {
audioPlayer.play();
}
}
 SOLID principles | Advantages

 Increased maintainability: By adhering to the SOLID


principles, code is written in a way that is more easily
understood and less prone to errors. This makes it easier to
change and update the code over time without introducing
bugs.
 Improved readability: The SOLID principles help to create
code that is more organized and easier to read. This makes it
easier for developers to understand the codebase and make
changes to it.
 Increased scalability: The SOLID principles help to create
code that is more flexible and extensible. This makes it
easier to add new features and functionality to the codebase
without introducing bugs or causing issues with existing
code.
 Better testability: The SOLID principles help to create
code that is more testable, which allows for more thorough
testing and fewer bugs.
 Reduced coupling: The SOLID principles help to create
code that is less tightly coupled, which makes it less likely
that changes to one part of the system will affect other
parts.
 Enhanced reusability: SOLID principles make the code
more reusable by making the code more modular, which
makes it easier to reuse parts of the codebase in other
projects.
 Better performance: By following SOLID principles, the
codebase is optimized for performance and scalability
which results in faster and more efficient software.
 SOLID principles | Disadvantages

 Increased complexity: Adhering to the SOLID principles


can lead to a more complex codebase, as it requires splitting
code into smaller, more focused classes and interfaces.
 More classes and interfaces: Following SOLID principles
can lead to creating more classes and interfaces, which can
make the codebase harder to navigate.
 Over-engineering: It's possible to apply SOLID principles
too strictly, which can lead to over-engineering and
unnecessary complexity.
 Difficulty in understanding: SOLID principles are not easy
to understand and implement, especially for junior
developers or developers who are new to software
development.
 Additional time and effort required: Adhering to SOLID
principles requires extra time and effort, as it requires a lot
of planning and design before you start writing code.
 Limited use-cases: SOLID principles are a good fit for
large-scale projects but may not be suitable for small
projects where the overhead of creating multiple classes and
interfaces is not worth the benefits.
 Limited flexibility: SOLID principles can be limiting in
terms of flexibility as it may not be easy to change the
design once it's implemented.

You might also like