DEV Community

Alex Omeyer
Alex Omeyer

Posted on • Updated on • Originally published at stepsize.com

The Engineer’s Guide to Writing Meaningful Code Comments

“What on earth does this do?”
“Why wasn’t this a ticket?”

Been there? If you’re anything like most engineers, it’s safe to say this happens to you a lot.

The most obvious and immediate benefit of writing good comments is that they make code easier for others to understand.

But when we nail our code commenting best practices (which include when to and when not to write comments), we can unlock even more impactful, long-lasting benefits like:

  • improved engineering velocity
  • better code quality
  • managing and reducing technical debt

On the other hand, when we don’t embrace good practices, code comments can have the opposite effect. After all, code comments are an unstructured way of storing information. They’re not easily searchable or visible beyond looking at the code. This makes them a poor alternative for proper documentation or issue tracking. Combined with the code quality nosedive and velocity issues they cause, poor commenting leads to mounting problems, from huge learning curves for new engineers to invisible backlogs of tech debt.

In this complete guide, we’ll:

  • Explain what types of comments there are
  • Discuss when and how to write code comments
  • Cover some code commenting best practices
  • Talk about when not to write them (and what to do instead!)
  • Types of comments (and when to use them)
  • Should we be using comments at all?

Some say that if a piece of code is written well, we can do away with comments altogether because that code’s purpose will be obvious. As John Ousterhout says, this is a delicious myth.

Comments can indeed be used to plaster over poor or unclear code. But the bottom line is that various kinds of information simply can’t be represented in code.

Two types of comments

1. Contextual comments

Contextual comments are used to describe any purpose, intent or feature of code that isn’t obvious by looking at it. There are two primary types of contextual comments.

Module-level comments. These describe the purpose of classes, functions and methods.

These comments might include…

  • The parameters a function accepts
  • The output it generates
  • Any features of the module which can’t be understood at a glance

Logic comments. These explain code in context, wherever they are needed.

We should use them sparingly. The last thing your team needs are comments that explain things which are already obvious by glancing at the code!

Code comments be like...

Well-placed comments save development time and prevent engineers from misunderstanding the purpose or context of a code snippet. When we misunderstand code, it’s possible to introduce inefficiency, unnecessary complexity and bugs. These harm code quality and velocity, particularly when it happens routinely.

✅ When to use them:

  • Where there’s unavoidable complexity in your code
  • To add details to increase precision, such as units, inclusivity and exclusivity or the treatment of null values
  • When context is missing, for example, using code from another repo or a package

For example, it’s unclear whether the start and an end parameters are inclusive or exclusive. A comment would save readers from working it out.

Fewer comments often mean more readable code. If somebody sees a comment, they’ll know it’s incisive and valuable.

❌When to avoid them:

  • When the intent of the function is obvious
  • In libraries or APIs
  • When it ought to be ticketed as an issue. (This is how teams get themselves buried under heaps of tech debt without even knowing it.)

Here’s an important point – if engineers are writing tonnes of comments to explain complexity, that could be a code smell.

An engineering practice your team should adopt is consistently documenting unnecessarily complex code as issues. This avoids accumulating serious tech debt that can be hard to pay back. If you’re not already using a tool for this, try Jira or Linear for app-based issue tracking. Or, try Stepsize to track and manage tech debt from your code editor.

2. TODOs/FIXMEs

TODOs and FIXMEs are everywhere. But they come with a substantial cost.

TODOs are a great single-player tool... They are great for temporarily dumping thoughts so you can focus on what you’re doing. TODOs are definitely better than having a list on the side, because they have context.

But a terrible multiplayer tool. When TODOs make it to main, you end up with a never-ending, invisible backlog which isn’t actionable.

These bad comment practices are a direct path to spiralling tech debt and declining code quality.

Tools for converting TODOs and managing tech debt issues

Use TODOs to aid your personal code development process. Never push TODOs to main.

If you have TODOs in your codebase, use Stepsize’s issue management tool to convert them into issues without leaving the IDE. The tool will also surface TODOs in PRs, where you can turn them into issues.

Three best practices for writing code comments

Focus on the why

The best code comments are the ones you don’t need. The best comments can’t be replaced by code.

Check out this example we borrow from Jef Raskin:

/* A binary search turned out to be slower than the Boyer-Moore algorithm for the data sets of interest, thus we have used the more complex, but faster method even though this problem does not at first seem amenable to a string search technique. */

Code should be written as simply as possible. The best comments explain unavoidable complexity. For example, we might add a comment explaining the code's business application or the rationale for choosing a particular algorithm.

*Code tells you how. Comments tell you why. *

Don’t push TODOs. Create issues.

TODOs should only be single-player. TODOs that get pushed result in a never-ending, invisible backlog which isn’t actionable.

If you’re pushing a TODO, you should be creating an issue instead. When leaving TODOs in a codebase is a team-wide habit, it leads to spiralling tech debt.

Use a tool like Stepsize to manage issues without leaving your codebase. Stepsize integrates with platforms like Jira and Linear if you want it to. The VSCode extension is here, and the Jetbrains extension is here. This tool will enable you to:

  • Convert TODOs into issues with a click
  • Flag TODOs and issues in PRs
  • Visualise issues and tech debt in different parts of your codebase
  • Make issue management seamless for engineers
  • Be a tech debt hero!

Convert TODOs with Stepsize

Pick and document conventions

Documenting your conventions helps keep your comments consistent. This forces teams to decide what will be commented, and what the format will be.

You might be programming in a language with a document compilation tool, such as Javadoc for Java, godoc for Go! Or Doxygen for C++. Make use of these – even though they’re not perfect, the structural benefits outweigh the drawbacks.

Choose tools and practices for managing issues that are intuitive for individual engineers, and that delivers value to the team. Are you disallowing TODOs in main or having a policy on how issues are documented? Make sure this is universally understood.

Once good practices become habits across a team, they become an effortless contribution towards shipping faster, better code and managing tech debt properly.

Enshrining your principles pays back dividends when engineers join or leave your team, too.

4. Communicate better.

Shared understanding in software teams isn't all about comments.

Your team is more effective when everybody knows what is happening, without having to trawl through Slack or chase for Jira ticket updates.

I built CollabGPT with my team to help.

CollabGPT by Stepsize – AI for software teams

CollabGPT knows everything that happens in Slack, Jira and GitHub.

It can meaningfully summarise what is going on, answer pressing questions and offers actionable suggestions on what to do next.

CollabGPT has long-term "memory". It's not just a dumb layer between an LLM and your data. It uses a complex network of AI agents to "remember" the context that matters about your projects.

Have a peek at CollabGPT, if you like

Rounding up

Code commenting isn’t just about knowing how to write good comments. It’s also about knowing when not to – and what to do instead.

When we get this right, we don’t just make it easier for others to understand. We:

  • Speed up engineering velocity
  • Improve code quality
  • Boost team morale
  • Manage and fix tech debt

Firstly, when we write good comments, we constantly surface essential information about code features and architecture decisions.

Secondly, when we avoid commenting about code problems and create issues instead, we ensure issues are actionable and visible. This promotes good tech debt management practices, which enable your team to fix tech debt issues.


I'm building CollabGPT with my team. It's the AI companion for software projects with long-term "memory" of your business context and activity.

It integrates with your Jira, Slack and GitHub. Use it to get powerful activity summaries, actionable suggestions on what to do next and answers to pressing questions in seconds.

No more chasing Jira ticket updates or trawling through Slack!

I'd love to know what you think. Check out CollabGPT here, if you like.

Top comments (0)