As a result of publishing the series of post of the clock-in/out system, I had the need to write a function to import the data from a large XLS file to a Postgres database using the ORM (TypeORM).
This function was written quickly as a script without thinking too much about the quality of the code, but simply “work”. However, once the system is working and a test suite is available, it is a good idea to go through a constant refactoring to improve the code.
Next I will show different refactoring steps that I have applied to this function to improve the quality of the code. Therefore, the function that we are going to improve is shown first.
- normalizedUID: this function is used to generate the name/uid (string) of each teacher.
- getDaysByTeacher: Returns an array in which each position represents each user’s day. Each of the days is also represented by an array. Hence, this function returns an array of arrays in which we will have organized the weekly working hours of each user (fixed schedules).
- factorySchedule: Create a schedule object from another object composed of the room, hour and number of day.
The main code would be as follows after the extraction of functions:
Before going on to address the next phase of refactoring, we will eliminate the variables that are understood using the domain of the problem, also the temporary variables will be removed.
The first forEach loop that we are going to address is the following:
This loop can be transformed into the method reduce because of what we want to get a single value (an array) after iterating through each of the days. In addition, the schedule variable can be omitted and the factorySchedule method can be invoked directly since the creation of this variable does not add semantic value in the code.
If we observe the function performed in the body of the method reduce, it is an if-else which can be transformed into a ternary operation that we can combine with the potential of immutability (another characteristic of functional programming) leaving the code as follows:
If we look at the code, the next natural step will be to replace the forEach method that includes the reduce by another method reduce. It may seem complicated the code that will generate since we are using the features of fat-arrow and spread operator (…) which if you never are used before can seem abstract (we will solve it by creating functions that allow you to decompose the task).
In our case, we are going to create several small functions that combined with the bind method will solve the problem of passing parameters in the callbacks. In this way, the resulting code until this moment would be the following:
The next step is to address the forEach method that encompasses the entire main method. The elimination of this method will allow us to eliminate the two variables that act as accumulators (users and schedulers). In such a way, that the method reduce will receive as an accumulator an array that contains two arrays (schedulers and users), which will be unstructured to be able to be concatenated easily in the method reduced.
After refactoring the code we find the following version:
In the same way as we did in the previous case, the method reduce receives a callback that is the one that performs the conversion to JSON, and finally we rename the content of the file to a variable called xls. So the partial result is the following:
Finally the result of the script after making these changes is shown below:
- Extract functions.
- Name the functions and variables must be an identification value.
- Use the built-in language methods for your use (forEach against of reduce).
- Abstract complexity and details of the code to auxiliary functions of lower level.
Originally published at www.carloscaballero.io on December 28, 2018.