SOLID Introduction
1. SOLID principles are the design principles that enable us to manage most of the software
design problems
2. The term SOLID is an acronym for five design principles intended to make software
designs more understandable, flexible, and maintainable
3. The principles are a subset of many principles promoted by Robert C. Martin
4. Michael Feathers first introduced the SOLID acronym
Advantages of following these Principles
Help us to write better code:
1. Avoid Duplicate Code
2. Easy to maintain
3. Easy to Understand
4. Flexible software
5. Reduce Complexity
SOLID Acronym
S: Single Responsibility Principle (SRP)
O: Open closed Principle (OSP)
L: Liskov substitution Principle (LSP)
I: Interface Segregation Principle (ISP)
D: Dependency Inversion Principle (DIP)
Single Responsibility Principle
1. “A class should have only one reason to change”.
2.Every module or class should have responsibility over a single part of the functionality
provided by the software, and that responsibility should be entirely encapsulated by the
class.
Eg. Marker Entity:
Class Marker{
String name;
String color;
int year;
int price;
public Marker(String name,String color,int year,int price){
this.name = name;
this.color = color;
this.year = year;
this.price = price;
Class Invoice {
private Marker marker;
private int quantity;
public Invoice(Marker marker, int quantity){
this.marker = marker;
this.quantity = quantity;
public int calculateTotal(){
int price = ((marker.price) * this.quantity);
return price;
Class InvoicePrinter {
private Invoice invoice;
public InvoicePrinter(Invoice invoice){
this.invoice = invoice;
public int print(){
//print the invoice
Class InvoiceDao {
Invoice invoice;
public InvoiceDao (Invoice invoice){
this.invoice = invoice;
public int calculateTotal(){
//Save into the DB
}
Open/Closed Principle
1. “Software entities should be open for extension, but closed for modification”
2. The design and writing of the code should be done in a way that new functionality should
be added with minimum changes in the existing code
3. The design should be done in a way to allow the adding of new functionality as new
classes, keeping as much as possible existing code unchanged
Eg.
Interface InvoiceDao{
Public void save(Invoice invoice);
Class databaseInvoiceDao implements InvoiceDao{
@override
Public void save(Invoice invoice){
//save to DB
Class FileInvoiceDao implements InvoiceDao{
@override
Public void save(Invoice invoice){
//save to file
}
Liskov Substitution Principle
1. Introduced by Barbara Liskov states that “objects in a program should be replaceable with
instances of their sub-types without altering the correctness of that program”
2. 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
3. We can also state that Derived types must be substitutable for their base types
4. Subclass should extent the capability of the parent class not narrow it down
Eg.
Interface InvoiceDao{
void turnOnEngine();
void accelerate();
Class MotorCycle implements Bike{
boolean isEngineOn;
int speed;
Public void turnOnEngine (){
//turn on the engine!
isEngineOn = true;
Public void accelerate(){
//increase the speed
speed = speed + 10;
//this is violates liskov priciple
Class Bicycle implements Bike{
public void turnOnEngine (){
throw new AssertionError(“there is no engine”)
public void accelerate(){
//increase the speed
speed = speed + 10;
Interface Segregation Principle
1. “Many client-specific interfaces are better than one general-purpose interface”
2. Interfaces should be such, that client should implement unnecessary functions they do
not need.
3. We should not enforce clients to implement interfaces that they don't use. Instead of
creating one big interface we can break down it to smaller interfaces
Eg.
Interface WaiterInterface{ Interface ChefInterface {
void serveCustomers(); void cookFood();
void takeOrder(); void decideMenu();
} }
Class waiter implements waiterInterface{
public void serveCustomers (){
System.out.println(“serving the customer”)
public void accelerate(){
System.out.println(“taking orders”)
}
Dependency Inversion Principle
1. One should “depend upon abstractions, [not] concretions"
2. Class should depend on interfaces rather than concrete classes.
3. Abstractions should not depend on the details whereas the details should depend on
abstractions
4. High-level modules should not depend on low level modules
Eg.
Class macbook{
private final Keyboard keyboard;
private final Mouse mouse;
public macbook(Keyboard keyboard, Mouse mouse){
this.keyboard = keyboard;
this.mouse = mouse;
If we don’t follow SOLID Principles we
1. End up with tight or strong coupling of the code with many other modules/applications
2. Tight coupling causes time to implement any new requirement, features or any bug fixes
and some times it creates unknown issues
3. End up with a code which is not testable
4. End up with duplication of code
5. End up creating new bugs by fixing another bug
6. End up with many unknown issues in the application development cycle
Following SOLID Principles helps us to
1. Achieve reduction in complexity of code
2. Increase readability, extensibility and maintenance
3. Reduce error and implement Reusability
4. Achieve Better testability
5. Reduce tight coupling
A solution to develop a successful application depends on
Architecture: choosing an architecture is the first step in designing an application based on
the requirements. Example: MVC, WEB API, MVVM..etc
Design Principles: The application development process needs to follow the design
principles
Design Patterns: We need to choose the correct design patterns to build the software