scieee AI-readable full text Open interactive document viewer

Some Tips on Modernizing Legacy Software

Koufos, Alexander

Abstract

Legacy codebases often pose considerable challenges, including a scarcity of tests, monolithic architecture, inadequate documentation, and a lack of standardized development practices. These obstacles typically arise from the absence of formal testing, complicating efforts to maintain and update the code for compatibility with newer hardware and software. Consequently, writing unit tests often necessitates refactoring the code, which involves restructuring it without compromising its original functionality. However, this raises a critical question: How can one refactor without having tests in place to verify functionality? This poster will explore the incorporation of software better practices, with a particular emphasis on testing, to facilitate the modernization of legacy codebases. By adopting a structured approach to testing, our aim is to enhance the reliability and maintainability of the code while preserving the current functionality and stability of software that produces science-ready data. The discussions will focus on practical strategies for implementing testing frameworks, establishing a culture of continuous integration, and ensuring that updates do not disrupt the production of critical scientific outputs. Through these efforts, we can create a more robust and adaptable codebase that meets the demands of modern scientific research.

Full text

Some Tips on Modernizing Legacy Software Alex Koufos (he/him)1 1Stanford University & Joint Science Operations Center Overview Legacy codebases often pose considerable challenges, including a scarcity of tests, monolithic architecture, inadequate documentation, and a lack of standardized development practices. These obstacles typically arise from the absence of formal testing, complicating efforts to maintain and update the code for compatibility with newer hardware and software. Consequently, writing unit tests often necessitates refactoring the code, which involves restructuring it without compromising its original functionality. However, this raises a critical question: How can one refactor without having tests in place to verify functionality? This poster will explore the incorporation of software better practices, with a particular emphasis on testing, to facilitate the modernization of legacy codebases. By adopting a structured approach to testing, our aim is to enhance the reliability and maintainability of the code while preserving the current functionality and stability of software that produces science-ready data. The discussions will focus on practical strategies for implementing testing frameworks, establishing a culture of continuous integration, and ensuring that updates do not disrupt the production of critical scientific outputs. Through these efforts, we can create a more robust and adaptable codebase that meets the demands of modern scientific research. Why Good Research Requires Better Software Practices What Makes Good Research? According to The National Academies of Sciences, Engineering, and Medicine, reproducibility (i.e. computational reproducibility) is defined “as obtaining consistent computational results using the same input data, computational steps, methods, code, and conditions of analysis”8. Reproducibility is the cornerstone of reliable research, and most research cannot be done without software. Thus, better software practices are even more important in today’s research environment. A Failure to Reproduce? Figure 1 shows researchers ability to reproduce results within their fields. In all research communities, researchers struggled to reproduce the results of others, and even themselves. Figure 1. Failure to Reproduce Published Results (Baker, M. 2016)1. Higher values represent a greater failure in reproducing experiments. In most fields, researchers have been unable to reproduce ≈50% of their own work! Modernization of Legacy Code Version Control & Simple Workflow Initialize a Git repo (if missing); enforce a feature-branch → PR model Require at least one passing test before merging Tag releases that correspond to reproduced scientific results Perform Code Reviews Review every change for style, test adequacy, and documentation updates Use checklists: “Is there a test?”, “Did we update docs?”, “Did we preserve behavior?” Incremental Documentation Document why a module exists, not just what it does Store docs alongside code (Markdown in docs/ or docstrings) Link test cases to the corresponding documentation sections Leverage Existing Manual Tests Harvest scripts, example runs, or ”known to be correct” output files Convert them into automated regression tests (e.g. pytest fixtures) Compare new runs against baseline results across OSes, compilers, and hardware Establish a Testing Framework Unit tests for pure functions (aim ≥70% coverage) Integration tests that stitch modules together (use historic input/output pairs) System/acceptance tests that validate end�to�end scientific results Continuous Integration (CI) Pipeline Automate linting, unit-test execution, and cross-platform builds on each push Decide when it’s bet to run the full integration suite on representative datasets Visual dashboards (GitHub Actions, GitLab CI, Jenkins) keep the team aware of breakages Map & Modularize Identify functional “chunks” and their dependencies Sketch a dependency graph; look for natural separation points Refactor incrementally: extract a module → write tests → lock behavior Reproducibility Checks Pick a published result, re�run it on the refactored code, and capture the output Treat the reproduced result as a golden integration test Reference the “Improving reproducibility through better software practices” tutorial for concrete steps Useful Links and References [1] M. Baker. 1,500 scientists lift the lid on reproducibility. Nature, 533:452–454, 2016. doi: 10.1038/533452a. [2] Better Scientific Software (BSSw). Testing Resources. https://bssw.io/items?topic=testing, 2024. [3] N. U. Eisty, D. E. Bernholdt, A. Koufos, D. J. Luet, and M. Mundt. Ten essential guidelines for building high-quality research software, 2025. URL https://arxiv.org/abs/2507.16166. [4] GitKraken. GitKraken - Git Flow Page. https://www.gitkraken.com/learn/git/git-flow#github-flow, 2022. [5] Intersect - Research Software Engineer Training. Testing Lesson. https://intersect-training.org/testing-lesson/, 2022. [6] A. Koufos. Software Best Practices for Reproducible Open Science. Apr. 2024. doi: 10.5281/zenodo.10994996. [7] A. Koufos, M. Mundt, and N. Eisty. Software Testing Practices for Reproducible Open Science. Dec. 2024. doi: 10.5281/zenodo.14291633. [8] C. on Reproducibility and Replicability in Science. Reproducibility and Replicability in Science. National Academies Press, 2019. ISBN 978-0-309-48616-3. doi: 10.17226/25303. [9] Stack Overflow. Stack Overflow Survey. https://survey.stackoverflow.co/2022/#version-control-version-control-system-prof, 2022. [10] US-RSE. United States Research Software Association (US-RSE). https://us-rse.org, 2017. Practical Tips & Common Pitfalls Tip Why It Matters Avoid massive style changes while refactoring • Style changes can mask regressions • Keeps the focus on functional correctness Introduce a linter early (e.g., ruff, clang-format) • Enforces a consistent style without manual effort • Reduces cognitive load for reviewers Remove dead code before adding tests; if possible, run static analysis • Shrinks the surface area that needs testing • Helps with readability of the codebase Use disposable branches; merge into main ⇐⇒ all tests pass • Allows bold architectural changes • Limits risk to the stable/release version of the software Document “known-issues” alongside fixes • Future contributors see the rationale behind workarounds • Improves onboarding speed Cross-platform CI • Guarantees portability for scientific pipelines • Increases ability for reproducibility of results Take the First Step Today Start small: pick one module, write a single unit test, and commit the change. Make testing visible: add a badge (“Tests X85%”) to the repository README. Share success: present a short demo at your next lab meeting—show how a failing test caught a regression. Iterate: repeat the cycle, gradually expanding coverage and modularity. Bottom line Even modest, test-driven refactoring yields measurable confidence gains, faster onboarding, and reproducible science. Acknowledgments RSE work supported by the NASA Contract NAS5-02139 (SDO/HMI) and NASA Cooperative Agreement 80NSSC22M0162 (COFFIES DRIVE Science Center). I would also to acknowledge the United States Research Software EngineerAssociation (US-RSE)10 for supporting research software engineering and RSEs more broadly. A special thanks to Schmidt Sciences for funding many, including myself, to attend the USRSE’25 Conference. Lastly, I’d like to thank Nasir Eisty, Miranda Mundt, David Luet, and David Bernholdt for conversations around better practices with some conversations about legacy software for our paper on arXiv3. Check out the digital version of this poster from our Zenodo collection of USRSE’25 papers and posters! Alex Koufos: akouf[email protected]ord.edu US-RSE’25 Github: exoticdft