SlideShare a Scribd company logo
1 of 20
S.O.L.I.D Principles
HUMAYUN KHAN
SOLID
 The SOLID principles are five dependency management for object oriented
programming and design.
 The SOLID acronym was introduced by Robert Cecil Martin, also known as "Uncle Bob".
 Each letter represents another three-letter acronym that describes one principle.
 When working with software in which dependency management is handled badly,
the code can become rigid, fragile and difficult to reuse.
 Rigid code is that which is difficult to modify, either to change existing functionality or
add new features.
 Fragile code is susceptible to the introduction of bugs, particularly those that appear in
a module when another area of code is changed.
If you follow the SOLID principles, you can produce code that is more flexible and robust,
and that has a higher possibility for reuse.
The S.O.L.I.D Principles
Single
Responsibility
Principle
Liskovs
Substitution
Principle
Dependency
Inversion
Principle
Single Responsibility Principle
The Single Responsibility Principle (SRP)
states that there should never be more than one
reason for a class to change.
This means that you should design your classes
so that each has a single purpose.
This does not mean that each class should have
only one method but that all of the members in
the class are related to the class's primary
function.
Where a class has multiple responsibilities,
these should be separated into new classes.
When a class has multiple responsibilities, the
likelihood that it will need to be changed
increases.
Each time a class is modified the risk of
introducing bugs grows.
By concentrating on a single responsibility, this
risk is limited.
SRP Violation Example
The code on LHS is a class that communicates with a hardware
device to monitor the oxygen levels in some water.
The class includes:
Method named "ReadOxygenLevel" that retrieves a value from a
stream generated by the oxygen monitoring hardware. It converts
the value to a percentage and stores it in the OxygenSaturation
property.
Second method, "OxygenLow", checks the oxygen saturation to
ensure that it exceeds the minimum level of 75%.
The "ShowLowOxygenAlert" shows a warning that contains the
current saturation value.
There are at least three reasons for change within the OxygenMeter
class.
1. If the oxygen monitoring hardware is replaced the
ReadOxygenLevel method will need to be updated.
2. If the process for determining low oxygen is changed, perhaps
to include a temperature variable, the class will need updating.
3. Finally, if the alerting requirements become more sophisticated
than outputting text to the console, the ShowLowOxygenAlert
method will need to be rewritten.
SRP Refactored
NB: The refactored example code on LHS
breaks other SOLID principles in order that
the application of the SRP is visible.
Further refactoring of this example is
necessary to achieve compliance with the
other four principles.
Open Closed Principle
Open/Closed principle says that a class should be open
for extension but closed for modification.
"Open to extension" means that you should design your
classes so that new functionality can be added as new
requirements are generated.
"Closed for modification" means that once you have
developed a class you should never modify it, except to
correct bugs.
The reason is that if you modify a class, you’ll likely
break the API/Contract of the class which means that
the classes that depend on it might fail when you do so.
If you instead inherit the class to add new features, the
base contract is untouched and it’s unlikely that
dependent classes will fail.
OCP Violation Example
The code in LHS is a basic module for logging
messages.
The Logger class has a single method that
accepts a message to be logged and the type of
logging to perform.
The switch statement changes the action
according to whether the program is outputting
messages to the console or to the default
printer.
If you wished to add a third type of logging, perhaps sending the logged messages to a message queue or
storing them in a database, you could not do so without modifying the existing code.
Firstly, you would need to add new LogType constants for the new methods of logging messages.
Secondly you would need to extend the switch statement to check for the new LogTypes and output or store
messages accordingly. This violates the OCP.
OCP Refactored
We can easily refactor the logging code to achieve compliance with the OCP.
Firstly we need to remove the LogType enumeration, as this restricts the types
of logging that can be included.
Instead of passing the type to the Logger, we will create a new class for each
type of message logger that we require.
In the final code we will have two such classes, named ConsoleLogger and
PrinterLogger.
Additional logging types could be added later without changing any existing
code.
The Logger class still performs all logging but using one of the message logger
classes described above to output a message. In order that the classes are not
tightly coupled, each message logger type implements the IMessageLogger
interface.
The Logger class is never aware of the type of logging being used as its
dependency is provided as an IMessageLogger instance using constructor
injection.
Liskovs Substitution Principle
Liskovs Substitution Principle states that any
method that takes class X as a parameter must
be able to work with any subclasses of X.
Robert Cecil Martin's simpler version is,
"Functions that use pointers or references to
base classes must be able to use objects of
derived classes without knowing it".
For languages such as C#, this can be changed
to "Code that uses a base class must be able to
substitute a subclass without knowing it".
The principle makes sure that every class follows
the contract defined by its parent class.
LSP Violation Example
The code in LHS shows the outline of several classes:
The first class represents a project that contains a number of
project files. Two methods are included that load the file data
for every project file and save all of the files to disk.
The second class describes a project file. This has a property
for the file name and a byte array that contains file data once
loaded. Two methods allow the file data to be loaded or
saved.
The third class may have been added to the solution at a later
time to the other two classes, perhaps when a new
requirement was created that some project files would be
read-only. The ReadOnlyFile class inherits its functionality
from ProjectFile. However, as read-only files cannot be
saved, the SaveFileData method has been overridden so that
an invalid operation exception is thrown.
The ReadOnlyFile class violates the LSP in several ways.
Although all of the members of the base class are
implemented, clients cannot substitute ReadOnlyFile
objects for ProjectFile objects.
This is clear in the SaveFileData method, which
introduces an exception that cannot be thrown by the
base class.
Next, a post-condition of the SaveFileData method in the
base class is that the file has been updated on disk. This
is not the case with the subclass. The final problem can
be seen in the SaveAllFiles method of the Project class.
Here the programmer has added an if statement to ensure
that the file is not read-only before attempting to save it.
This violates the LSP and the OCP as the Project class
must be modified to allow new ProjectFile subclasses to
be detected.
LSP Violation Example…
LSP Refactored
There are various ways in which the code can be refactored
to comply with the LSP.
The Project class has been modified to include
two collections instead of one. One collection contains all of
the files in the project and one holds references to writeable
files only.
The LoadAllFiles method loads data into all of the files in the
AllFiles collection. As the files in the WriteableFiles collection
will be a subset of the same references, the data will be
visible via these also.
The SaveAllFiles method has been replaced with a method
that saves only the writeable files.
The ProjectFile class now contains only one method, which
loads the file data. This method is required for both writeable
and read-only files. The new WriteableFile class extends
ProjectFile, adding a method that saves the file data.
This reversal of the hierarchy means that the code now
complies with the LSP.
Interface Segregation Principle
ISP states that interfaces that have become “fat”
(like god classes) should be split into several
interfaces. Large interfaces makes it harder to
extend smaller parts of the system.
In other words…
The Interface Segregation Principle (ISP) states
that clients should not be forced to depend upon
interfaces that they do not use. When we have
non-cohesive interfaces, the ISP guides us to
create multiple, smaller, cohesive interfaces. The
original class implements each such interface.
Client code can then refer to the class using the
smaller interface without knowing that other
members exist.
ISP Violation Example
Code in LHS shows the outline of three classes:
The Contact class represents a person or business
that can be contacted. The class holds the
person's name, address, email address and
telephone number.
The Emailer class sends email messages to
contacts. The contact and the subject and body of
the email are passed to the parameters.
The Dialler class extracts the telephone number
from the Contact and calls it using an automatic
dialling system.
The example code violates the ISP.
The Emailer class is a client of the Contact class.
Although it only requires access to the Name and
EmailAddress properties, it is aware of other
members too. Similarly, the Dialler class uses a
single property, Telephone. However, it has access
to the entire Contact interface.
ISP Refactored
To refactor the code to comply with the ISP we need to hide unused
members from the client classes. We can achieve this by introducing
two new interfaces, both implemented by Contact.
The IEmailable interface defines properties that hold the name and
email address of an object that can receive email.
The IDiallable interface includes only a Telephone property, which is
enough to allow client classes to call the telephone number of a
target object.
The Email class is updated, replacing the Contact dependency with
an IEmailable object.
Similarly, the Dialler's dependency becomes an IDiallable instance.
Both classes now interact with contacts using the smallest possible
interface.
With smaller interfaces it is easier to introduce new classes that
implement them. To demonstrate, the refactored code includes a new
class named MobileEngineer. This represents engineers that visit
customer sites. Engineer has properties for a name, telephone
number and vehicle registration. The class implements IDiallable so
that the Dialler object can call engineers.
Dependency Inversion Principle
The principle which is easiest to understand.
DIP states that you should let the caller create the
dependencies instead of letting the class itself
create the dependencies. Hence inverting the
dependency control (from letting the class control
them to letting the caller control them).
In other words…
The Dependency Inversion Principle (DIP) states
that high level modules should not depend upon
low level modules. Both should depend upon
abstractions. Secondly, abstractions should not
depend upon details. Details should depend upon
abstractions.
DIP Violation Example
The problem with such a design is that the high
level TransferManager class is directly dependent
upon the lower level BankAccount class.
The Source and Destination properties reference
the BankAccount type.
This makes it impossible to substitute other
account types unless they are subclasses of
BankAccount.
If we later want to add the ability to transfer money
from a bank account to pay bills, the BillAccount
class would have to inherit from BankAccount.
Further problems arise should changes be
required to low level modules.
A change in the BankAccount class may break the
TransferManager. In more complex scenarios,
changes to low level classes can cause problems
that cascade upwards through the hierarchy of
modules. As the software grows, this structural
problem can be compounded and the software
can become fragile or rigid.
DIP Refactored
Applying the DIP resolves these problems by
removing direct dependencies between classes.
To comply with the DIP we must remove the
direct dependency that the TransferManager
has on the BankAccount class. We could
introduce a new interface for accounts that
contains the methods we require to add and
remove funds. However, in this case I have
introduced two new interfaces. ITransferSource
includes a method that allows funds to be
removed from an account. ITransferDestination
includes the method for adding funds to an
account.
The separation of the two interfaces complies with the Interface Segregation Principle (ISP)
and allows for the inclusion of accounts that accept payments but cannot be the source of
funds. The BankAccount class is modified so that it implements the new interfaces.
TransferManager is modified so that the Source property expects an ITransferSource object
and the destination is an ITransferDestination. No direct dependencies on concrete classes
now exist. Instead, both the high level class and the low level class depend upon the two
abstractions.
Solid Principles

More Related Content

What's hot (20)

Spring Boot in Action
Spring Boot in Action Spring Boot in Action
Spring Boot in Action
 
Solid principles
Solid principlesSolid principles
Solid principles
 
SOLID
SOLIDSOLID
SOLID
 
SOLID principles
SOLID principlesSOLID principles
SOLID principles
 
TypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the painTypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the pain
 
SOLID Design Principles
SOLID Design PrinciplesSOLID Design Principles
SOLID Design Principles
 
Solid Principles
Solid PrinciplesSolid Principles
Solid Principles
 
Open Closed Principle kata
Open Closed Principle kataOpen Closed Principle kata
Open Closed Principle kata
 
Spring boot
Spring bootSpring boot
Spring boot
 
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID PrinciplesRefactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
 
Dependency injection ppt
Dependency injection pptDependency injection ppt
Dependency injection ppt
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Spring Framework - Core
Spring Framework - CoreSpring Framework - Core
Spring Framework - Core
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
What is component in reactjs
What is component in reactjsWhat is component in reactjs
What is component in reactjs
 
reactJS
reactJSreactJS
reactJS
 
Introduction to React JS for beginners
Introduction to React JS for beginners Introduction to React JS for beginners
Introduction to React JS for beginners
 
TypeScript Best Practices
TypeScript Best PracticesTypeScript Best Practices
TypeScript Best Practices
 
Maven
MavenMaven
Maven
 

Similar to Solid Principles

Object Oriented Concepts and Principles
Object Oriented Concepts and PrinciplesObject Oriented Concepts and Principles
Object Oriented Concepts and Principlesdeonpmeyer
 
Solid principles
Solid principlesSolid principles
Solid principlesNhan Nguyen
 
Software design principles - jinal desai
Software design principles - jinal desaiSoftware design principles - jinal desai
Software design principles - jinal desaijinaldesailive
 
C# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringC# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringEyob Lube
 
Module 3: Introduction to LINQ (Material)
Module 3: Introduction to LINQ (Material)Module 3: Introduction to LINQ (Material)
Module 3: Introduction to LINQ (Material)Mohamed Saleh
 
Sec1_SOLID Principles_Software Engineering.pptx
Sec1_SOLID Principles_Software Engineering.pptxSec1_SOLID Principles_Software Engineering.pptx
Sec1_SOLID Principles_Software Engineering.pptxHebaSamy22
 
4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPT4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPTAjay Chimmani
 
Top 30 Technical interview questions
Top 30 Technical interview questionsTop 30 Technical interview questions
Top 30 Technical interview questionsSohailSaifi15
 
Mit302 web technologies
Mit302 web technologiesMit302 web technologies
Mit302 web technologiessmumbahelp
 
DesignPrinciples-and-DesignPatterns
DesignPrinciples-and-DesignPatternsDesignPrinciples-and-DesignPatterns
DesignPrinciples-and-DesignPatternsBasavaraj Patil
 
Mca5010 web technologies
Mca5010   web technologiesMca5010   web technologies
Mca5010 web technologiessmumbahelp
 

Similar to Solid Principles (20)

Object Oriented Concepts and Principles
Object Oriented Concepts and PrinciplesObject Oriented Concepts and Principles
Object Oriented Concepts and Principles
 
OO Design Principles
OO Design PrinciplesOO Design Principles
OO Design Principles
 
Solid principles
Solid principlesSolid principles
Solid principles
 
Software design principles - jinal desai
Software design principles - jinal desaiSoftware design principles - jinal desai
Software design principles - jinal desai
 
C# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringC# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoring
 
Java Notes
Java NotesJava Notes
Java Notes
 
Module 3: Introduction to LINQ (Material)
Module 3: Introduction to LINQ (Material)Module 3: Introduction to LINQ (Material)
Module 3: Introduction to LINQ (Material)
 
Sec1_SOLID Principles_Software Engineering.pptx
Sec1_SOLID Principles_Software Engineering.pptxSec1_SOLID Principles_Software Engineering.pptx
Sec1_SOLID Principles_Software Engineering.pptx
 
Concurrency and parallel in .net
Concurrency and parallel in .netConcurrency and parallel in .net
Concurrency and parallel in .net
 
4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPT4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPT
 
Top 30 Technical interview questions
Top 30 Technical interview questionsTop 30 Technical interview questions
Top 30 Technical interview questions
 
Objc
ObjcObjc
Objc
 
L07 Design Principles
L07 Design PrinciplesL07 Design Principles
L07 Design Principles
 
Java 8-revealed
Java 8-revealedJava 8-revealed
Java 8-revealed
 
Mit302 web technologies
Mit302 web technologiesMit302 web technologies
Mit302 web technologies
 
DesignPrinciples-and-DesignPatterns
DesignPrinciples-and-DesignPatternsDesignPrinciples-and-DesignPatterns
DesignPrinciples-and-DesignPatterns
 
Ad507
Ad507Ad507
Ad507
 
Mca5010 web technologies
Mca5010   web technologiesMca5010   web technologies
Mca5010 web technologies
 
C# interview
C# interviewC# interview
C# interview
 
Oop
OopOop
Oop
 

Recently uploaded

Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsHyundai Motor Group
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 

Recently uploaded (20)

Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 

Solid Principles

  • 2. SOLID  The SOLID principles are five dependency management for object oriented programming and design.  The SOLID acronym was introduced by Robert Cecil Martin, also known as "Uncle Bob".  Each letter represents another three-letter acronym that describes one principle.  When working with software in which dependency management is handled badly, the code can become rigid, fragile and difficult to reuse.  Rigid code is that which is difficult to modify, either to change existing functionality or add new features.  Fragile code is susceptible to the introduction of bugs, particularly those that appear in a module when another area of code is changed. If you follow the SOLID principles, you can produce code that is more flexible and robust, and that has a higher possibility for reuse.
  • 4. Single Responsibility Principle The Single Responsibility Principle (SRP) states that there should never be more than one reason for a class to change. This means that you should design your classes so that each has a single purpose. This does not mean that each class should have only one method but that all of the members in the class are related to the class's primary function. Where a class has multiple responsibilities, these should be separated into new classes. When a class has multiple responsibilities, the likelihood that it will need to be changed increases. Each time a class is modified the risk of introducing bugs grows. By concentrating on a single responsibility, this risk is limited.
  • 5. SRP Violation Example The code on LHS is a class that communicates with a hardware device to monitor the oxygen levels in some water. The class includes: Method named "ReadOxygenLevel" that retrieves a value from a stream generated by the oxygen monitoring hardware. It converts the value to a percentage and stores it in the OxygenSaturation property. Second method, "OxygenLow", checks the oxygen saturation to ensure that it exceeds the minimum level of 75%. The "ShowLowOxygenAlert" shows a warning that contains the current saturation value. There are at least three reasons for change within the OxygenMeter class. 1. If the oxygen monitoring hardware is replaced the ReadOxygenLevel method will need to be updated. 2. If the process for determining low oxygen is changed, perhaps to include a temperature variable, the class will need updating. 3. Finally, if the alerting requirements become more sophisticated than outputting text to the console, the ShowLowOxygenAlert method will need to be rewritten.
  • 6. SRP Refactored NB: The refactored example code on LHS breaks other SOLID principles in order that the application of the SRP is visible. Further refactoring of this example is necessary to achieve compliance with the other four principles.
  • 7. Open Closed Principle Open/Closed principle says that a class should be open for extension but closed for modification. "Open to extension" means that you should design your classes so that new functionality can be added as new requirements are generated. "Closed for modification" means that once you have developed a class you should never modify it, except to correct bugs. The reason is that if you modify a class, you’ll likely break the API/Contract of the class which means that the classes that depend on it might fail when you do so. If you instead inherit the class to add new features, the base contract is untouched and it’s unlikely that dependent classes will fail.
  • 8. OCP Violation Example The code in LHS is a basic module for logging messages. The Logger class has a single method that accepts a message to be logged and the type of logging to perform. The switch statement changes the action according to whether the program is outputting messages to the console or to the default printer. If you wished to add a third type of logging, perhaps sending the logged messages to a message queue or storing them in a database, you could not do so without modifying the existing code. Firstly, you would need to add new LogType constants for the new methods of logging messages. Secondly you would need to extend the switch statement to check for the new LogTypes and output or store messages accordingly. This violates the OCP.
  • 9. OCP Refactored We can easily refactor the logging code to achieve compliance with the OCP. Firstly we need to remove the LogType enumeration, as this restricts the types of logging that can be included. Instead of passing the type to the Logger, we will create a new class for each type of message logger that we require. In the final code we will have two such classes, named ConsoleLogger and PrinterLogger. Additional logging types could be added later without changing any existing code. The Logger class still performs all logging but using one of the message logger classes described above to output a message. In order that the classes are not tightly coupled, each message logger type implements the IMessageLogger interface. The Logger class is never aware of the type of logging being used as its dependency is provided as an IMessageLogger instance using constructor injection.
  • 10. Liskovs Substitution Principle Liskovs Substitution Principle states that any method that takes class X as a parameter must be able to work with any subclasses of X. Robert Cecil Martin's simpler version is, "Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it". For languages such as C#, this can be changed to "Code that uses a base class must be able to substitute a subclass without knowing it". The principle makes sure that every class follows the contract defined by its parent class.
  • 11. LSP Violation Example The code in LHS shows the outline of several classes: The first class represents a project that contains a number of project files. Two methods are included that load the file data for every project file and save all of the files to disk. The second class describes a project file. This has a property for the file name and a byte array that contains file data once loaded. Two methods allow the file data to be loaded or saved. The third class may have been added to the solution at a later time to the other two classes, perhaps when a new requirement was created that some project files would be read-only. The ReadOnlyFile class inherits its functionality from ProjectFile. However, as read-only files cannot be saved, the SaveFileData method has been overridden so that an invalid operation exception is thrown.
  • 12. The ReadOnlyFile class violates the LSP in several ways. Although all of the members of the base class are implemented, clients cannot substitute ReadOnlyFile objects for ProjectFile objects. This is clear in the SaveFileData method, which introduces an exception that cannot be thrown by the base class. Next, a post-condition of the SaveFileData method in the base class is that the file has been updated on disk. This is not the case with the subclass. The final problem can be seen in the SaveAllFiles method of the Project class. Here the programmer has added an if statement to ensure that the file is not read-only before attempting to save it. This violates the LSP and the OCP as the Project class must be modified to allow new ProjectFile subclasses to be detected. LSP Violation Example…
  • 13. LSP Refactored There are various ways in which the code can be refactored to comply with the LSP. The Project class has been modified to include two collections instead of one. One collection contains all of the files in the project and one holds references to writeable files only. The LoadAllFiles method loads data into all of the files in the AllFiles collection. As the files in the WriteableFiles collection will be a subset of the same references, the data will be visible via these also. The SaveAllFiles method has been replaced with a method that saves only the writeable files. The ProjectFile class now contains only one method, which loads the file data. This method is required for both writeable and read-only files. The new WriteableFile class extends ProjectFile, adding a method that saves the file data. This reversal of the hierarchy means that the code now complies with the LSP.
  • 14. Interface Segregation Principle ISP states that interfaces that have become “fat” (like god classes) should be split into several interfaces. Large interfaces makes it harder to extend smaller parts of the system. In other words… The Interface Segregation Principle (ISP) states that clients should not be forced to depend upon interfaces that they do not use. When we have non-cohesive interfaces, the ISP guides us to create multiple, smaller, cohesive interfaces. The original class implements each such interface. Client code can then refer to the class using the smaller interface without knowing that other members exist.
  • 15. ISP Violation Example Code in LHS shows the outline of three classes: The Contact class represents a person or business that can be contacted. The class holds the person's name, address, email address and telephone number. The Emailer class sends email messages to contacts. The contact and the subject and body of the email are passed to the parameters. The Dialler class extracts the telephone number from the Contact and calls it using an automatic dialling system. The example code violates the ISP. The Emailer class is a client of the Contact class. Although it only requires access to the Name and EmailAddress properties, it is aware of other members too. Similarly, the Dialler class uses a single property, Telephone. However, it has access to the entire Contact interface.
  • 16. ISP Refactored To refactor the code to comply with the ISP we need to hide unused members from the client classes. We can achieve this by introducing two new interfaces, both implemented by Contact. The IEmailable interface defines properties that hold the name and email address of an object that can receive email. The IDiallable interface includes only a Telephone property, which is enough to allow client classes to call the telephone number of a target object. The Email class is updated, replacing the Contact dependency with an IEmailable object. Similarly, the Dialler's dependency becomes an IDiallable instance. Both classes now interact with contacts using the smallest possible interface. With smaller interfaces it is easier to introduce new classes that implement them. To demonstrate, the refactored code includes a new class named MobileEngineer. This represents engineers that visit customer sites. Engineer has properties for a name, telephone number and vehicle registration. The class implements IDiallable so that the Dialler object can call engineers.
  • 17. Dependency Inversion Principle The principle which is easiest to understand. DIP states that you should let the caller create the dependencies instead of letting the class itself create the dependencies. Hence inverting the dependency control (from letting the class control them to letting the caller control them). In other words… The Dependency Inversion Principle (DIP) states that high level modules should not depend upon low level modules. Both should depend upon abstractions. Secondly, abstractions should not depend upon details. Details should depend upon abstractions.
  • 18. DIP Violation Example The problem with such a design is that the high level TransferManager class is directly dependent upon the lower level BankAccount class. The Source and Destination properties reference the BankAccount type. This makes it impossible to substitute other account types unless they are subclasses of BankAccount. If we later want to add the ability to transfer money from a bank account to pay bills, the BillAccount class would have to inherit from BankAccount. Further problems arise should changes be required to low level modules. A change in the BankAccount class may break the TransferManager. In more complex scenarios, changes to low level classes can cause problems that cascade upwards through the hierarchy of modules. As the software grows, this structural problem can be compounded and the software can become fragile or rigid.
  • 19. DIP Refactored Applying the DIP resolves these problems by removing direct dependencies between classes. To comply with the DIP we must remove the direct dependency that the TransferManager has on the BankAccount class. We could introduce a new interface for accounts that contains the methods we require to add and remove funds. However, in this case I have introduced two new interfaces. ITransferSource includes a method that allows funds to be removed from an account. ITransferDestination includes the method for adding funds to an account. The separation of the two interfaces complies with the Interface Segregation Principle (ISP) and allows for the inclusion of accounts that accept payments but cannot be the source of funds. The BankAccount class is modified so that it implements the new interfaces. TransferManager is modified so that the Source property expects an ITransferSource object and the destination is an ITransferDestination. No direct dependencies on concrete classes now exist. Instead, both the high level class and the low level class depend upon the two abstractions.

Editor's Notes

  1. To refactor the code we will separate the functionality into three classes. The first is the OxygenMeter class. This retains the OxygenSaturation property and the ReadOxygenLevel method. You could decide to split these members into separate classes. In this case we will keep them together as they are closely related. The other methods are removed so that the only reason for change is replacement of the monitoring hardware. The second class is named "OxygenSaturationChecker". This class includes a single method that compares the oxygen level with the minimum acceptable value. The method is the same as the original version except for the addition of a parameter that injects an OxygenMeter object containing the saturation level to test. The only reason for the class to change is if the test process is changed. The final class is named "OxygenAlerter". This displays an alert that includes the current oxygen saturation level. Again, the OxygenMeter dependency is injected. The one reason for the class to change is if the alerting system is updated.
  2. The two parts of the principle appear to be contradictory. However, if you correctly structure your classes and their dependencies you can add functionality without editing existing source code. Generally you achieve this by referring to abstractions for dependencies, such asinterfaces or abstract classes, rather than using concrete classes. Such interfaces can be fixed once developed so the classes that depend upon them can rely upon unchanging abstractions. Functionality can be added by creating new classes that implement the interfaces. Applying the OCP to your projects limits the need to change source code once it has been written, tested and debugged. This reduces the risk of introducing new bugs to existing code, leading to more robust software. Another side effect of the use of interfaces for dependencies is reduced coupling and increased flexibility.
  3. The LSP applies to inheritance hierarchies. It specifies that you should design your classes so that client dependencies can be substituted with subclasses without the client knowing about the change. All subclasses must, therefore, operate the same manner as their base classes. The specific functionality of the subclass may be different but must conform to the expected behaviour of the base class. To be a true behavioural subtype, the subclass must not only implement the base class's methods and properties but also conform to its implied behaviour. This requires compliance with several rules. The first rule is that there should be contravariance between parameters of the base class's methods and the matching parameters in subclasses. This means that the parameters in subclasses must either be the same types as those in the base class or must be less restrictive. Similarly, there must be covariance between method return values in the base class and its subclasses. This specifies that the subclass' return types must be the same as, or more restrictive than, the base class' return types. The next rule concerns preconditions and postconditions. A precondition of a class is a rule that must be in place before an action can be taken. For example, before calling a method that reads from a database you may need to satisfy the precondition that the database connection is open. Postconditions describe the state of objects after a process is completed. For example, it may be assumed that the database connection is closed after executing a SQL statement. The LSP states that the preconditions of a base class must not be strengthened by a subclass and that postconditions cannot be weakened in subclasses. Next the LSP considers invariants. An invariant describes a condition of a process that is true before the process begins and remains true afterwards. For example, a class may include a method that reads text from a file. If the method handles the opening and closing of the file, an invariant may be that the file is not open before the call or afterwards. To comply with the LSP, the invariants of a base class must not be changed by a subclass. The next rule is the history constraint. By their nature, subclasses include all of the methods and properties of their superclasses. They may also add further members. The history constraint says that new or modified members should not modify the state of an object in a manner that would not be permitted by the base class. For example, if the base class represents an object with a fixed size, the subclass should not permit this size to be modified. The final LSP rule specifies that a subclass should not throw exceptions that are not thrown by the base class unless they are subtypes of exceptions that may be thrown by the base class. The above rules cannot be controlled by the compiler or limited by object-oriented programming languages. Instead, you must carefully consider the design of class hierarchies and of types that may be subclassed in the future. Failing to do so risks the creation of subclasses that break rules and create bugs in types that are dependent upon them. One common indication of non-compliance with the LSP is when a client class checks the type of its dependencies. This may be by reading a property of an object that artificially describes its type or by using reflection to obtain the type. Often a switch statement will be used to perform a different action according to the type of the dependency. This additional complexity also violates the Open / Closed Principle (OCP), as the client class will need to be modified as further subclasses are introduced.
  4. The problem with such a design is that the high level TransferManager class is directly dependent upon the lower level BankAccount class. The Source and Destination properties reference the BankAccount type. This makes it impossible to substitute other account types unless they are subclasses of BankAccount. If we later want to add the ability to transfer money from a bank account to pay bills, the BillAccount class would have to inherit from BankAccount. As bills would not support the removal of funds, this is likely to break the rules of the Liskov Substitution Principle (LSP) or require changes to the TransferManager class that do not comply with the Open / Closed Principle (OCP). Further problems arise should changes be required to low level modules. A change in the BankAccount class may break the TransferManager. In more complex scenarios, changes to low level classes can cause problems that cascade upwards through the hierarchy of modules. As the software grows, this structural problem can be compounded and the software can become fragile or rigid. Applying the DIP resolves these problems by removing direct dependencies between classes. Instead, higher level classes refer to their dependencies using abstractions, such as interfacesor abstract classes. The lower level classes implement the interfaces, or inherit from the abstract classes. This allows new dependencies to be substituted without impact. Furthermore, changes to lower levels should not cascade upwards as long as they do not involve changing the abstraction. The effect of the DIP is that classes are loosely coupled. This increases the robustness of the software and improves flexibility. The separation of high level classes from their dependencies raises the possibility of reuse of these larger areas of functionality. Without the DIP, only the lowest level classes may be easily reusable.
  5. Refactored Code To refactor the code to comply with the DIP we must remove the direct dependency that the TransferManager has on the BankAccount class. We could introduce a new interface for accounts that contains the methods we require to add and remove funds. However, in this case I have introduced two new interfaces. ITransferSourceincludes a method that allows funds to be removed from an account. ITransferDestinationincludes the method for adding funds to an account. The separation of the two interfaces complies with the Interface Segregation Principle (ISP) and allows for the inclusion of accounts that accept payments but cannot be the source of funds. The BankAccount class is modified so that it implements the new interfaces. TransferManager is modified so that the Source property expects an ITransferSource object and the destination is an ITransferDestination. No direct dependencies on concrete classes now exist. Instead, both the high level class and the low level class depend upon the two abstractions.