What are the SOLID principles?

The SOLID principles consist of five guidelines for clean, maintainable and flexible code in object-based programming. Applying and adhering to the principles results in easy-to-understand software design over long development periods. With these principles, not only can better code be written, but existing code can also be maintained more easily.

What are the SOLID principles and who developed them?

Good source code starts with rules, programming paradigms and a suitable programming style for efficient and clean code. This is exactly what the five SOLID principles, coined by Robert C. Martin, Bertrand Meyer and Barbara Liskov, ensure. By following these principles in object-oriented programming (OOP) with languages such as Python or Java, you not only write better code, but you also ensure more efficient code maintenance, sustainable and flexible software design and greater security in the long term.

The name SOLID is representative of the solid programming foundation that anyone who wants to learn programming should have. The acronym itself was created by Michael Feathers, who took the first letters of each of the five principles to create it:

  • Single Responsibility Principle: A class should have one, and only one, reason to change.
  • Open-Closed Principle: Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
  • Liskov Substitution Principle: Subclasses should be able to inherit and implement all methods and properties of the superclass.
  • Interface Segregation Principle: Interfaces should not contain more methods than are required for implementing classes.
  • Dependency Inversion Principle: Classes should not depend on other classes, but on interfaces or abstract classes.

What benefits do the SOLID principles offer?

Where there are no rules, chaos ensues, and this becomes particularly noticeable when programming. Even small errors, inaccuracies and gaps can make good source code completely unusable in the long term if left ‘untreated’. Sometimes all it takes is complex classes that make implementation difficult or subclasses that lack individual properties of their superclasses. The SOLID principles ensure that as little code as possible needs to be repaired with refactoring.

SOLID principles make code:

  • Clear, clean and attractive: Software and codes are easier to understand, more effective and simply look better.
  • Easy to maintain: The straightforward and clear structure makes it simpler for multiple collaborators to maintain and manage both new code and legacy code.
  • Customisable, expandable, reusable: Through improved readability, reduced complexities and responsibilities, and decreased dependencies on classes, code can be better edited, adapted and expanded through interfaces, and flexibly reused.
  • Less error-prone: Clean code with a simple structure means that changes to one part of the code do not accidentally affect other areas or functions.
  • Secure and more reliable: Reducing or eliminating vulnerabilities, incompatibilities and errors enhances a systems’ functionality and dependability, which in turn improves security.

What do each of the SOLID principles mean?

The SOLID principles belong to the golden rules for good programming and should be familiar to anyone that works in object-based programming. Below we’ll explain each principle in detail.

SRP: Single Responsibility Principle

Robert C. Martin created the original definition for this principle in ‘Agile Software Development: Principles, Patterns and Practices’; writing:

Quote

“Each software module should have one and only one reason to change”.

The Single Responsibility Principle (SRP) states that each class in object-oriented programming (OOP) should have only one responsibility. This implies there should only be one reason to modify a class. Contrary to common interpretations, this does not mean that a class or module can only have exactly one task. Rather, it means that it should only be responsible for specific tasks that ideally do not overlap with other areas.

An overlap of responsibilities, such as offering functions for various business segments, might impact the class’s functionality when modifications are made in one segment. Holding multiple responsibilities and numerous dependencies may cause a single change in one area to bring about code errors or the need for additional changes.

The Single Responsibility Principle (SRP) is designed to create cohesive modules tasked with specific, well-defined functions or objects. Thanks to its clear, structured setup with minimal dependencies and independent implementations, modifications and adjustments can be made more efficiently, swiftly and smoothly.

Note

Classes, also known as object types, are the central elements in object-oriented programming (OOP). They can be seen as blueprints for objects, outlining their attributes so that it’s possible to recreate real-world objects and concepts in software. Classes, also known as modules, are often compared to file types.

OCP: Open Closed Principle

According to Robert C. Martin and Bertrand Meyer in ‘Object Oriented Software Construction’, the OCP states:

Quote

“Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification”.

The OCP ensures that you do not have to rewrite software at its core in order to implement changes. If in-depth code modulations are required, there is a risk of subtle errors and code smells. A well-structured code should provide interfaces that can be used to extend it with additional functions. The keyword here is class inheritance.

New features and extensions with clear new functions and methods that need to be implemented can be easily added to a superclass via an interface in the form of subclasses. This way, you don’t have to tamper with the written, stable code. It simplifies the maintenance and upkeep of software and significantly improves the efficiency of reusing stable code elements via interfaces.

LSP: Liskov’s Substitution Principle

According to Barbara H. Liskov and Jeannette M. Wing in ‘Behavioral Subtyping Using Invariants and Constraints’, the LSP states that:

Quote

“Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T”.

It may sound cryptic, but it’s actually quite easy to understand: Linked or extended subclasses must function like their superclasses or base classes. This means that each subclass must retain the properties of its respective superclass through inheritance and these properties must not be changed in the subclass. They must be replaceable in principle, hence the substitution principle. Superclasses, on the other hand, may be modified.

To explain, let’s look at the classic example from Robert C. Martin about rectangles and squares. In geometry lessons, we learn the following principle: every square is a rectangle, but not every rectangle is a square. A square not only has right-angled sides like rectangles do, but all its sides are also equal in length.

In programming, assuming that similar or seemingly identical classes are related or dependent on each other leads to errors, misunderstandings and unclear code. For this reason, in programming, the class ‘Rectangle’ is not a square, and the class ‘Square’ is not a rectangle. Both are decoupled and implemented separately. Without an integrated connection between the classes, misunderstandings cannot lead to errors across classes. This enhances the security and stability when swapping implementations in subclasses or superclasses, without repercussions.

ISP: Interface Segregation Principle

According to Robert C. Martin in ‘The Interface Segregation Principle’, the ISP is defined as follows:

Quote

“Clients should not be forced to depend upon interfaces that they do not use”.

The ISP states that users should not have to use interfaces that they do not need. In other words: In order to provide clients with the functions of certain classes, new, smaller interfaces are tailored to specific requirements. This prevents interfaces from becoming too large and ensures that strong dependencies don’t form between classes. The advantage is that software with decoupled classes and several small interfaces tailored to specific requirements is easier to maintain.

DIP: Dependency Inversion Principle

According to Robert C. Martin in ‘The Dependency Inversion Principle’, the fifth and last of the SOLID principles, is as follows:

Quote

“A. High-level modules should not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend upon details”.

The DIP ensures that specific functionalities and dependencies within source code layers rely on abstract interfaces, not directly on each other. Software architectures are typically organised into higher user levels and lower, more abstract levels. Logically, one might think that the abstract foundation influences the behaviour of the upper layers. However, the DIP identifies a potential issue here, as it creates dependencies for the higher levels on the lower levels, which can lead to problems.

Instead of linking higher levels to lower levels, classes in high and low levels should depend on abstract, intermediate interfaces. The interfaces retrieve functionalities that are required at higher levels from lower levels and make them available. In this way, a bottom-up hierarchy of dependencies can be avoided, which can lead to errors in the code over time. This facilitates the reusability of modules and enables changes to lower classes without affecting higher levels.

Web Hosting
Secure, reliable hosting for your website
  • 99.9% uptime and super-fast loading
  • Advanced security features
  • Domain and email included

What happens if the SOLID principles aren’t adhered to?

Creating clean, readable code that simplifies maintenance should be a primary aim in software development. If developers overlook essential guidelines like the SOLID principles, the code can degrade severely due to vulnerabilities, redundancies, accumulated errors and excessive dependencies. In extreme cases, the code might become unusable as time passes. This is a significant issue in agile software development, where many people often work on complex coding tasks.

The consequences of unclean code or poor code maintenance include:

  • Code smell: When code isn’t written in accordance with the necessary standards, this can cause code smell or ‘smelly code’, leading to functional errors and incompatible programs.
  • Code rot: If it is not maintained or repaired by refactoring or a costly code review, code can figuratively ‘rot’ and completely lose its functionality. Another term for unreadable, convoluted code is spaghetti code.
  • Security risks: The issues that arise aren’t limited to outages, complex upkeep and compatibility problems. There are also security gaps that provide malware with opportunities to exploit the code, including zero-day exploits.

Who developed the SOLID principles?

The origin of the SOLID principles lies in several principles first introduced by Robert C. Martin (‘Uncle Bob’), one of the initiators of agile programming, in the year 2000 in his essay titled ‘Design Principles and Design Patterns’. The SOLID principles were coined by Robert C. Martin, Bertrand Meyer and Barbara Liskov. The catchy acronym was popularised by Michael Feathers, who rearranged the initial letters of the five essential principles into a memorable order.

What similar programming principles are there?

In software development, principles are general or very specific guidelines and recommendations for action. In addition to the SOLID principles, which were developed for object-oriented programming, other programming principles for clean code include:

  • DRY principle (Don’t repeat yourself) for functions with a single, unique representation
  • KISS principle (Keep it simple, stupid) for code constructed as simply as possible
Was this article helpful?
Page top