Starting with this post I will be diving into the SOLID Principles of Object Oriented Programming. There is an abundance of resources when it comes to SOLID in OOP. And sure that makes sense since it was created to be applied to OOP. But I recently discovered that SOLID can be applied to Functional Programming as well. And why not? I will be demonstrating these ideas with ELixir.
The first principle I want to talk about is the Single Responsibility Principle. It is the "S" in SOLID, and it is SPR for short.
A class should have only one reason to change.
We should always expect the code to be changed sometime in the future. Knowing this expectation we should make it as easy as possible to handle this change. It is easier to change something without affecting the code as a whole if we split it up into smaller pieces. That is why not only a class should have one responsibility but functions too should have a single responsibility.
So how can we apply this principle if ELixir does not have classes? This is when we have to think just a little bit out of the box. Elixir may not have classes but it does have modules. And the same concept still applies.
A module should have only one reason to change.
I keep mentioning responsibilities. What exaclty is a responsibility? A responsibility can be defined as the reason for the change. When a module or a function has many responsibilities it has many reasons to change. If a module or funciton has many responsibilities, the responsibilities are coupled to each other, which means a change of one part of the code may result in a change for another part of the code.
Sometimes it can be a a little tricky to identify whether a function is doing too much. One way you can figure this out is if you describe your module or function with the use of the term "and" or "or".
For example, the module Rectangle has a function that's called area. Area calculates the area of the rectangle, and then it formats it to be colored red, and lasty it prints the formatted area to the command line. So we can be sure that the function area is doing a lot of things that are more than what its responsibility should be. Area should only be calculating the area of the rectangle as the name suggests.
Not only does this function have a lot to do, it is also hard to test. I can't individually test whether the area is correctly calculated, I can't check if the color changed to red, and I can't be sure that it is infact printing to the console. So we must refactor our code in order to have smaller, more focused functions, and to allow each function to be easier to test.
In the above snippet we have managed to split everything into separate functions. Having our functions smaller we are able to write tests for each function.
We can most certainly refactor this code further, I will touch more on that in my next post.