As a developer, you probably use or have heard about SOLID principles. This acronym, introduced by Robert C. Martin (Uncle Bob), in his book Agile Software Development: Principles, Patterns, and Practices, refers to five basic principles of object-oriented programming, which are related to Design Patterns.

If we apply these five principles:

  • We will have flexible code, which we can easily change and that will be both reusable and maintainable.
  • The software developed will be robust, stable and scalable (we can easily add new features).
  • Together with the use of the Design Patterns, it will allow us to create software that is highly cohesive (that is, the elements of the system are closely related) and loosely coupled (the degree of dependence between elements is low).

Origin of the acronym SOLID

The acronym SOLID comes from:

  • S (SRP): Single responsibility principle
  • O (OCP): Open/closed principle
  • L (LSP): Liskov substitution principle
  • I (ISP): Interface segregation principle
  • D (DIP): Dependency inversion principle

Single responsibility principle

According to this principle, a class should have a reason, and only one, to change. That is, a class should only have one responsibility.

Let’s see an example:

As noted, this class presents three responsibilities: Authentification, Decode info and Save info. To fulfill the principle of sole responsibility we extract each of these responsibilities in other smaller classes.

Open/closed principle

According to this principle, we must be able to extend the a class without changing its behaviour. This is achieved by abstraction.

For each new type of vehicle, the getScrapingAddress() function must be implemented again, which breaks the principle of open/closed. To solve this point, we introduce the Scrappable protocol that contains the getScrappingAddress() method:

Liskov substitution principle

This principle, introduced by Barbara Liskov in 1987, states that in a program any class should be able to be replaced by one of its subclasses without affecting its functioning.

For example, suppose we have a class, UserService, which has the responsibility of contacting users (for example, sending an email). If we change the business logic and, for example, we can only send mails to users over 17 years of age, we can create a subclass that adds the new business logic:

In this case, the Liskov substitution principle is not fulfilled, since the subclass adds a condition (that the age of the user is over 17 years old), which a customer of the UserService class would not expect. We can solve this problem by not creating the subclass, and adding the precondition to UserService (including a default value):

Interface segregation principle

The Principle of segregation of the interface indicates that it is better to have different interfaces (protocols) that are specific to each client, than to have a general interface. In addition, it indicates that a client would not have to implement methods that he does not use.

 For example, we can create an interface for animals that includes displacement methods:

However, although Wale adopts the protocol, there are two methods that he does not implement. The solution is to establish three interfaces (protocols), one per method:

Dependency inversion principle

According to the Dependency inversion principle:

  • High level classes should not depend on low level classes. Both should depend on abstractions.
  • Abstractions should not depend on the details. The details should depend on the abstractions.

This principle tries to reduce the dependencies between modules, and thus achieve a lower coupling between classes.

Let’s look at the following example:

What happens if instead of using CoreData to save the data, we want to use the Realm database? The instantiation of the class as we have done in the example generates a strong coupling, so if we want to use another database, we would have to redo the code.

To solve this, we can do what was explained in a previous article, when a database layer was established.

Now we have User that adopts the Storable protocol and the UserService class adopts the StorageManager protocol, so even if we change the database, we will not need to change the entire implementation code:

Conclusion

These principles will allow us to reduce the rigidity and fragility of the code, by allowing us to create reusable, maintainable and higher quality components in your code.


0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Follow on Feedly
shares