This article was published on Medium a few weeks ago. Since I'm saying good bye to Medium I am reposting it here.
When I join a new project (which happens quite often since I’m working as an independent freelance developer) I usually have a look at the current project setup first. It’s a good way to get a quick overview of how the project is organized, what tools they’re using or most of the times, unfortunately, they are not using.
I like clean, thoughtful and well-designed setups and processes a lot and I appreciate a healthy and sustainable code base as it makes working with your company’s code a lot easier, a lot less painful and it makes your developers faster in the long run since it results in a much more maintainable code base.
So when I have a look at your
package.json for example there are a few things I’d like to see there and I would really recommend and encourage you to somehow integrate them in your workflow. They might be hard in the beginning and sometimes your developers will curse for a moment but trust me once you’ve done that and you got used to it there is no way back.
Let’s start with a tool that was (and still is) controversely discussed in the dev community. It seems like you either love it or you hate it. I was in the second group at first and I’ll explain why in a bit. I’m talking about Prettier.
It’s a tool that formats your code in a completely unified way. You can either use the Format on Save option in your IDE, format it manually, or even create a Git hook to format all files that are being committed automatically.
Rik Nieu@riknieuThe 3 stages of @PrettierCode;
1. Ugh, why is it formatting it like this? Looks weird.
2. Hmm, ok, think I'm getting used to it. Need to adjust my own approach here...
3. OMGZORZ this is so liberating!06:53 AM - 15 Jun 2018
Many developers I talked to who disliked Prettier said that they want to have control over how their code is formatted and that they often disagree with how Prettier formats code. As mentioned in the beginning, that was also me in the beginning. Until I found the true value of the tool.
Most of the time it is not about you, but about your colleagues.
Ever wondered about that super strange coding style your colleague uses when formatting code? The same thought you have when reading that colleague’s code, your colleague will very likely have when he’s reading your code, ever thought about that? Won’t happen with Prettier.
Prettier has only very few options and formats your code based on some really sophisticated rules. They are open to new PRs, too. While you won’t always agree to how Prettier thinks your code should be formatted it’s freeing up so much mental energy, believe me.
Spend your energy on thinking about what to write and not how to write it! Write it however you like, hit CTRL+S and watch Prettier do its job. It really frees up so much mental energy. I’d say it has probably become the most valuable tool in my developer toolchain since switching to Git in 2010.
Another clear plus: we can end the debate whether to use semicolons or not and if 2 or 4 spaces is the right level of indentation. You can delegate that decision mostly to a computer program and write the code exactly you feel is right for you.
So my recommendation here, if it has not happened yet: add Prettier to your projects! Even more: have your files automatically run through Prettier to make sure that even colleagues who still refuse to use it in their IDE push their code in a way everybody can read. I remember that one colleague who refused to use it and later committed mock data for tests with an array of 25 objects. All. In. One. Line. No. Don’t be that guy, please.
Which leads us directly to our next candidate:
Husky simply describes itself in its readme with:
Git hooks made easy
And yup. That is what it is. It makes writing Git hooks a bliss! No more shell scripts that work only on your machine, no more need to install ruby or python only to run a certain Git hook. Install Husky, create a
.huskyrc file and put a few simple commands in there.
Husky works especially great in combination with lint-staged and install-deps-postmerge. lint-stage runs linters against all your staged files allowing you to modifiy files before they are eventually pushed to GitHub. install-deps-postmerge on the other side runs after you merged files from remote (e.g. via
git merge), then checks your
package.json and your lockfiles (
package-lock.json) for changes and automatically updates your dependencies.
In my typical setup I use it to automatically have all my staged files run through Prettier before they land on GitHub. That’s typically a pre-commit hook I add. Another one is an ESLint check which lets your commit fail to avoid having potentially harmful code in your code base. Which leads us to our next very useful tool.
no-undef or many many others).
If you can catch bugs at devtime instead of runtime, why should you not do that? I created my own personal eslint-config and published it as a package on npm. A client asked me to take a day to figure out which rules make most sense in their React project back in 2016 and so I created my very own package from this newly acquired knowledge with all the rules I found helpful. You can find it here: https://www.npmjs.com/package/eslint-config-wiremore
Although I’m really trying to keep it up-to-date on a regular basis there might be ESLint configs that are even better and more regularly maintained than mine. I can really recommend to have a look at the eslint-airbnb-config for that matter.
ESLint integrates really well with Prettier by the way. So together they’re a great combination.
When I develop software I am following the 12 factor methodology. This is something I recommend all my clients as that makes your software predictable, maintainable and understandable. Part of that methodology is to III. store config in the environment. And by environment, of course, environment variables are meant.
This is where cross-env and dotenv come into play. Both tools are designed to make your life as a developer easier when it comes to dealing with env vars. cross-env as the name indicates let’s you use env variables on all different platforms (Windows, Unix, Mac) without having to think about special syntaxes, try to detect the OS or terminal the user is using etc. Just prefix a command you want to run with cross-env followed by the env variable(s) you want to set and you’re all set.
$ cross-env HELLO=world node -e 'console.log(process.env.HELLO)' > world
The other tool, dotenv, is for pulling all the env vars into your application at runtime (node) or build time (webpack, rollup, etc.). It allows you to keep all your env vars in a single
.env file which is loaded automatically once you import dotenv into your application.
dotenv also respects your commandline env vars which then take precedence over env vars from your .env file by default. It goes nicely hand in hand with cross-env so I recommend using them together to add some more maintainability to your setup.
There are tools on the one side but there are also processes on the other side. Tools can help you get your processes right, support you to keep your codebase clean and tidy but for certain things you need to establish certain processes where tools are limited or not suitable.
Something most developers don’t like to do is to write documentation. I know it’s hard sometimes to write things down instead of writing code but having a good documentation is so important, especially if you’re having a high fluctuation and you’re off- and onboarding new team members regularly. And a good documentation doesn’t have to be the size of a whole book. You can start with a simple
README.md in your repository.
Setup a project as if you were new to your own team, clone the repo, install all dependencies, gather all the necessary environment variables and put it in your
.env file. Write down every single step. Don’t forget the obivous things you have done a long time ago: installing Node/nvm. Installing helpful editor plugins such as Prettier or ESLint. Provide links for all that and try to think of it as if you were onboarding a Junior Developer to your team.
Then write down all links to your develop, staging and production environment. Give hints where pull requests are deployed to (if they are) and where to find the link to your CI. I guarantee you it probably won’t even take an hour but will in return save you hours of work in the future, whenever you are onboarding new people or setting up the project from scratch. Encourage your colleagues to fix things if they are outdated.
This way they could even create their first Pull Request which is always a good feeling. Creating a Pull Request on your first day in a new project always feels rewarding, even if the only thing you actually fix is a typo or a broken link but it gives you the strong feeling that now, after your first PR, you’re really a member of the team already.
If you’re building installable packages (e.g. via npm) writing a changelog is also a great idea usually. And sometimes also a “decisions” document can be useful. Use it to note down why you have done certain things the way you’ve done it. It can give future team members valuable hints.
Ideally your main branches (usually
develop and sometimes also
staging) are protected and nobody in your team has the access rights to directly push code to one of these branches. All work should be done on branches! In my opinion it does not really matter that much if you’re working on feature branches or developer branches or if you’re strictly following Gitflow or not but more important is that you should really never have any of your developers directly push into one of the main branches!
The goal is to make sure that every single change has been peer reviewed and approved by at least one other member of your dev team. All large Git services (GitHub, Gitlab, Bitbucket) have such a feature. This is an easy way to make sure that at least the most obvious bugs can get caught before they are deployed. It also splits responsibility from a single person to at least two persons — the original creator of the PR and the reviewer.
Doing it that way also makes sure that code can be understood by others. If some parts of the code are not understood easily by other members of your team who review your branch you should think about either simplifying it and since that is not always easily possible at least add some comments there to have some inline documentation of what is going on there.
Keep your Pull Requests small. They are easier to review. They are easier to revert. And they are easier to fix if a bug is discovered while in review.
And probably most important: encourage your team members to have a good review culture! Take it serious and don’t underestimate the value of a thorough code review. I have had a project where I spend an hour or even longer on an average work day in code reviews and I have never before seen such a high quality code base.
What is the value of a high quality code base? Developer satisfaction, retention and in the long run: you gain speed by understanding what has been done months ago while at the same time not having to waste hours of fixing bugs every day only because you were careless 3 months ago, just to save 20 minutes of your time. Of course code reviews alone don’t make your code bug free or better maintainable per se but from my experience I can say the more priority the review process had in a team, the less technical debt had been accumulated over time.
This, in turn usually makes your developers happy since nobody likes smelly code and that automatically makes your developers want to write clean code to keep standards high.
There is nothing worse than discovering a bug in a new version of a browser or a device and not being able to fix it because some of your old dependencies are incompatible to other dependencies from your dependency tree which are needed to get this bug fixed. Been there. Done that. Spent almost a week only to update the dependencies in a project that hadn’t gotten any love for almost one and a half years.
During that time a new iPhone and a new iOS was released and for some weird reason my client’s site didn’t work properly anymore. The source for this bug was deep down in the dependency tree and required an update of one of the project’s core dependencies which itself required a new jQuery version etc. etc. etc. Long story short: it was a pain.
So even if you’re only in “maintenance mode” with your product you should at least spend some effort to update your depenencies regularly. At least, say, every 2 months. You should spend even more time to update your dependencies if you’re still actively developing your product. If you do that regularly, at least monthly, it is usually done within half an hour. Given that you have tests for the most important parts of your application of course. In npm you can run
npm outdated to see which of your dependencies are outdated, in yarn you can even update them easily by running
yarn upgrade-interactive in your terminal.
There are many ways to increase the quality of your codebase, the happiness of your developers and the overall performance of your company. Some of them require a little change in the mindset of the people involved, some of them can be implemented in a few minutes and have massive impact on the success of your team, your product and your company.
In this text I tried to illustrate some of the things you can usually implement pretty quickly and without too much resistance. I encourage you to try that. Not everything that works great in one team works equally well in another team. The things I described are mostly considered “best practice” though, so they should work at least for most of the teams.
Give it a try! And tell me if you did and it worked for you and your team!