If you’re familiar with object-oriented programming, you’ve probably heard of SOLID principles.

These five software development principles are guidelines to follow when developing software to facilitate scaling and maintenance. They were popularized by software developer Robert C. Martin.

There are so many great articles about SOLID online, but I rarely see examples with pictures. This makes it a bit difficult for visual learners like me to learn and stay engaged.

The main purpose of this article is to better understand these rules by using illustrations and emphasizing the purpose of each principle.

You see, some of these principles may look similar, but they don’t serve the same purpose. You can satisfy one rule/principle while breaking another, even if they look similar.

To make it as easy as possible to understand, I use the word “class”. Note, however, that in this article it can also refer to a function, method, or module.

The SOLID Principles

S — Single Responsibility

A class should have a single responsibility

When a class has multiple responsibilities, the risk of error increases because changes to one of its responsibilities can affect the others without your knowledge.

Goal

This principle is intended to separate behaviors so that failures that occur as a result of any change do not affect other, unrelated behaviors.

O — Open-Closed

Classes should be open for extension, but closed for modification

Changing the current behavior of a class affects all systems that use that class. If you want a class to perform multiple functions, the ideal approach is to add functions that already exist and NOT to modify them.

Goal

This principle is intended to extend the behavior of a class without changing the existing behavior of that class. This helps avoid errors no matter where the class is used.

— Liskov Substitution

If S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program.

When a child class cannot perform the same tasks as its parent class, it can lead to bugs.

If you have a class and create another one, that class becomes the parent and the new class becomes the child. The child class should be able to do anything that the parent class can do. This process is called inheritance.

The subclass must be able to process the same requests and provide the same result as the superclass, or it can provide the same type of result.

If the subclass does not meet these requirements, the subclass has been completely modified and is in violation of this rule.

Goal

The purpose of this rule is to enforce consistency so that the superclass or its subclass can be used in the same way without error.

— Interface Segregation

Clients should not be forced to depend on methods that they do not use.

Having a class do things that aren’t useful is wasteful and can lead to unexpected bugs if the class doesn’t have the ability to do those things.

The class should only do what is necessary to fulfill its role. All other actions should either be removed entirely or moved elsewhere if they can be used by another class in the future.

Goal

This principle is intended to break down a set of actions into smaller sets so that a class ONLY performs the set of actions it needs.

— Dependency Inversion

Abstractions should not depend on details. Details should depend on abstractions.

First, let’s simply define the terms used here.

Top-level module (or class): a class that performs an action with a tool.

Low-level module (or class): a tool needed to perform an action.

Abstraction represents an interface connecting two classes.

Details: How the tool works

This principle states that a class should not be associated with the tool it uses to perform an action. Rather, it should be associated with an interface that allows the tool to connect to the class.

It also indicates that the class and interface should not know how the tool works. However, the tool must meet the interface specification.

Goal

This principle aims to reduce the dependency of the top-level class on the low-level class by introducing an interface.

Summary of SOLID principles

So far we have covered these five principles and highlighted their purposes. They are designed to help you customize, extend, and test your code easily and without much effort.

Categorized in: