How are devs coding with AI?

Help us find out-take the survey.

Code Quality Check: How to Perform & Measure It

Code Quality Check: How to Perform & Measure It
Code Quality Check: How to Perform & Measure It

How to Perform the Best Code Quality Check

Ensuring your code meets high-quality standards is essential as your software grows more complex and connected. If you regularly perform systematic code quality checks, you’ll quickly spot security issues, minimize technical debt, and simplify your development workflow.

In this article, we’ll focus on how to check code quality, explore key methods like static and dynamic analysis, and take a look at essential code quality check tools, including powerful AI-based options.

Automation and human eyes in quality checks

When you perform a code quality check, you usually combine automated tools with manual methods. Automated tools, like static and dynamic analysis, quickly provide objective metrics on maintainability, complexity, duplication, and security risks. On the other hand, traditionally manual approaches-including code reviews and pair programming-allow your team to leverage context, experience, and judgment to catch issues automated tools might miss. This is, however, bound to change, with automated and AI tools being developed to handle those tasks as well.

Static vs. dynamic code analysis

Development and infrastructure teams typically employ two types of automated methods for quality checking: static and dynamic analysis. These methods vary fundamentally, but their complementary nature gives a rather broad picture of the overall system’s quality and health, both in design and runtime.

Static Code Analysis:

  • Analyzes code before it’s executed or even compiled.
    Examples: Identifies code with high complexity (cyclomatic complexity or deep inheritance).
  • Identifies security vulnerabilities.
    Examples: SQL injection risks due to poor input sanitization and buffer overflow risks can be seen already at the source code level.
  • Reveals maintainability issues.
    Examples: Identifies deviation from naming or styling conventions or duplicated logic.

Dynamic Code Analysis:

  • Analyzes software performance as it’s running on a live environment.
    Example: Identifying memory or other resource leaks at runtime through profiling or monitoring.
  • Identifies runtime errors and performance bottlenecks.
    Example: Checking resource usage with cluster monitoring tools, executed code paths with distributed telemetry, or response times during stress testing.
  • Reveals runtime security vulnerabilities.
    Example: Penetration testing or security auditing on a live application, either by attacking API endpoints or trying to find vulnerabilities in client-side software (in-browser client code).

Typically, those two types of analysis cover a lot of ground when it comes to truly knowing and characterizing your software. In order, however, to truly “know” and benchmark software in a meaningful way, you have to go a step further than “go/no go” and extract metrics that can point maintainers and developers toward the right path. So, which are the most useful metrics to keep track of?

Essential metrics for code quality

There are tons of metrics that can be defined on your processes and software – some of those stem from the domain and others from widely known software principles. For an effective code quality check, you’ll need objective, quantifiable, and ideally automated metrics. Meanwhile, software researchers are actively researching the potential of intelligent code analysis as a natural extension of static, rule-based analysis.

Here are some key metrics that you can consider calculating for your repos or codebases:

Cyclomatic Complexity:

Measures the complexity of your logic and indicates how easily (or not) your code can be understood and maintained.

Ideal range: under 10.

Maintainability Index:

Evaluates how easy your code is to update or extend. Higher scores mean simpler maintenance.

Ideal range: above 65/100.

Code Coverage (%):

Shows the percentage of your code executed by automated tests. Essential for reliability and reducing bugs.

Recommended: above 80%

Code Duplication (%):

Highlights redundant logic scattered throughout your project, directly affecting maintainability and scalability. Modern tools can also highlight “near” duplication.

Ideal range: Varies – usually, more duplication is tolerated in test code.

Security Vulnerability Scores (CVSS):

Standard scoring for software vulnerabilities, pinpointing security risks.

Goal: Aim for low severity (under 4.0) by regularly addressing vulnerabilities.

Code Churn:

Indicates frequent code rewrites or instability, revealing potential problem areas that might need refactoring.

Recommended: Lower values indicate stability.

Tools for Code Quality

The question, of course, arises: How do I calculate those metrics as often as needed, and what’s the scope to which I should apply them? Obviously, manual calculation is more of an exercise than a solution – that’s why many tools exist that aim to do this for you. You can start with your IDE – IntelliJ and Visual Studio are just some of the IDEs that offer built-in or plugin-based functionality for code quality monitoring.

The issue with this approach is that it’s innately too close to the developer and not as easily observable by peers or managers, which could potentially create silos or lead to “supposedly” optimized code finding its way to production.

For this reason, many tools have existed for years that offer a more “integrated” version of code quality, hooking into version control platforms like GitLab and allowing for a broader overview of a codebase’s quality among team members.

Here’s a list of tooling organized per language, as well as a list of more general purpose or language-agnostic tools and style guides that can help orient you when starting out on measuring the quality of your code:

Tools with multilanguage support:

  • SonarQube: Supports Java, C#, JavaScript, TypeScript, Python, C++, Go, Rust, and more.
  • Codacy: Covers Java, JavaScript, TypeScript, C#, Python, Go, and others.
  • Coverity: Static analysis for Java, JavaScript, C/C++, C#, and more.
  • Qodo (formerly Codium): AI-driven code review and quality checks; language-agnostic.
  • DeepSource: Covers JavaScript, Python, Go, Java, Rust, and more.

An example in Python

Here’s a simple example in Python showing how some of the tools above react to a particular piece of suboptimal code:

def calculate(x,y,operator):
  if operator == "+":
    return x+y
  elif operator == "-":
    return x-y
  elif operator == "*":
    return x*y
  elif operator == "/":
    return x/y

print("Calculation result:", calculate(10, 0, '/'))

Pylint output:

calc.py:1:0: C0114: Missing module docstring (missing-module-docstring)
calc.py:1:0: C0103: Argument name "x" doesn't conform to snake_case naming style (invalid-name)
calc.py:1:0: C0103: Argument name "y" doesn't conform to snake_case naming style (invalid-name)
calc.py:1:0: C0103: Argument name "operator" doesn't conform to snake_case naming style (invalid-name)
calc.py:2:2: C0326: Exactly one space required after comma (bad-whitespace)
calc.py:2:0: C0116: Missing function or method docstring (missing-function-docstring)
calc.py:9:6: W1514: Using open without explicitly specifying an encoding (unspecified-encoding)
calc.py:7:10: W0702: No exception type(s) specified (bare-except)
calc.py:7:10: W0104: Statement seems to have no effect (pointless-statement)
calc.py:7:10: R1710: Either all return statements in a function should return an expression, or none of them should. (inconsistent-return-statements)
Your code has been rated at 1.25/10

You can see the full list of Pylint messages here.

Flake8 output:

calc.py:1:17: E231 missing whitespace after ','
calc.py:9:1: E305 expected 2 blank lines after function or class definition, found 1

And bandit:

[bandit] No issues identified.

You can immediately see that there can be different levels of verbosity and output style. While these tools can be configured to a great extent, the consumers of their outputs traditionally tend to be human. In the future, we may see enterprises accelerating this tedious step by configuring an LLM to reparse the outputs of tools and create concise summaries or annotations or even automated reviews of PRs.

FAQ

How do static and dynamic code analysis differ in assessing code quality?

Static analysis examines your source code without executing it, detecting complexity, duplication, maintainability issues, and security flaws. Dynamic analysis evaluates software as it is being executed, identifying bottlenecks, runtime errors, and other issues that might emerge only in live environments.

Why do we measure code quality?

Measuring code quality creates an impartial “stick-in-the-ground” point on which developers can improve. It guides and quantifies improvement but also enforces consistency, reduces technical debt, and helps keep the software robust.

Can AI-powered tools help improve code quality checks?

Recent research is heavily focused on utilizing reasoning models to guide software quality. AI tools can provide intelligent suggestions, automate refactoring, and offer near-real-time feedback, complementing static and dynamic analysis methods.

How do you get the code quality score?

Automated tools such as SonarQube or Codacy evaluate factors such as complexity, duplication, coverage, and a variety of other configurable options and condense their findings into one or multiple scores to help guide improvement.

Conclusion

Regular code quality checks should be considered and practiced in any organization building software at scale. Essential for robustness and security, engineers and product owners have long been measuring and integrating into their workflow measures of code quality. In an ideal scenario, “keeping the lights on” and constantly devoting a fraction of the overall engineering effort toward improvement and refactoring is the proper way to avoid code rot, scrounging, and technical debt from piling up. Tooling exists for almost every language, and contextualizable LLM solutions appear to be strong contenders in distilling information about the code and providing feedback in a more timely and insightful way.

Start to test, review and generate high quality code

Get Started

More from our blog