Code is Science is back: the journal code policy tracker now covers 24 journals.See the tracker

Good practices and good quality code

You do not need to become a software engineer to write research code other people can trust. You need a handful of habits, a few good references, and a place to put the code when the paper is done.

PracticeBy the Code is Science editorsJan 20, 20186 min read
Key takeaways
  • Version control, small functions and a README cover most of the distance between a private script and shareable code.
  • Two papers, Best Practices for Scientific Computing (2014) and Good Enough Practices in Scientific Computing (2017), are the best starting points.
  • Host code where people work on it, then archive a frozen copy somewhere built to last, with a persistent identifier.

Most research code is written by people who were trained to do science, not to build software. That is fine. Nobody expects a postdoc to ship production systems. But the results in a paper are only as solid as the code that produced them, and code that nobody else can read, run or check is a weak link in the chain of evidence.

The good news: the gap between "works on my laptop" and "good enough to share" is smaller than it looks. It is mostly habits, not talent.

What counts as good quality code in research?

Forget elegance for a moment. For research, good code has three properties:

  • Someone else can run it. They know what to install, what data goes in and what comes out.
  • Someone else can read it. Names mean something, steps are separated, and the odd decisions are explained.
  • You can tell when it breaks. There is at least some check that the numbers are still the numbers you expect.

Everything below serves one of those three goals.

Six habits that do most of the work

1. Put everything under version control

Use Git from day one, even if you are the only person on the project. It gives you a history of every change, a safe way to try ideas, and an easy path to sharing later. Commit small, commit often, and write messages your future self will understand.

2. Write functions, not copies

If you have pasted the same block of code three times with one value changed, turn it into a function. Fewer copies means fewer places for a bug to hide, and a single place to fix it.

3. Separate raw data, code and results

Keep raw data read only. Keep scripts in their own folder. Write results to a separate output folder that can be deleted and regenerated. If you cannot regenerate a figure from raw data by running your code, you have a manual step that nobody else can repeat.

4. Record your dependencies

Write down which language version and which packages you used. A plain requirements.txt, an environment.yml or an R lockfile is enough to start. Without this, your code may run today and fail in a year for reasons that have nothing to do with your science.

5. Test the parts that matter

You do not need full coverage. Start with the functions that do the actual science: unit conversions, statistical transforms, anything where a sign error would change a conclusion. A test can be as simple as checking a known input against a known output.

def celsius_to_kelvin(c):
    return c + 273.15

def test_celsius_to_kelvin():
    assert celsius_to_kelvin(0) == 273.15
    assert abs(celsius_to_kelvin(-273.15)) < 1e-9

6. Write a README before you need one

Three short sections go a long way: what this code does, how to install and run it, and how to cite it. Update it as the project changes. A README written on submission day is usually missing the one step that only you remember.

Where can I learn this properly?

You do not have to figure it out alone. Some of the best material is free and written specifically for researchers.

  • Software Carpentry runs short, hands-on workshops and publishes open lessons on the Unix shell, Git, Python and R for researchers. Their lessons are a good self-study path even if you never attend a workshop.
  • Best Practices for Scientific Computing by Wilson et al., PLOS Biology, 2014, lays out a set of practices drawn from software engineering and adapted for science.
  • Good Enough Practices in Scientific Computing by Wilson et al., PLOS Computational Biology, 2017, is the friendlier follow up. It focuses on what most researchers can realistically adopt, covering data management, project organization, collaboration and manuscripts as well as code.

If you only read one, read the 2017 paper. It is written for people who are busy, and it says so.

Where should I host my code?

Hosting and archiving are different jobs. A hosting platform is where code lives while people work on it. An archive is where a fixed version is kept so a paper can point to it for decades.

For hosting, a public Git platform such as GitHub or GitLab is the default. It gives you issue tracking, a place for collaborators to suggest changes, and a familiar interface for anyone who wants to read your code.

For archiving and citation, look at services built for long term storage:

  • Zenodo, run by CERN, accepts software and data and issues DOIs. It can archive a GitHub repository automatically each time you make a release.
  • Figshare hosts research outputs of many kinds, including code, and issues DOIs.
  • OSF, the Open Science Framework, lets you keep code, data, preregistrations and documents together in one project, and connect to storage you already use.
  • Software Heritage archives publicly available source code at scale, with its own intrinsic identifiers for exact versions.

The usual pattern is simple: develop in a public repository, then deposit a tagged release in an archive and cite that version in the paper.

What if my code is messy?

Share it anyway. Messy code that exists is more useful than clean code that does not. A reader who wants to check your analysis would rather have your actual script than a description of it. Add a short note in the README saying what state the code is in and what it was used for. That honesty is more valuable than a polish you do not have time for.

The habits above are not a gate you must pass before sharing. They are a direction. Each one makes the next project a little easier, and each one makes your work a little more checkable.

Start with one change

Pick the habit that would have saved you the most pain on your last project. For most people that is version control or a README. Do that one well for a month, then add the next. Good research code is built the same way good research is: incrementally, with a record of what changed.

Questions

Do I need to learn software engineering to share research code?

No. A few habits, such as version control, a README, recorded dependencies and a few tests, cover most of what makes code shareable. The Good Enough Practices paper is written exactly for this situation.

Is GitHub enough to preserve my code?

GitHub is a good place to develop and share code, but it is not an archive. Deposit a tagged release in a service like Zenodo or Software Heritage so the version cited in your paper stays available.

What should go in a README for research code?

At minimum: what the code does, how to install and run it, what data it expects, and how to cite it. A short note on the state of the code and the paper it supports is also helpful.

Keep reading. More from the desk.