SOLID is an acronym that stands for five principles in object-oriented software design:
Single Responsability
Open-Closed
Liskov Substitution
Interface Segregation
Dependency Inversion Principle
Although Go is not an object-oriented language, we can still utilize the principles of SOLID. Below, we will look in more detail at each of the principles.
Single Responsability
A class or, as is the case with Go, a struct should have a single responsibility. That is, each struct must be designed to perform a certain action.
Thinking about a CRUD, of course, you won’t have a struct for each of the actions (Create, Read, Update, and Delete). But it also won’t have just one struct to handle all the responsibilities of the package.
The ideal is to have at least one struct that represents the package entity. One to handle database transactions, commonly called a repository. And another to handle requests, regardless they are via the API or in some MVC model.
Open-Closed
A class must be open to extensions but closed to modifications. That is, whenever it is necessary to add functionality, we should extend the class instead of modifying it.
Although it is possible through the embedding strategy, this principle is a little more difficult to apply in Go.
This is because, unlike a language that implements object orientation, in Go, not everything will be linked to a struct.
Even so, for greater reuse of system functions, it is important that they have their responsibilities very well defined.
Liskov Substitution
“Child” classes, can be used in place of “parent” classes without the program breaking.
This is another principle that, to be applied to Go, may require some changes that, in other languages, such as PHP, are not necessary.
As Go is a strongly typed language, it is not possible to pass structs of type Bar, where only structs of type Foo are accepted.
Another point worth remembering is that, in Go, there is no concept of inheritance. Therefore, even if a struct uses the embedding strategy, it has no direct relationship with the other struct, as in class inheritance.
Interface Segregation
A class should not be required to implement interfaces and methods that will not use. In other words, it’s better to have six very specific interfaces than two generic ones.
This principle is also widely applied in the core of the Go language. If we look at the io package, we have, for example, the interfaces:
-> io.Reader
-> io.Writer
-> io.ReadWriter
Wheres the third one is nothing more than an embedding of the first two.
Dependency Inversion Principle
Dependencies must be abstracted so high-level modules don’t depend on low-level modules.
-> WARNING! Dependency Inversion and Dependency Injection are different things.
One way to implement this concept is to use interfaces to define attributes of structs and function parameters. So, instead of expecting a concrete type, i.e. highly coupled, we expect any type that implements the interface.
Conclusion
Although it is impossible to apply all SOLID concepts in Go the same way as in object-oriented languages, we can still build highly scalable and robust software.
My point of view is that the concepts that are unable to be applied partially or fully do not impact the software’s robustness, scalability, and flexibility.
In the upcoming article, I’ll bring an example code written in Go to cover each point explained here.
Therefore, if you are not yet a subscriber, be sure to subscribe to our newsletter. It’s free, and your data will not be sold to advertisers.
See you next time!
*O conteúdo deste artigo é de responsabilidade do(a) autor(a) e não reflete necessariamente a opinião do iMasters.
Leave a comment