Quality Approaches - Code Quality
Focus for this post is to ensure our code follows certain standards, so that our code is easy to understand, maintainable and someone coming in can get started pretty quickly.
I won’t be re-inventing the wheel here, as there are so many practices highlighted out there that help achieve this objective. My goal here is to give everyone suggestions of what could be applied, and there are certain concepts you might not have considered, so it could serve as a good refresher.
Better GIT commit messages and better Pull Requests
A lot of the times, when we commit code we just want to push the code up upsteam and don’t really give a lot of though about what we are entering within the commit messages. When we then try to figure out what we pushed it makes it hard to understand.
Besides writing clear concise code, which is self documenting have a good commit history and describing the work you’ve done in a PR via a message makes a big difference.
Using standards across the team here helps a lot. I’ve used Conventional Commits in the past and it has been great in standardizing the process across the team, and therefore making it easier to understand the changes made.
Here’s a reference to the specification I’ve used in the past to good effect but I’m sure there are a few around https://www.conventionalcommits.org/en/v1.0.0-beta.4/ The goal is to get alignment within the team and the team defines how they would like to structure this.
I’m pretty sure you can now use AI as well to document the changes you have made within your PR, based on the code that’s present within the Pull Request.
Comprehensive Test Automation that specifies the expected behaviour of the system
There are many ways to dice this, but usually I like to follow the Test Pyramid/ Testing Trophy pattern for automating tests. Having lots of tests, which checks for various combinations at that unit level, checking the BUSINESS logic really helps in that sense. TDD is a helpful pattern to follow as you write your tests describing the behaviour of the system and how you would like your code to perform the business logic you’ve described.
Our Integration and E2E tests then check for the integration between various components of the system. This is very simplified view, that I have described here and there are a lot more different tests that you can add which can be beneficial (contract testing, UI Component testing etc.) but I won’t go into too much detail as that could be a blog post in itself.
Code Coverage for unit tests can then be measured. It’s not a guarantee that close to 100% code coverage by tests mean that your code is bug free. If you have bad tests just to increase your code coverage, you’ll still have bugs. But the number does give you a good idea on how much focus the team gives to writing tests at that unit level.
Measuring feature coverage, is a whole different ball game, and is probably something that’s futile to measure. The way I’ve done it in the past is listing all the features and see where we have test coverage for this at the different layers (unit, integration, e2e) but this is always hard and there will always be something that slips through the cracks.
Automatic Code Linting, Formatting & Checks
How many times have you been part of teams, where developers have different styles of coding or have particular ways of solving coding problems. As a recent example to just make API calls within a NodeJS program, the team used fetch, axios and I think Kai was the third one. We certainly don’t want to stifle creativity, as writing code is an art, but again as mentioned above it would be good to have some standards.
Using linters and prettier (code formatters) is a good way to get this done. You can go a step further and added static security and code analysis as well. Certain environments allow you to perform performance profiling on your code too, if performance of code is a key metric you need to measure. All of this setup with git pre hooks makes for a great way to ensure you don’t commit code upstream without passing the necessary checks (say committing secrets into your repository for example)
Pair Programming
Sometimes using PRs to review code is not the ideal solution, especially if it’s a big feature that you are working on. Pair Programming has been a great tool for me especially in my early days. Now I use AI quite a bit , where AI is more or less the driver while me being the observer and questioning if the solution provided meets the requirements I have specified.
What are other code quality practices you within your team have implemented to help improve the quality of your code? Would love to hear about ideas that I might have missed while writing this blog.