From the messy codebase to the new era of consistent quality across the company
Have you ever needed to develop in a messy codebase? Have you ever switched projects and felt lost because of the different standards?
Everyone has probably been through one of those scenarios. We have been too, but we have found ways to improve code style consistency across the company.
These are the main challenges that led to an inconsistent code base that we had to deal with:
- many developers in a unique project
- many developers in many projects
- specifics company needs (like customized rules to be followed)
First, let me start with a story…
In September 2017, we released the first QuintoAndar PWA (Progressive Web App). Which means that we basically rewrote the entire front-end application that existed before.
(I was part of that team, it was an amazing experience! I’ll tell it in another post someday)
One year after the release, we now have about 10 PWAs. All of them using the same stack: React + Redux and reusing code between projects.
We already had a glimpse of how bad things could get on our legacy website if things weren’t kept in check, and we definitely didn’t want our shiny new project to go the same route.
As everybody knows, JavaScript is an amazing programming language with thousands of libraries and different projects around the world. However, JS world is not really perfect! But if I had to summarise the main point of contention:
“The best and worst of javascript is the lack of constraints that allow us doing everything we want”
We have so much “freedom” with JS, which is amazing because we can create a lot of things. However, it’s dangerous too! Just imagine many developers being able to do whatever they want in a single project without any kind of standard /consistency.
It can turn into a mess as it was our old project. Messy code is difficult to read, test and maintain. This makes the project more “buggy” and harder for the new developers to onboard.
As a developer, I would prefer not to give that kind of “freedom” as we can get a bit too much creative!
So... How did we avoid making the same mistakes of the old project in the new ones? How did we prevent messy code?
We set boundaries to our own “freedom”! We put constraints on the project in order to make the code clean and consistent. It helps developers to be creative in solutions for the problems not for code style.
How did we set boundaries?
First of all, we enforced at least one code-reviewer in each pull-request! Unfortunately, this is not automated because it depends on humans, so it can’t scale as well and some errors and inconsistencies will pass!
For the task of automating we used code linters to check the code style and best practices. Thus, we can ensure that all JS files in a project will be consistent.
This leads to improved readability and maintainability of the code. It also helps to find syntax errors and have fewer bugs. Making this process part of CI is key to ensure that standards are kept during the entire development cycle.
There are code linters for almost any programming language, in JS, the most popular is Eslint*.
*If you want to know how it works internally you can see here and there are lots of articles about eslint as you can see [_here](https://github.com/dustinspecker/awesome-eslint)._
Now you may think:
Ok, lint.. Everybody knows.. Why am I reading this article?
We had to scale this solution to several projects and repositories and this can become a growing pain. As companies grow, so does the number of projects in JS, including back-end in NodeJS.
So, how to maintain the same code style and code quality for the entire codebase?
As I told before, we have 10 PWAs and an internal components' library too. On top of that, we have several micro-services in NodeJS. As we can see in the image below:
Thus, we truly understand the pain to try to maintain the same code style and code quality in the entire codebase.
Still, you might think that is not a huge pain because we can just copy and paste the eslint config and rules in ALL our projects .
It’s a solution, but obviously, it’s not the best one!
Every new config or new rule you want to put, you should go through all the projects replicating the same thing.
The real danger here is that you may forget to apply some change in one and when you see it, we’re not following the same code style again => inconsistent codebase 😑
For that, the best way to fix it is using a cool feature of Eslint called Shareable Configs.
Shareable Configs
All the eslint configurations of a project are in a file named .eslintrc.This file is an important part of your project and sometimes you may want to share it with other projects or people.
How can we share it?
Shareable config allows you to publish your configuration settings on npm. Allowing others to download and use it in their ESLint projects.
All you need to do is add it as a dev-dependency in your project and extend it in the eslint resource file.
There are lots of shareable configs in npm right now as we can see here. One of the most used is Airbnb’s. This is one that we use at QuintoAndar too, but we felt the need to add our own settings too.
Thus, we created our shareable config packages eslint-config-quintoandar. But as you know we have specific stuff to PWA (front) and some to our micro-services (back-end). That’s why we created:
- eslint-config-quintoandar-base is the npm package that it’s common for everything in JS and uses NodeJS (see at GitHub).
- eslint-config-quintoandar-pwa is another npm package that has the specific configurations to react applications. It extends the QuintoAndar base package (eslint-config-quintoandar-base) and adds the specific stuff (see at GitHub).
Feel free to use our packages, and we’re also open to contributions. Everything is documented. If you want to create your own, you may also use as a reference.
At QuintoAndar, we’re still working on those packages and the usage of them. But the results are visible , with this tool you can maintain the same code quality and application quality because we could use rules that help to find bugs and improve performance.
For example, one simple rule that helps us to avoid unnecessary loss of performance, forcing not to use arrow functions or bind inside the render of React components, like this (line 8):
The code above would not pass in our eslint and, consequently, break the build (CI) forcing the developer to fix it.
The example above is a rule that already exists on the package provided by Airbnb. In case you feel the need, like we did, to create rules for your specific scenarios you can create custom rules.
Custom rules
Sometimes you need to enforce a specific rule in your codebase that is not going to be relevant outside of your company or you need to create one that doesn’t exist yet in the many existing open-source plugins.
It’s really easy and simple to create a new rule.
You just need to use the AST (Abstract syntax tree) to find what you want to report and set the description of how to fix it. If you need a more detailed description you can find it atthis article or in eslint docs.
At QuintoAndar, a npm package with our custom rules:
eslint-plugin-quintoandar (GitHub).
In this plugin, we have different kinds of custom rules:
Rules that are applicable to every project of every company, for example:
- A rule does not allow the use of target="_blank" without using rel="noopener noreferrer"
Rules that are applicable only for QuintoAndar, for example:
- A rule created to deprecate an internal component that should not be used anymore, or it can be applied to functions or files too.
A rule to deprecate a file in your project is the simplest rule that you could make. You just need to assert the import like this:
As you can see, it's really easy to customize lint rules to comply with new necessities of your team or company maintaining consistency and code quality across the codebase.
So, the final solution for consistent code quality across the company was:
- Add eslint in all projects
- Create and use npm packages of shareable config for the company
- Create new customized rules to comply with new requirements
Still, these steps won't solve the whole problem, because it now means that every new rule needs to be applied to all files in all repositories at the same time.
It doesn't scale and it's dangerous because we can break the apps. So, we need to figure how to apply the rule continually using a progressive way to apply them.
I've already broken some apps trying to enforce a new rule everywhere in one shot. However, I found a better approach. Do you want to learn about that?
See the next article that explains what and how we to use Progressive Lint and why you must start doing in this way.
Progressive Lint: How to continuously improve the codebase
Join Us
If you like challenges and you want to work in a startup that is redesigning the entire experience of the rental process using technology and design as the core components. Look at our job opportunities on our career page. We’re always looking for talented and eager to learn people.
Tks for reading! I’m always open to receive feedback, recommendations or questions, feel free to contact me!!
LinkedIn : https://www.linkedin.com/in/pamepeixinho
Twitter : https://twitter.com/pamepeixinho
GitHub : https://github.com/pamepeixinho
Website : https://pamepeixinho.github.io
My last name is LittleFish, I swim and code sometimes. “Sea” you later! 😉
Top comments (0)