The first refactor in the user registration use case
It is a myth that we can get systems “right the first time”.
This post is based on two other posts. Check them first for a broader understanding:
- Authentication rules in a handcrafted iOS application with TDD https://medium.com/cocoaacademymag/authentication-rules-in-a-handcrafted-ios-application-with-tdd-8db5396ebac6
- Firebase user registration at iOS with integration tests https://medium.com/cocoaacademymag/firebase-user-registration-at-ios-with-integration-tests-fa450e4ec8bb
This post will provide you an update about the changes that I made in my project. These changes are in this commit. And I’ll also talk about:
- Single Responsibility Principle
- Entities
- Test Driven Development and Unit Tests
The problem
While writing my last post in this project, I realized that my user registration use case had more than one responsibility. And this breaks the first SOLID principle, the Single Responsibility Principle. The use case had the complexity to validate data and deliver data across other layers.
It is a myth that we can get systems “right the first time.” Instead, we should implement only today’s stories, then refactor and expand the system to implement new stories tomorrow…
Martin, Robert. “Clean Code” 2008
So, with all my tests passing, is time to refactor.
Single Responsibility Principle
The Single Responsibility Principle (SRP) states that a class or module should have one, and only one, reason to change.
Martin, Robert. “Clean Code” 2008
Analyzing the use case code, I have identified the following responsibilities:
- E-mail format validation
- Name format validation
- Password format validation
- Manage input data
Four reasons to change is too much. And except the last item, all others are not related to the use case context, and could be easily delegated to other classes.
But why having multiple responsibilities is not a good thing? Because the more reasons you have to change, the greater the chances to mess up something else. Besides that, it is harder to test a class with more than one responsibility.
Refactoring
Now that I already know where the responsibilities are, it’s time to extract the code and test it. The code responsible to make format validations will be extracted to small classes, that will be responsible for a single purpose. These classes are called Entities.
Entities encapsulate Enterprise wide business rules. An entity can be an object with methods, or it can be a set of data structures and functions…
…They encapsulate the most general and high-level rules. They are the least likely to change when something external changes.
Martin, Robert. “The Clean Architecture” 2012
I’ll show just the ValidateEmailEntity
. Because the other entities follow the same process. So I started with the entity tests. The first scenario is very simple, it’s just an assert by an empty e-mail, that should be invalid.
And to make this test run with success. The code below is quite enough.
After this simple scenario I started to increase the test complexity. Making asserts by email with invalid characters, without provider, incomplete, and with special characters.
And fortunately a simple regex (found on Stack Overflow 😆) made all scenarios pass. The code below shows how the ValidateEmailEntity
got.
After creating an entity for each data format validation, I’ll go back to the use case and make use of these entities. Below is the old use case with multiple responsibilities:
And after the refactor (13 additions and 24 deletions) the use case is cleaner and easy to understand:
As you can see I also created a protocol that had a isValid
property to facilitate error validation. And another to get the respective error.
As it’s possible to note I also created a protocol to keep some pattern and this was useful to filter just the invalid inputs and I also created an error property.
And because I am testing the validations separated from the use case, It’s not necessary to test all data variations at the use case level anymore. So I ran the tests and all tests are green, with this the refactor is completed successfully.
References
Martin, Robert. “The Clean Architecture” 2012
https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html
Martin, Robert. “Clean Code” 2008
https://www.amazon.com.br/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882