SOLID Principles

5 principles that every programmer should know

SOLID is a popular set of design principles used in object-oriented software development. SOLID is an acronym that stands for five key design principles: Single responsibility principle, Open-closed principle, Liskov substitution principle, Interface segregation principle and Dependency inversion principle. All five are commonly used by software engineers and provide some important benefits for developers.

SOLID principles were developed by Robert C. Martin in an essay published in 2000, "Design Principles and Design Patterns"although the acronym was later coined by Michael Feathers. In his essay, Martin recognized that successful software will change and evolve. As it changes, it becomes increasingly complex. Without good design principles, Martin warns that software becomes rigid, brittle, immobile and viscous. SOLID principles were developed to combat these problematic design patterns.

The overall goal of SOLID principles is to reduce dependencies so that engineers can change one area of the software without affecting others. In addition, they are intended to make designs easier to understand, maintain and extend. Ultimately, the use of these design principles makes it easier for software engineers to avoid problems and create software that is adaptable, efficient and agile.

While principles have many benefits, following principles generally leads to writing longer and more complex code. This means that it can extend the design process and make development a bit more difficult. However, this extra time and effort is worth it because it makes the software much easier to maintain, test and extend.

5 Principles every programmer should know

Following these principles is not a panacea and will not prevent design problems. That said, the principles have become popular because when followed correctly, they lead to better code in terms of readability, maintainability, design patterns and testability.

1. Single Responsibility Principle

This principle requires that "a class must have one, and only one, reason to change". Following this principle means that each class only does one thing and each class or module is only responsible for one part of the software functionality. More simply, each class must solve only one problem.

The single responsibility principle is a relatively basic principle that most developers already use to create code. It can be applied to classes, software components and microservices.

Using this principle makes the code easier to test and maintain, makes the software easier to implement, and helps avoid unforeseen side effects of future changes.

2. Open-Closed Principle

The idea of the open-closed principle is that existing, well-tested classes should be modified when something needs to be added. However, changing classes can lead to problems or bugs. Instead of changing the class, you simply want to extend it. With that goal in mind, Martin summarizes this principle: \"You should be able to extend the behavior of a class without modifying it."

Following this principle is essential for writing code that is easy to maintain and review. Your class complies with this principle if it is:

  • Open for extension, meaning that the behavior of the class can be extended; and
  • Closed by modification, which means that the source code is configured and cannot be changed.

At first glance, these two criteria seem to be contradictory. The way to comply with these principles and ensure that your class is easily extensible without having to modify the code is by using abstractions. Using inheritance or interfaces that allow polymorphic substitutions is a common way to comply with this principle. Regardless of the method used, it is important to follow this principle to write code that can be maintained and reviewed.

3. Liskov Substitution Principle, Liskov's Substitution Principle

Of the five SOLID principles, Liskov's substitution principle is perhaps the most difficult to understand. In general terms, this principle simply requires that each derived class be substitutable for its parent class. The principle is named after Barbara Liskov, who introduced this concept of behavioral subtyping in 1987. Liskov herself explains the principle by saying:

"What is sought here is something like the following substitution property: if for every object O1 of type S there is an object O2 of type T such that for all programs P defined in terms of T, the behavior of P does not change when O1 is substituted for O2 then S is a subtype of T."

In a clearer way, we can say that:

"The principle defines that objects of a superclass shall be replaceable with objects of its subclasses without interrupting the application. That requires that the objects of the subclasses behave in the same way as the objects of the superclass."

While this can be a difficult principle to internalize, in many ways it is simply an extension of the open-closed principle, as it is a way to ensure that derived classes extend the base class without changing behavior.

4. Interface Segregation Principle, Interface Segregation Principle

The general idea of the principle of interface segregation is that it is better to have many smaller interfaces than a few larger ones. Martin explains this principle by advising:

"Make detailed interfaces that are customer-specific. Don't force customers to implement interfaces they don't use."

For software engineers, this means that you don't want to simply start with an existing interface and add new methods. Instead, start by creating a new interface and then let your class implement multiple interfaces as needed. Smaller interfaces mean that developers should have a preference for composition over inheritance and decoupling over coupling. According to this principle, engineers should work toward having many customer-specific interfaces, avoiding the temptation to have one large general-purpose interface.

5. Dependency Inversion Principle, Principle of Dependency Inversion

This principle provides a way to decouple software modules. Simply put, the principle of dependency inversion means that developers should "depend on abstractions, not concretions. With this principle, "high-level modules should not depend on low-level modules. Both should depend on abstractions". Furthermore, "abstractions should not depend on details. Details should depend on abstractions".

One popular way to comply with this principle is by using a dependency inversion pattern, although this method is not the only way to do it. Regardless of which method you choose to use, finding a way to use this principle will make your code more flexible, agile, and reusable.

Conclusion

Implementing SOLID design principles during development will lead to systems that are easier to maintain, scalable, testable and reusable. In today's environment, these principles are used globally by engineers. As a result, to create good code and use design principles that are competitive and meet industry standards, it is essential to use these principles.

Examples

In this article you can find some examples for each of the SOLID principles, they are in JAVA, but can be applied to any programming language that allows the development of applications with OOP: https://www.baeldung.com/solid-principles

\"\"

DARIO

Senior Software Engineer

Scroll to Top