Originally written by Maciej Król
Building a software development project is a bit like a game of Jenga.
All elements create one perfect tower. Usually, it might be tweaked and worked on with no consequences. But if it has even one vulnerable place, a wrong move might ruin all the hard work.
Okay, so it’s not a perfect analogy. A software program requires much more work than a pile of wooden blocks and we don’t necessarily strip it of its parts, but rather add the next ones.
However, the “poke one and all will fall” metaphor still stands. If your project has any weak points, they might doom the entire construction.
It doesn’t matter how well written the rest of your code is if that one tool you used is outdated and might cause serious security breaches. And the more sensitive data your product is dealing with, the more careful you have to be.
A code audit is vital to ensure your product is of good quality, secure, and ready to launch.
In this article, you will find a detailed guide on what a code audit is, why you need it and how to perform it, step by step. As a Python-centered software house, we decided to focus on how to run an audit of Python-based code. However, you will find some of the tips and guidelines relevant regardless of your technology choice.
We will also provide you with a checklist and a sample report from an audit so that you can see what a well-prepared, comprehensive auditing process looks like. The exemplary audit is over 20 pages long and will serve as a fantastic point of reference for your future work! Download the checklist and report in PDF format below.
With our guide, you will be able to run a Python code audit yourself, and learn what you should expect from one.
Read on!
What is a code audit?
“Code audit is a comprehensive analysis of source code in a programming project with the intent of discovering bugs, security breaches or violations of programming conventions,” according to Wikipedia. I know that quoting Wikipedia in an article is like quoting Merriam-Webster during a wedding speech—but this time they got it so right that they deserve credit!
The intention of every code audit is ensuring that a given program is:
- secure,
- devoid of bugs and defects,
- easy to maintain and be further worked with,
- up to date with the current standards,
- in line with coding best practices.
Skip any of these, and you’re sacrificing the quality and security of your code, which may—and most probably will—have disastrous consequences. Poor documentation and tech debt might slow down or even halt your project; bugs and security breaches might cost you clients, reputation, and good user ratings. And that’s just the start.
With a code audit, you’ll be sure your code is secure, bug-free and ready for handover.
Code audit vs. code review
After reading the section above, you might think: okay, but everything you’ve just described can be achieved with the help of a code review, and we run these regularly!
It’s true that the terms might sometimes be used interchangeably, but there are a few subtle differences between them.
Code review is contained within one team—the developers review each other's code, and they focus only on one specific part.
A code audit, on the other hand, always concerns the whole project and is performed by a person outside of the team—be it other developers, or even an outside company.
While code reviews are useful and necessary, performing a code audit every once in a while makes a tremendous difference. Let me use another metaphor here: reviews are like checking different parts of your car for potential malfunctions. Of course, it’s necessary to see if the headlights operate correctly, if both wipers are fine, and if your brakes do their job… But unless you start the car, take a drive, and assess how everything works together, you won’t know how good the whole machine actually is.
As the unwritten rule goes, the more people see your code, the better. And the more you fix, the more faultlessly the project will perform in the long run.
When can you benefit from a code audit?
You might find yourself in need of running a code audit on many different stages of development and different situations:
Before introducing your product to the market, to make extra sure the quality is impeccable and you won’t wake up the next day seeing a bunch of one-star reviews;
After inheriting legacy code, to help you plan your future work and assess the scope, cost and time-frame of the project;
Before you invest in a project, to verify whether it’s a good bet;
Whenever you feel your product is suboptimal. Perhaps the app’s lagging, or there are a few too many bugs to ignore? It’s never too late to check the code and apply changes.
The benefits of a code audit
A code audit serves many different purposes. They all depend on where you stand.
From a developers’ point of view, you get the following advantages:
As mentioned above, the more people see your code, the better. If your product has undergone a comprehensive check-up, chances are any potential bugs and vulnerabilities will be found pre-release and you can fix them stress-free. Not to mention it will help you sleep soundly knowing that all the tools are up to date and following the maximum security protocol.
It’s extremely rare that the very same team of developers works on the same product from start to finish. Coworkers might change, sometimes an outsourced team or two might join the efforts, and the total number of developers might be scaled up or down. Additionally, every part of the source code is written by different people with different skills and competences.
That’s why it’s advisable to perform an audit each time you get source code that you haven’t worked with before (for example, we usually run an internal audit on the code we receive from a client before we start working on it). It will help you assess the scope of your work, the general quality, and maintainability.
- An audit will help you avoid technical debt. Trust me, “that’s a problem for future me” is not a good approach when it comes to software development.
As a team leader, you’ll find that:
- Performing a code audit yourself or at least participating in it will give you an overview of the whole project. Usually, team leaders don’t see the code on a daily basis, so an audit will help them get acquainted with the present state of the project, its structure, and its functionalities.
And from a strictly business perspective, you get the following advantages:
An audit helps prove that your program is ready to be launched and introduced to your clients and customers. Malfunctions or security breaches might potentially cost you a lot of money—and your reputation.
An up-to-date, fresh and technologically relevant project is more attractive for developers. High-quality code will attract high-quality talents!
Audited code helps simplify and streamline the development process, which in turn means work can progress faster with fewer blockers.
Python code audit—step-by-step guide + checklist
In this section, we will introduce a step-by-step process of how to run a Python code audit.
Each subsection details the crucial elements of the code audit. It will give you an idea of how to structure the document.
We also included tips on how to ensure you follow the best possible practices from the very beginning. You can apply them even before the audit!
To see what the end result should look like, consult our example provided in the free PDF below. It’s over 20 pages long and based on a real-life code audit we performed.
Let’s get started!
1. Code repository
In the beginning, it’s important to check for a version control system that tracks and provides changes to the source (like GIT, for example). Verify if it’s well-maintained.
TIP: Consider working according to the Gitflow Workflow, which “dictates what kind of branches to set up and how to merge them together.” Pay attention to the right names of the branches. If your product is particularly vast, consider using appropriate Git tags. It makes managing a larger project infinitely easier.
2. Software architecture
a) Technology choices
The point of this section is to verify if the tech stack is the optimal choice for the project and if it’s internally compatible.
When you start verifying the technology choices, the first step should be to check if all applications used are named according to the LTS version and if they are up-to-date.
Then, it’s time to judge if all the components are well-tested and if they fit each other.
What does it mean in practice? For example, Django apps go together with Postgres much more often than with other database engines, like MySQL. While the less popular choices are not necessarily technologically weaker, opting for them will drastically reduce your opportunities to find help with any potential problems.
Such aspects are important to be taken into account in order to assess the sustainability of the project.
b) Deployment configuration
It’s always worth checking which services are used to support the application. You should pay attention to the software providing hosting services (uwsgi, gunicorn, nginx) and the hosting method (whether it’s cloud or local).
TIP: There is no clear answer which methods are right—each hosting type has its advantages and disadvantages. Everything depends on the type of project you’re working with.
However, I sincerely recommend cloud hosting. It will not only help you save money (no need to care about the hardware, less maintenance, increased productivity), but you also gain much higher availability of the app. Most cloud providers offer over 99,99%!
The next step is to verify whether the application contains files which are responsible for the virtualization of the project.
TIP: I highly advise using Docker. It allows solving a lot of potential problems and bugs during the development stage, as the development version functions in an environment identical to the product version.
Then, it’s time to check whether the README file contains all the necessary elements:
instructions for configuration,
instructions for installation,
a user’s manual,
a manifest file (with an attached list of files),
information on copyrights and licenses,
contact details for the distributors and developers,
known bugs and malfunctions,
problem solving section,
a changelog (for developers).
While revising your project catalog, you should check if it includes files responsible for continuous integration and deployment (CI/CD).
TIP: Well-constructed CI/CD pipelines can greatly benefit your project. They allow for a more effective way of building the program, but they also include scripts responsible for testing the application and verifying its validity during code-building.
Check the project configuration and verify if it doesn’t contain any passwords that a third person could find.
TIP: It’s advisable to keep all logins and passwords necessary to run the application in environment variables—whether in a machine on which the application runs or in the tool responsible for CI/CD.
Check if there’s an Error Tracking System in place. One of the most popular ones is Sentry.
3. Coding best practices
This section will look differently depending on the programming language and the packages/libs you use.
With Python, you need to check carefully whether the code is compliant with the PEP 8 style guide and the PEP 257 docstring conventions.
The good news is, you don’t have to do it all manually. There are tools that might help you along the way.
a) Linters
b) Other standalone tools
Pylint—a source code, bug and quality checker for Python;
PyFlakes—another bug checker (it only checks for logical errors, not for style, but it works faster);
Pycodestyle—checks Python code against the style conventions in PEP 8;
Pydocstyle—checks compliance with Python docstring conventions;
Bandit—finds common security issues in Python code;
MyPy—static type checker for Python.
c) Code analysis and formatting tools
Mccabe—a Python complexity checker;
Radon—a Python tool that computes various metrics from the source code;
Black—a Python code formatter;
Isort—a Python utility/library to sort imports;
Yapf—a Python formatter.
Even though the tools can greatly automate and speed up your work, it’s still worth it to analyze the code manually in order to find any potential:
bugs,
bottlenecks,
performance issues,
security vulnerabilities,
dangers connected with maintaining the application.
4. Tips for the future: how to ensure the quality of your code
Code audits can help improve your code and get rid of any existing issues.
But if upon running the code audit the list of things to improve feels too long, try getting familiar with a few good practices. While not all of them may be applied in every single team, here are a few that are worth taking into consideration:
Every piece of code should be reviewed by at least two developers;
Use githooks;
Decide on one specific formatter configuration for the whole team;
Share your knowledge! Both when it comes to technologies that you are proficient in and when it comes to tasks that you solved—it helps the team to adopt the same good practices;
Consider asking the team members to use the same code editor—it will help with standardization.
Final thoughts
We hope our guide on how to run a code audit will help you perform one on your own, or assess what a good audit document should look like.
If you want to get to work, we recommend you download our PDF—it consists of a checklist and a real-life audit example for reference.
And if you want to find out more about how to ensure the better quality of your code, why not check out the following articles:
Top comments (0)