SOLID Design Principles

Challenge Inside! : Find out where you stand! Try quiz, solve problems & win rewards!

Learn via video courses

Overview

The SOLID design principles were introduced by Robert C. Martin, also known as "Uncle Bob", in his paper "Design Principles and Design Patterns" in 2000. But the acronym was coined later by Michael Feathers.

The SOLID Principles are a set of Object-Oriented design principles that have revolutionized how we write software. They are a collection of guidelines and best practices for writing clean, flexible, reusable, scalable, and maintainable code.

breif-intro-of-solid-principle

Scope of Article

The five SOLID design principles assist us in comprehending the importance of specific design patterns and overall software architecture. This article will educate you on how to apply SOLID principles to software projects. We will delve into the nitty-gritty details - the whys and hows of each principle.

The article covers the following :

  • We list the SOLID Design Principles in software engineering.
  • We discuss all five principles in detail.

SOLID Design Principles in Software Engineering

The term SOLID in SOLID design principles is an acronym for five principles, they are :

  • S : Single-responsibility Principle
  • O : Open-closed Principle
  • L : Liskov Substitution Principle
  • I : Interface Segregation Principle
  • D : Dependency Inversion Principle

These SOLID design principles designate practices for designing software while keeping maintenance and extension in mind as the project expands. Embracing these techniques can help you avoid code smells, refactoring, and produce Agile software. Let us look at each of these principles in detail.

Single Responsibility Principle (SRP)

Simply put, the single responsibility, in SOLID design principles, states that a class, module, or function should have only one job. The most common definition says every class should have only one reason to change. If a class contains the logic of performing more than one job, it won't be easy to debug and maintain as the codebase increases in size. New developers will have a tough time trying to read and understand the code. If we separate the logic and make each class performs one single job, not only will the code be easy to maintain and debug, but the code will also become reusable because each core functionality is performed by one class. The code is also easily maintainable and scalable because rather than reading interconnected lines of code, we have separated the functionalities to focus on the features we want to work on.

Open/Closed Principle

The open-closed principle of the SOLID design principles states that software entities should be open for extension but closed for modification. It means that these entities should be implemented in such a way that their functionalities can be extended to other entities without modifying the code of the original entity.

Let us understand this principle with an example. Suppose we have implemented an 'Oven' class.

We launch this app, but after some time, we want to add a grilling feature to this oven. We can edit this oven class, but it may mass up the entire codebase. So, the open-closed principle is against this. Instead, we should extend this class :

In this way, we kept the existing code closed for modification but open for extension.

Liskov's Substitution Principle (LSP)

According to Barbara Liskov and Jeannette Wing, the Liskov substitution principle states that :

Let Φ(x)Φ(x) be a property provable about objects x of type T. Then Φ(y)Φ(y) should be true for objects y of type S, where S is a subtype of T.

Simply put, it extends the Open/Closed principle by allowing you to replace parent class objects with subclass objects without destroying the application. This necessitates that all subclasses behave similarly to the parent class.

To accomplish this, the subclasses must follow the following rules :

The validation requirements for input parameters of the child class should not be tighter than those of the parent class.

The same rules apply to all output parameters that the parent class does.

Interface Segregation Principle (ISP)

The I in SOLID design principles stands for interface segregation, which indicates that bigger interfaces should be divided into smaller ones. By doing so, we can ensure that implementing classes is only concerned with the methods that are relevant to them. In other words, multiple client-specific interfaces are better than a single generic interface.

Clients must never be forced to implement an interface they do not use, nor should they be forced to rely on methods they do not use. For example, implementing a volume interface does not make sense for the Square or Circle classes, which are two-dimensional shapes.

Dependency Inversion Principle (DIP)

Suppose a high-level module or class significantly depends on low-level modules or classes. In that case, the code will have tight coupling, and changing one class can break another, which is problematic at the production level. So, always strive to make classes as loosely connected as possible, which you can do through abstraction. The D in SOLID design principles stands for the Dependency inversion principle. The fundamental goal of this approach is to decouple dependencies so that if class A changes, class B does not need to care or be aware of the changes. So, to summarize, high-level modules should not depend on low-level modules, both should depend on abstractions, and abstractions should not depend on details.

Conclusion

  • SOLID is an acronym that stands for five fundamental design principles : single responsibility principle, open-closed principle, Liskov substitution principle, interface segregation principle, and dependency inversion principle.
  • The SOLID design principles' essential purpose is to eliminate dependencies so that software engineers can alter one section of software without affecting others. They're also meant to make designs easier to understand, maintain, and extend. Finally, applying these design principles helps software engineers avoid problems and create flexible, maintainable, and agile software.
  • The "single responsibility principle" states that each class should perform only one function.
  • The "open to extension, close to modification" principle states that new features should be added without affecting the existing code.
  • The "Liskov's substitution principle" requires that every subclass or derived class be substitutable for their base or parent class.
  • The "Interface segregation principle" states that a program's interface should be split so that the client would only have access to the necessary methods related to their needs.
  • The "Dependency inversion principle" states that entities must depend on abstractions, not on concretions or details.