6 coding best practices to take you to the next level
Tags: webdev, programming, tutorial, productivity
Published: 2023-05-31 00:55:51


Today I'll talk about a topic that will follow you over your entire career as a software engineer: **coding best practices.** The practices below are more focused on people starting their careers, but they're valid for any level.

It's also worth mentioning that knowing about these practices are not only good for your day-to-day job, but also very important for **technical interviews**. Demonstrating knowledge on these practices are a great sign of experience and authority over the development process.

## Why learn best practices?

Programming is an activity that is not only related to the act of writing code that works, and not restricted to the writing itself. There are a lot of other activities around that, involving conventions, teamwork definitions, and process improvements.

The average developer spends more time reading than writing code. Not only reading, but planning, thinking, debugging, choosing the best approaches, defining the right tools, and so on. These processes can always be improved, and some of them can be delegated to your computer.

It's kinda easy to write code that works, but not so easy to write code that is maintainable and easy to read. This is pretty well stated in this quote from Martin Fowler:

> Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

With that said, let's see some good practices that you can apply right now to your coding.

## 1. Meaningful naming conventions

It's very common to see on programming tutorials examples of variable and function names like:

- `var numsCount`
- `const numsAmnt`
- `function calcNumsAvg(fnum, lnum)`
- `function calcAge(bdate)`

The computer completely understands these commands, in fact, it will understand any name that you add as variable or function names (except reserved words).

The problem here is that you or other developer will need to read and/or give maintenance to this code in the future, when the context that you had when these namings were defined will not be on your head anymore. This can lead to more time spent trying to understand the code, or even a misunderstanding of its purpose.

Even if you understand the code and remember its purpose, another factor that needs to be considered is when new developers join the team. Having not so clear and explicit namings can lead to more time spent ramping-up.

The solution to this issue is to use **meaningful naming conventions**. Let's refactor the previous examples:

- `var numsCount` → `var numbersCounter`
- `const numsAmnt` → `const numbersAmount`
- `function calcNumsAvg(fnum, lnum)` → `function calculateNumbersAverage(firstNumber, lastNumber)`
- `function calcAge(bdate)` → `function calculateAgeFromBirthdate(birthdate)`

These namings are giving an explicit and clear context about what's going on to the reader. Talking about file size, the difference is not considerable, it's just a couple more chars. Even if it's more than a couple, it's a tradeoff that is worth it.

Another great advantage is that if you have self-explained namings, you can reduce the comments on the code. In many cases, the code becomes the documentation.

## 2. Use a code formatter

When you're coding, there are some decisions and procedures that can be delegated to the computer. One common example is the code formatting.

In languages like JavaScript, you need to take some decisions in order to have standards in your codebase:

- Should I use single or double quotes?
- Should I add semicolons at the end of my statements or not?
- Should I use spaces or tabs?
- Should the indentation be 2 or 4 spaces?

Having these definitions in place before starting a new project is crucial. When you're part of a team, this is even more crucial. Can you imagine if your team has 4 developers, and each one uses a different formatting rule? The code reviews will be a mess.

One of the tools that aim to solve this is [Prettier](https://prettier.io/). It is an opinionated code formatter that supports many languages, and the best part is that it integrates with your editor, so you can expect code formatting on every file save. Pretty cool, right?

You can play with some Prettier configurations on its [playground](https://prettier.io/playground/).

## 3. Have a clear folder structure

When starting new projects, or even working on existing ones, it's important to always stick to a clear and predefined folder structure. This definition can be done based on the architectural pattern that is being used.

Having a clear folder structure has many advantages, like:

- **Faster ramping-up:** when new developers join the team, they know where to find files/features;
- **Faster decisions:** when you need to write new features, you already know where to put new files;
- **Faster debugging:** you can speed up your search through the project;

It's also important to decide if you will use index files, default exports, camel-case or snake-case, for example. These definitions are very important to the standardization and success of the codebase.

**There's no right or wrong definition.** Choose one, share it with the team members, document if necessary, and stick to it.

Keep in mind that you don't need to keep it forever. If you want to change it in the future, just refactor your code. It can be hard, but it's possible. Nowadays, many IDEs have built-in features to help with that.

## 4. Know your editor or IDE

Like I've mentioned, usually a developer spends more time reading than writing code. That's why it's important to know how to optimize your editor or IDE use.

I've been using VSCode for a long time. But before that, I used Sublime Text, Atom, and even Eclipse and NetBeans.

**Doesn't matter the editor or IDE that you choose.** You need to feel comfortable and productive, because you will spend most of your day looking and interacting with it.

There are a lot of shortcuts and plugins that make developers' life easier, so it's very important to always keep an eye on the repetitive tasks that you execute, and also on the complex ones, because these can be simplified with plugins or shortcuts.

Most of the IDEs let you create snippets, which generates pieces of code much faster than if you have to type everything from scratch every time (React devs know the pain).

Here are some useful plugins and integrations that I use on my IDE:

- [Prettier](https://prettier.io/) (format everything on file save);
- [ESLint](https://eslint.org/) (give hints and suggestions about potential issues);
- [GitLens](https://www.gitkraken.com/gitlens) (integrates with Git and show useful info);
- Syntax Highlighters for specific extensions (`.hbs`, `.md`, `.json`, `.csv`);
- [Markdown Preview](https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced) (live preview for markdown files).
- And much more.

Another tip is to save your IDE's configuration file (it's usually a JSON) on your GitHub or somewhere else, so you can reuse it if you need to reinstall your IDE, and you can also share it with other people.

## 5. Use Git wisely

Using the Git basics is simple, but you can level-up this skill with some simple actions.

It's very important, mostly when working on teams, to choose a commit convention and stick to it. This lets everyone know instantly what each commit, branch, and pull request means.

One pattern to write commit messages is to imagine the sentence _"This commit will..."_ before the actual commit message. [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) is widely used by the community. It's, as defined, _"A specification for adding human and machine readable meaning to commit messages"_. Here are some examples:

- `feat: create new user page`
- `fix: correct submit button behavior`
- `refactor: improve readability on UserList component`
- `test: create tests for GET /payments endpoint`

It's also worth using conventions to connect GitHub to your project management app (e.g., Jira, ClickUp). This is very useful not only for developers, but for other stakeholders.

Another good practice it's to have multiple tiny commits. I heard a great analogy from a past manager that I've worked with, that each commit is like a hiking anchor; if you fall, you'll be hanging on the last anchor that you fixed, so you're safe.

This is useful during code reviews, because each commit will represent one step of the solution, which can give more context to the reviewer and also will act like a documentation for the PR.

Another tip is to have aliases for some common and repetitive git tasks. Here are some examples to give you ideas:

- `ga` → `git add . `
- `gs` → `git status`
- `gc` → `git commit -m ` → `gc "feat: add hover to buttons"`
- `gps` → `git push -u ` → `gps origin main`
- `gpl` → `git pull` → `gpl origin`

These aliases can be defined on the `.bashrc`, `.zshrc`, or the respective file that you use to configure your terminal.

There are also some concepts that you're not going to be using in the beginning but at some time they'll be essential to you as a developer:

- [`git rebase`](https://git-scm.com/docs/git-rebase)
- [`git stash`](https://git-scm.com/docs/git-stash)
- [`git grep`](https://git-scm.com/docs/git-grep)
- [`git reflog`](https://git-scm.com/docs/git-reflog)
- [`git reset`](https://git-scm.com/docs/git-reset)

## 6. Write code with the SRP mindset

SRP means [Single-Responsibility Principle](https://www.wolff.fun/srp-in-react/), and it's one of the five [SOLID](https://en.wikipedia.org/wiki/SOLID) principles that Uncle Bob introduced to define good software engineering practices. The SRP on its definition means:

> A class should have one, and only one reason to change, meaning that a class should have only one job.

What I mean by "SRP mindset" is to have attention to some details that may pass when you start coding. Sometimes this can be a helper method that is not very related to the class that it's defined in, a component that does more than one thing, or a logic that is repeated in more than one place.

I know that it's hard to see these improvement opportunities at first, but you'll get there with time and study. Some examples of situations that can be improved are:

- A `UserClass` that also connects to the database, gets the users, parses the result, and returns it;
  - It's a good idea to have repositories/entities to deal with database logic;
  - Parsing can be extracted to a helper or utility class/function.
- A logic that is repeated in many places;
  - Abstract this logic into a class or function, and call it in these places.
- A React component called `ProductsList` that also implements each product's presentation, the buttons, the data fetch and has all the logic for each button action;
  - Create a `ProductCard` component to make it reusable;
  - Create `PurchaseButton` and `AddToCartButton` components with specific logic and make them reusable.
  - Abstract the fetch logic into hooks and services;

And the list goes on... This is a very subjective topic, and there are many different opinions around it.

If you want to know more about that, I wrote an article about [SRP in React apps](https://www.wolff.fun/srp-in-react/).

## Conclusion

These coding best practices are only a few of them, and this is a topic that you'll probably be studying for your entire career as a developer. Don't try to apply everything beforehand, first identify the opportunity of improvement on the code or process, and then choose the best solution. After that, analyze and reiterate.

---

If you have any feedback or suggestions, send me an email:  lucashwolff@gmail.com.

Great coding!