SOLID Principles
Single-responsiblity Principle
Open-closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
The solid principles are a set of best practices, transformed
into a set of rules after dozens of years of cumulative
development experience around the world done by software
professionals.
2
Single-Responsibility Principle
A class should have one and only one reason to change,
meaning that a class/method should have only one job.
3
Single-Responsibility Principle
The single responsibility principle is one of the most common
design principles in OO programming.
You can apply it to classes, software components, and
microservices.
4
Single-Responsibility Principle
The purpose of those principles is to allow developers to
write better software.
The software is easier and cheaper to maintain, easier to
understand, faster to develop in a team, and easier to test.
Following those principles doesn’t guarantee success, but
avoiding them will lead in most cases to at least sub-optimal
results in terms of functionality, cost, or both.
5
Open-Closed Principle
Class isn’t allowed to have more than one responsibility
This avoids any unnecessary, technical coupling between
responsibilities
Reduces the probability that you need to change your class.
It also lowers the complexity of each change because it reduces
the number of dependent classes that are affected by it.
6
Open-Closed Principle
Objects or entities should be open for extension but closed
for modification.
7
Open-Closed Principle
You will be able to add new functionality without changing the
existing code.
That prevents situations in which a change to one of your
classes also requires you to adapt all depending classes.
Inheritance is proposed to use this goal.
Inheritance introduces tight coupling if the subclasses depend
on implementation details of their parent class.
8
Open-Closed Principle
Open/Closed Principle can also be defined using
the Polymorphic Open/Closed Principle.
It uses interfaces instead of superclasses to allow different
implementations without changing the code that uses them.
The interfaces are closed for modifications, and you can
provide new implementations to extend the functionality of your
software.
9
Open-Closed Principle
An interface introduces an additional level of abstraction which
enables loose coupling.
The implementations of an interface are independent of each
other and don’t share any code.
If you consider it beneficial that two implementations of an
interface share some code, you can either
use inheritance or composition.
10
Liskov Substitution Principle
Avoid from wrong abstraction.
Every subclass or derived class should be substitutable for their
base or parent class.
11
Liskov Substitution Principle
The principle defines that objects of a superclass shall be
replaceable with objects of its subclasses without breaking the
application.
That requires the objects of your subclasses to behave in the
same way as the objects of your superclass.
12
Liskov Substitution Principle
An overridden method of a subclass needs to accept the
same input parameter values as the method of the
superclass.
Otherwise, any code that calls this method on an object of
the superclass might cause an exception, if it gets called
with an object of the subclass.
13
Interface Segregation Principle (ISP)
No code should be forced to depend on interfaces that it
does not use.
ISP principle divides interfaces that are very large into
smaller and more specific ones so that clients will only have
to know about the methods that are of interest to them.
14
Interface Segregation Principle (ISP)
Similar to the Single Responsibility Principle, the goal of the
ISP is to reduce the side effects and frequency of required
changes by splitting the software into multiple, independent
parts.
15
Interface Segregation Principle (ISP)
We can prevent large interfaces that define methods for
multiple responsibilities.
As explained in the Single Responsibility Principle,
avoid classes and interfaces with multiple responsibilities
because they change often and make your software hard to
maintain.
18
Dependency Inversion Principle
High-level modules should not import anything from low-level
modules.
Both should depend on abstractions (e.g., interfaces).
Abstractions should not depend on details.
Details (concrete implementations) should depend on
abstractions.
Dependency Inversion Principle
High-level modules, which provide complex logic, should be
easily reusable and unaffected by changes in low-level
modules, which provide utility features.
To achieve that, we need to introduce an abstraction that
decouples the high-level and low-level modules from each
other.
20
21
Introducing abstractions
Dependency Inversion Principle
You only need to apply the Open/Closed and the Liskov
Substitution principles to your code base.
After you have done that, your classes also comply with the
Dependency Inversion Principle.
23
24