How do you use static analysis to improve the quality of your research software?
Description
Static analysis is the automated examination of your source code without executing it. Tools in this category detect bugs, enforce coding standards, check types, and flag security vulnerabilities before your code runs. For research software, where correctness directly affects the validity of your results, catching these issues early is worth the modest setup effort. It does not replace testing or code review — a clean run means only that your code conforms to the rules you configured.
Considerations
- Linting, type checking, and security scanning are distinct levels — a basic linter alone adds real value, and for many research scripts it is sufficient.
- Adopting static analysis on an established codebase will surface many pre-existing warnings, so use the baseline or ignore-file mechanism most tools provide to address them incrementally.
- Tool ecosystems vary by language: Python and R are well served, while Fortran and Julia options are more limited and less stable.
- Code generated with AI assistance has the same quality needs as hand-written code, so put it through the same checks.
Solutions
You need the relevant language runtime and package manager, plus a service such as GitHub Actions or GitLab CI for the CI step.
- Decide what you want static analysis to do — style, bug detection, type checking, or a combination — as this shapes your tool choice.
- Choose a tool for your language and goals, verifying it is still actively maintained — the ecosystem moves quickly:
- Run the tool with default configuration to get a starting point — for Python with ruff:
ruff check . - Agree what your team will enforce and how suppressions are handled — a rule you routinely suppress has stopped being useful — and document the configuration.
- Run the tool in CI on every push or pull request as a pass/fail check.
- Add a pre-commit hook with precommit for faster local feedback.
- Skip throwaway scripts and purely exploratory notebooks, where setup overhead outweighs the benefit — reconsider for notebooks that others will run or that form part of a reproducible pipeline.
Further Reading
- Ruff documentation — Covers installation, configuration, rule selection, and editor and CI integration, making it a practical starting point for introducing static analysis to a Python project.
- pre-commit documentation — Explains how to manage code quality hooks that run locally before commits, useful for teams wanting consistent tool runs across contributors and languages.
- mypy documentation — Shows how to add type annotations incrementally and interpret type errors, worth reading once basic linting is in place and you want stronger correctness guarantees.
- Research Software Engineering with Python — A freely available book on software engineering practices for researchers, useful context for where static analysis fits within a broader quality practice.
- Software Engineering at Google — Chapter 26 covers static analysis at scale — false positive rates, developer trust, and rollout — and maps directly onto introducing tools to an established project.
AI Disclosure
This work was produced with the assistance of Claude Fable 5, under the strict editorial control and factual verification of the human author.
Related pages
Training
Tools and resources on this page
| Tool or resource | Description | Related pages |
|---|---|---|
|
Aqua.jl |
Aqua.jl (Auto QUality Assurance for Julia packages) provides automated quality checks for Julia packages, including ambiguity detection, unbound type parameters, and stale dependency checks. | |
|
Bandit View on TechRadar |
Bandit is a tool designed to find common security issues in Python code. | Improving research sof... |
|
clang-tidy |
clang-tidy is a clang-based C++ linter tool providing an extensible framework for diagnosing and fixing typical programming errors, style violations, and interface misuse. | |
|
cppcheck |
cppcheck is a static analysis tool for C and C++ code that detects bugs, undefined behaviour, and dangerous coding constructs without requiring the code to compile. | |
|
JET.jl |
JET.jl is a Julia package that uses Julia's type inference to detect potential errors and type instabilities in code without executing it, functioning as a static analyser for Julia programs. | |
|
lintr |
lintr is a static analysis tool for R code that checks for style errors, syntax errors, and possible semantic issues, helping to enforce consistent coding standards across R projects and it integrates with common R development environments. | Maintaining research s... |
|
mypy View on TechRadar |
Mypy is an optional static type checker for Python that aims to combine the benefits of dynamic typing and static typing | Writing readable code |
|
precommit View on TechRadar |
A framework for managing and maintaining multi-language pre-commit hooks | Continuous Integration... |
|
Pyright |
Pyright is a fast type checker for Python, developed by Microsoft, with support for type inference, strict mode, and integration with VS Code and other editors via the Language Server Protocol. | |
|
Ruff View on TechRadar |
An extremely fast Python linter and code formatter written in Rust | Phoenix2 Maintaining research s... |