Recently I started to read Clean Code, it is a well-known book in our area in which Uncle Bob tries to give us what he considers clean code, that is, a simple code to read and also to maintain.
In this article I want to focus on the first three chapters of the book where he talks about variables and functions. But this seems so common, that maybe you think if just paying attention to these two points can really improve the quality of my code?
The answer is yes and a lot, if we think carefully about the names of our variables and those names will be clear and will tell you what values are stored there and help in our understanding of what is going on in the code.
With an easier reading and understanding of the code, it is also easier to understand where to move and what to change, thus also helping in the maintainability of the software.
See an example with bad variable names:
const fn = "Patrick";
const yb = 2019;
const ln = "Nicezi";
console.log(fn+" "+ ln + " nasceu em" + yb);
// Result Patrick Nicezi was born in 1998
Now let's see the same example with well-named variables:
const firstName = "Patrick";
const yearOfBirth = "2019";
const lastName = "Nicezi";
console.log(firstName +" "+lastname+" nasceu em" + yearOfBirth);
// Result Patrick Nicezi was born in 1998
As you can see, the second one is much easier to understand because each variable says exactly what it stores and when it is used in conjunction with others it is much easier to understand what is happening. And this choice of names applies to everything you name during development like class names, functions...
But not only giving a good name to the variable gives a clear naming pattern it's also important to create a naming pattern, it helps a lot the next person who reads your code to understand it. For example:
function alterUser(){...};
function changeAddress(){...};
function modifyUserDate(){....};
When reading the code above, although I know that they are all functions that change an object, I still wonder if they have the same purpose, because with the different names I feel that they are doing different things
function updateUser(){...}
function updateAddress(){...}
function updateUserDate(){...}
Now in code with a naming pattern we can clearly see just by reading the function name what their purpose is and that they are similar purposes, and with this pattern it is much easier for someone who has never read a code to know what any function that starts with update does.
Speaking of functions, we have some very important things to focus on when creating one, the first one a function must do only one thing and the second it must not be too big, because apart from making it difficult to read if the function is very large it probably does more than one thing.
See an example of this:
function returnFormatedProducts(products){
products.map(product =>{
let amountOfPassengers;
let adults = 0;
let childrens = 0;
if(product.type === 'CRUISE'){
adults = cruiser.persons.adults;
childrens = cruiser.persons.children + cruiser.persons.infants;
amountOfPassengers = {adults,childrens};
}else if(product.type === 'HOTEL'){
const passengersPerRoom = hotel.rooms.map(room => {
let childrensInRoom = 0;
let adultsInRoom = 0;
passengers.forEach(passenger => {
if (passenger.type === 'ADULT') {
adults++;
} else {
childrens++;
}
return {adults,childrens};
});
amountOfPassengers = passengersPerRoom.reduce(
(totalPassengers, passengersInRoom) => {
return {
adults: (totalPassengers.adults += passengersInRoom.adults),
childrens: (totalPassengers.childrens += passengersInRoom.childrens),
};
},
{ adults: 0, childrens: 0 },
);
}else{
passengers.forEach(passenger => {
if (passenger.type === 'ADULT') {
adults++;
} else {
childrens++;
}
});
amountOfPassengers = {adults,childrens};
}
return{
sellDate:product.sellDate,
route: product.route,
startDate: product.startDate,
endDate: product.endDate,
price: product.price.replace('$', 'R$ '),
paxChd: `${amountOfPassengers.adults} / ${amountOfPassengers.childrens}`,
}
});
}
This code becomes much clearer when we separate this large function into smaller functions and each with their own responsibility it becomes clear what the function does just by reading its name.
function returnFormatedProducts(products){
products.map(product =>{
const amountOfPassengers = this.getPassengersAmount(product);
return{
sellDate:product.sellDate,
route: product.route,
startDate: product.startDate,
endDate: product.endDate,
price: product.price.replace('$', 'R$ '),
paxChd: `${amountOfPassengers.adults} / ${amountOfPassengers.childrens}`,
}
});
}
function getPassengersAmount(product) {
if (product.type === "CRUISE") {
return getPassengersFromCruiser(product);
}
if (product.type === "HOTEL") {
return getPassengersFromHotel(product);
}
return countPassengers(product.passengers);
}
function getPassengersFromCruiser(cruiser) {
const adults = cruiser.persons.adults;
const childrens = cruiser.persons.children + cruiser.persons.infants;
return {
adults,
childrens,
};
}
function getPassengersFromHotel(hotel) {
const passengersPerRoom = hotel.rooms.map(room => {
return this.countPassengers(room.passengers);
});
const amountOfPassengers = passengersPerRoom.reduce(
(totalPassengers, passengersInRoom) => {
return {
adults: (totalPassengers.adults += passengersInRoom.adults),
childrens: (totalPassengers.childrens += passengersInRoom.childrens),
};
},
{ adults: 0, childrens: 0 },
);
return amountOfPassengers;
}
With this little code refactoring we can read it more smoothly, when we see the returnFormatedProduct function, we can understand what it does and if we need more details on how the number of passengers are taken, we can look at the specific functions for that.
And if you ever need to add a new shape or change an existing one, it won't impact the code as a whole and can be easily changed.
Conclusion
Writing clean code is a matter of practice, training and paying attention to the small details. It's an ongoing process, don't be afraid to refactor your code and rename things if you find better names for them.
Top comments (1)
I like your article.
Just wanted to add, returnFormatedProducts(products)
In the return statement, you should add 2 or 3 more functions. One is for formatted price, another is for number of passengers display value adult/child.
Also, amountOfPassengers is misleading. It should be number of passengers by kind or something.