SOLID principles is an acronym of the five software developing principles where complying with the SOLID principles becomes a good technical guidance and practice for good OOP (Object Oriented Programming) designs.
π‘
Cohesionrefers to degree ofmodularityacrossinterrelated components.
π‘
Couplingrefers to the degree ofinterdependenceacross logically varyingsoftware components.
SOLID principles can be viewed as the clarifications and perhaps redefinition of the best common practices across the developers where the concepts like high-cohesion and low-coupling still well persist in the SOLID principles.
Five principles in the SOLID are namely:
ingle Responsibility Principle (SRP)pen and Close Principle (OCP)iskov Substitution Principle (LSP)nterface Segregation Principle (ISP)ependency Inversion Principle (DIP)where they will be discussed in the following sections.
Single Responsibility Principle (SRP) suggests that:
π³ A
classhas only one reason to change
which essentially translates to
π³ A
classshould have asingle responsibility.
SRP can be better explained by the below codes.
Dog Class
class Dog {
private String sex;
void bark() {
if (sex.equals("male")) {
System.out.println("Baaaark brk!!!")
} else if (sex.equals("female")) {
System.out.println("Bark Bark!!!")
}
}
}
Dog Class as can be seen has two logical branches, whether an instance's sex property is male or female. This violates the SRP as the Dog class has two reasons to change either for the male or female-related logic. Hence, a better class design could be the one below, where the abstract Dog class is extended to Male & Female Dog classes. Hence, there are two separate classes responsible for a single logical branch.
Dog Classes (SRP)
abstract class Dog {
abstract void bark() {}
}
class MaleDog extends Dog {
void bark() {
System.out.println("Baaaark brk!!!")
}
}
class FemaleDog extends Dog {
void bark() {
System.out.println("Bark Bark!!!")
}
}
SRP if appropriately applied can initially result in:
maintainabilitytestabilityexcessive implementation of SRP can, however, result in:
complexity (followed by too many defined classes)Open and Close Principle (OCP) suggests that
πͺ A
classshould beopen for extensionsbutclosed for modification.
This implies that new features should be introduced in the form of class extensions and interface implementation rather than directly changing the existing code as the latter enhances the risk of creating potential bugs.
A good example could be below:
Driver & SpecificCarClass
class Driver {
private SpecificCarClass specificCarClass = new SpecificCarClass();
}
class SpecificCarClass {
private int wheels;
private int windows;
private int seats;
}
Driver class from the above code has a field with a concrete class, and the violation of OCP is highly likely under the circumstances of concrete car class field changing.
Driver & Car & SpecificCarClass
class Driver {
private Car car;
}
class abstract Car {
private int wheels;
private int windows;
private int seats;
}
class SpecificCarClass extends car {
}
Hence, to maintain OCP, the principles from the DIP (polymorephism) could be directly implemented, where specifically the parent class or a parent interface could be implemented instead of the concrete class type.
The above code well illustrates how OCP via DIP could be maintained. Another good example in the real world could be JDBC API where in the JDBC, the interfaces are only stated, and the actual implementation or the future modification can be altered by simply implementing the interfaces from the JDBC APIs.

Geeks for Geeks Available at here
Compliance with OCP increases the codes'
maintainabilityreusability the above merits, however, come with the cost of:
complexity (followed by too many defined classes)Liskov Substitution Principle (LSP) simply suggests that
π A
child class'A' should be able to substitute itsparent class'B' without causing any breakdowns.
Abstraction from the OOP is a concept that is most closely related to the LSP as LSP redefines how abstraction via class extensions and interface implementation should be managed.
Specifically, LSP focuses on child classes to explicitly follow the behaviour conduct from their parent classes, where failing to comply with the behavioural conduct essentially implies that the abstraction has been poorly implemented leading to code that becomes tightly coupled, unpredictable, and harder to maintain or extend.
LSP could be further simplied to complying with the below sentences.
child class is a kind of parent classimplmenting class is able to interfaceLSP can be well represented underneath, in which the below child class, Penguin violates the behavioural conduct of its parent class, Bird assuming that the fly() method is implicitly not possible in the scope of the Penguin class.
Bird & Penguin & Sparow classes
abstract class Bird {
abstract void fly();
}
class extends Penguin extends Bird {
public void fly() {
System.out.println("FLY????");
}
}
class extends Sparow extends Bird {
public void fly() {
System.out.println("Yeh I can fly");
}
}
To maintain LSP, the overall class design could change, where specifically, the Sparrow class could implement the Flyable interface that requires the implementation of the fly() method.
Bird & Penguin & Sparow classes & Flyable interface
abstract class Bird {
abstract void eat();
}
class extends Penguin extends Bird {
@Override
public void eat() {
System.out.println("yum yum");
}
}
interface Flyable {
void fly();
}
class extends Sparow extends Bird implements Flyable {
@Override
public void eat() {
System.out.println("yum yum");
}
@Override
public void fly() {
System.out.println("Yeh I can fly");
}
}
Compliance with LSP increases codes':
stabilityflexibilitythe above merits, however, come with the cost of:
complexity (followed by too many defined classes)Interface Segregation Principle (ISP) suggests that
π¨οΈ A
clientshould not be dependent onmethodsthat are not used by the client.
methods that are hardly used strictly refers to the methods with varying interests strictly relevant to SRP.
ISP could be an alternative approach to maintaining SRP than by class extensions, where given with the methods with varying interests, these methods can be individually required to be implemented via interfaces.
Underneath Man class could be a good example, where the class excessive responsibilities harming its code maintainance.
Man Class
class Man {
public void doBetterToParents() {
}
public void helpParents() {
}
public void kiss() {
}
public void date() {
}
public void work() {
}
public void goWork() {
}
}
Under ISP, the above Man class can be further splitted into multiple interfaces with varying interests:
Interfaces
public interface Son {
public void doBetterToParents() {
}
public void helpParents() {
}
}
public interface Boyfriend {
public void kiss() {
}
public void date() {
}
}
public interface Worker {
public void work() {
}
public void goWork() {
}
}
and depending on the interests, vayring interfaces can be implemented.
Man, Boy & GrownUpMap class
abstract class Man {
}
class Boy extends Man implements Son {
@Override
public void doBetterToParents() {
}
@Override
public void helpParents() {
}
}
class GrownupMan extends Man implements Son, Worker {
@Override
public void doBetterToParents() {
}
@Override
public void helpParents() {
}
@Override
public void work() {
}
@Override
public void goWork() {
}
}
Compliance with ISP maintains SRP and hence increases:
maintainabilitytestabilitythe above merits, however, come with the expanse of:
complexity (followed by too many defined interfaces)Dependency Inversion Principle (DI) suggests that
π
High-level modulesshould not depend onlow-level modules, both should depend onabstractions.
this can be further elaborated in the following statement
A
classshould implementabstractionsrepresented asinterfacesandabstract classesoverconcrete classes
Exactly the same example codes from the OCP could be used to explain DI at the code level.
DI becomes the essence of Spring where the internal mechanisms of Spring Beans in the Spring Container extensively apply and implement DI.
DIP allows:
class decouplingflexibility maintainability the above merits, however, come with the expanse of:
understandability (followed by abstraction)μ€νλ§ μ
λ¬Έμ μν μλ° κ°μ²΄μ§ν₯μ μ리μ μ΄ν΄
Geeks for Geeks
Free Code Camp