All of us who are immersed in software development at some point have heard, have an idea or have experience about SOLID principles. This principles have been described long time ago (2000) and have been used in several programming languages.
This concepts are still been useful for all those who are developing software or have to review piece of codes in terms of quality/functionality (Like developers reviewing code in other programming language). It doesn’t matter how long have you been working with software (experience) these principles work as patterns to take good decisions at the developing time.
Let’s see what these patterns are and what they are trying to solve.
Have you ever tried to modify some piece of code and noticed that you will have to spent a lot of time refactoring or changing other functionality/files/classes than the specific piece of code?
This problem is known as Rigidity because it requires a lot of efforts like change several parts of the project to make a change.
Have you ever changed a piece of code and got errors/crashes/problems in other functionality/files/classes than the specific piece of code?
This problem is known as Fragility because a change may break unexpected parts .
Have you ever tried to reuse a piece of code in other file/module/project/repository and had to add his dependencies with it?
This problem is known as Immobility because is difficult to reuse a component in another file/module/project/repository because it has too many coupled dependencies.
I summarize all those problems making one golden rule:
Write code that is easy to delete or replace
As Uncle Bob (Robert C Martin) said, these concepts are not rules, laws or perfect truths, these are guidelines to help you developing good software and improve the quality of your software architecture so use them properly.
Is an acronym that stands for five guiding principles. I’ll be explaining each one with examples made in Swift (iOS).
Single Responsibility Principle means that a function, module, class or struct should have just one goal, reason or job. Every time you create/change a function/module/class/struct, you should ask yourself: How many responsibilities does it has? Sounds easy right?
We usually violate this principle because apply this pattern could be hard work in terms of the number of files, classes and/or protocols that you need to create for it.
In my experience as iOS developer, I saw one of the worst elements where we usually break the Single Responsibility Principle, the view controller.
We can detect this problem easily considering that:
A view controller can be a data source or delegate of your table view or collection view,
You can make web requests in a view controller
You can use business logic in a view controller
You can be formatting elements in a view controller
You can be handling the navigation in a view controller
Let’s look an example:
At first glance it’s not bad at all, but this class does more than single work and as you can see in the function names, there are different goals that this class is trying to achieve. That is giving us sign of bad design.
How many responsibilities does this class have?
MovieListViewController retrieves the data from the API (1), parses the API response (2), filter the movie list showing just the upcoming movies (3), and finally reload the table showing the cells (4), formatting the cell title (5). Also, we can filter the list using IBAction (6) and show the MovieDetailViewController once a cell gets tapped(7).
Some keys to achieve this principle is employ Delegation with Protocols, Design Patterns and Code Isolation (Moving the responsibilities down to little classes).
Let’s refactor this:
So first, we’ve isolated the view responsibilities to just display the information in the View using protocols (MovieListView), delegation (MovieListTableViewDataSource) and MVP pattern (MovieListPresenter), then
We’ve encapsulated the table data source job creating a class that handle all the table work needed and handling the table view selection through delegates (MovieListTableViewDataSource). Finally:
We’ve created a MovieListPresenter where we can handle the business logic, fetch data from the API using theMoviesAPIClient class and parsing that response using MovieParseHandler.
Finally, we’ve made a lot of improvements in this example project but it could take time because you need to uncouple all the class jobs and create a lot of files for it, but you’ll be rewarded having better and fully testable code.
These principles helps you to keep your classes as clean as possible. Don’t forget that you’ll need to use good practices and design/architectural patterns as tools to apply these concepts and improve your code to next level.
As you have just learned, I’ll be creating a series of articles about each SOLID principle avoiding have one so big article.
Hope you like this article, feel free to hit the clap button below 👏 to help others find it! Let me know your feedback in the comments below.