S.O.L.I.D PRINCIBLES
By: Evren Vural
Tags: Programming, Solid Ob, Object Oriented, Swift

S.O.L.I.D principles which have been introduced to us by Robert Martin (Uncle Bob) and which provide a basis for the Object-Oriented Programming are the software design principles.

The aim of these principles are to make the codes more readable and open to development. They consist of 5 principles:

Single-Responsibility Principle

Open-Closed Principle

Liskov Substitution Principle

Interface Segregation Principle

Dependency Inversion Principle

1.Single-Responsibility Principle

Each entity such as class, module or function must have only one mission. They should not be given more than one responsibility.

For example:

Let’s address a Player class of a game. While moving and shooting are functions of a character, saving to database is a whole different responsibility. Therefore, this responsibility should not be given to the Player.

Why Should We Adapt This Principle?

The aim of this principle is to protect your software architecture against the innovations or changes you may add in the future.

In other words, a change in the player character of our game should not affect the database operation that is a different responsibility.

The responsibilities should be seperated from each other so that their management be easy.

2.Open-Closed Principle

Entities should be open for extension, but closed for modification.

For example:

Let’s add a jumping feature to the Player class mentioned above.

As can be seen, we are able to extend our class without changing any existing feature.

Why Should We Adapt This Principle?

The main aim of this principle is to prevent confusion. If you do not design the base of a building properly and a change is needed when it comes to roof, how durable can this building be?

We can imagine our class as a box while applying this principle. When you want to add a pencil to the box you use for your valuable stuffs, there should be a room in the box. And, we provide this room with an order. You should not change the place of another valuable stuff to add the pencil. If you organize the box well in the first place, you just put the pencil in the right place.

The biggest cost of software is the changes added afterwards.

3.Liskov Substitution Principle

This principle is directly related to the Object-Oriented Programming. It states that a lower class created from an upper class satisfies all the features of the upper class.

For example:

Let our main class be bird and we add flying function to this class. There is no problem when we form a pigeon class from the bird class. Yet, when we form an ostrich class, we end up adding a feature to the ostrich that it is not able to do.

Liskov Substitution Principle states that such situations should not occur. We can fix this problem by adding another class between them or by giving the Pigeon class the ability to fly with interface(known as Protocol in Swift language.)

Another class was added in between.

Flying ability was added to the class as interface.

Why Should We Adapt This Principle?

This principle is presented to us to prevent any logical error that may occur in our classes and to add empty function so as not to lower the quality and readibility of the code.

4.Interface Segregation Principle

This is the principle that states that we should not form the interfaces as inclusive like a class but as specific such as the acquired abilities in the classes.

For example:

Let’s imagine an olimpic game that we can choose characters. Our characters will be superior or inferior to one another in terms of the features.

When we add the IAthleticAbilities interface to the SwimmerAthlete, we end up adding the ability to jump which is unnecessary for our swimmer. So, how can we fix this?

We have achieved the exact structure we wanted by breaking down the interfaces.

Why Should We Adapt This Principle?

According to the Interface Segregation, unnecessary abilities should not be added to the classes because if this happens, confusion of codes increases while the readability of the code decreases. To prevent this unwanted situation, this principle suggests breaking down the interfaces.

5.Dependency Inversion Principle

This is the principle that suggests that dependencies between the classes should be minimized. It also states that changes especially in lower classes should not affect the upper ones.

For example:

Let’s imagine that our app sends notifications via messages and e-mails. For this, we need two separate classes as messages and e-mails. Beside this, we also need a class that manages the notification operations.

When we form our classes like this, we make the notification class, which is an upper class, dependent on the lower classes. A change in the lower classes will directly affect the notification class in the future and this will lead the code to get complicated and be hard to manage. So, how can we fix this?

Abstraction gets involved here. If we add the upper class Notification to the lower classes as a feature, the upper classes will be unaffected by the changes in the lower classes.

Why Should We Adapt This Principle?

Dependency Inversion Principle is a principle that is put forward to prevent any confusion that would occur in the code. Dependencies between classes are minimized so that only the areas to be affected are affected. With this principle, our code will be open to develop and expand further.