Generating Meaningful Code Comments with AI
AI generated
Claude
>_
Claude AI · Code Comments · Prompt Engineering · Code Quality
Generating Meaningful Code Comments with AI
From redundant lines to real context knowledge

AI assistants like Claude can generate code comments in seconds, but without a deliberate instruction the result is often just a paraphrase of the code itself. This article explains why that is a problem, how precise prompting surfaces hidden constraints and workarounds, and how a concrete before-and-after example makes the difference between worthless and valuable comments clear.

12 min. read WHAT vs. WHY · Prompting · Workarounds Claude Code · Code Review · PHP

1. What makes a good code comment

A good code comment adds knowledge that cannot be inferred just by reading the code. The code itself already answers what happens, provided it is written reasonably readably: a loop iterates over an array, a condition checks a status, a function returns a value. A comment that restates exactly that in words adds no additional value, only additional text to read and maintain. The actual job of a comment is to close the gap the code alone cannot fill: why this solution, why this ordering, why this seemingly unnecessary special case.

A simple test helps with this classification: would an experienced developer arrive at this information just by reading the code? If yes, the comment is redundant and can be removed without losing anything. If no, because the information only comes from a ticket, a bug report in a third-party library, or a business rule not visible in the code itself, the comment is valuable. With AI tools like Claude, commenting can now be generated across entire files in seconds, which makes this distinction more urgent than ever.

2. The core problem: AI comments the obvious

Anyone who tasks a language model with a generic instruction like "comment this file" regularly gets comments in practice like // Loop through the items above a foreach loop or // Return the result above a return statement. This behavior is not an outlier but the statistically most likely output for an imprecise instruction, and it shows up across practically all current coding assistants, not just one specific model. The effect is especially pronounced in automated commenting passes over large sets of files, where no one reviews every single line in detail.

The practical cost is real, even though it rarely stands out immediately. Redundant comments increase the visual density of the code without adding any information, and they need to be maintained with every change even though they contribute nothing that is not already in the code. Worse, teams confuse high comment density with good documentation. A file full of // increment counter lines looks well maintained, but it obscures exactly the spots where a real explanation would actually be missing, such as an unexpected timeout value or an unusual error handling path.

3. Why language models default to redundant comments

The root cause lies in the training signal and in missing information, not in a defect of the model. A large share of publicly available, commented code in training data comes from tutorials, teaching material, and boilerplate generators, where exactly this kind of explanatory but redundant comment is common, because it is meant to help beginners follow along. Without an explicit counter-instruction, the model statistically produces what it has seen most often: a paraphrase of the following line.

On top of that comes a structural problem: the model often simply does not know the actual reasoning behind a design decision, because it is not present anywhere in the supplied context. Why an inventory check runs only after a specific event, why a retry is capped at exactly three attempts, or why an exception is deliberately swallowed cannot be derived from the source code alone. If the model lacks access to commit history, ticket references, or pull request discussions, it is left choosing between paraphrasing the code or inventing a plausible-sounding rationale that, in the worst case, is simply wrong.

4. WHAT vs. WHY: the crucial difference

The distinction between WHAT comments and WHY comments is the central lever for better AI-generated documentation. A WHAT comment describes the mechanics of a line of code and is almost always redundant, because the code already carries that information. A WHY comment describes a decision, a constraint, or a trade-off that lives outside the code: a business rule, a bug in a third-party library, a performance trade-off, or a legal requirement. Only the second category justifies a comment in most cases.

An example makes the difference immediately clear: // increment counter above $counter++; is a pure WHAT comment with no added value. // Magento's product repository cache keys by SKU, refreshing here avoids stale prices after import is a WHY comment that provides information not evident from the code alone. Anyone using AI tools for comments should define exactly this distinction as a filter, rather than relying on the generic default output.

5. Prompting deliberately for hidden constraints

The quality of AI-generated comments depends almost entirely on the precision of the instruction. Instead of "comment this file," a targeted instruction such as "comment only the spots where the reasoning is not obvious from the code itself: hidden constraints, workarounds for bugs in third-party code, ordering dependencies, and performance trade-offs. Skip anything that just restates the code in words" produces markedly more focused results. Few-shot examples in the prompt that place a bad comment next to a good one further calibrate the model toward the desired style.

Equally important is giving the model access to the information that makes a WHY comment possible in the first place. A reference to the associated ticket number, an inserted excerpt from the commit message, or the context of a pull request discussion supplies the model with facts that are missing from the source code itself. Without that additional context, even the best instruction can only prevent the model from inventing nonsense, but it cannot substitute for missing knowledge.


#!/usr/bin/env bash
# Claude Code: targeted prompt for meaningful comments instead of a generic pass
claude "Review StockReservationService.php and add comments only where the
reasoning is non-obvious from the code itself: hidden constraints, ordering
dependencies, workarounds for third-party bugs, and performance trade-offs.
Do not add a comment that merely restates the following line in words.
Reference the linked ticket MAGE-4821 for the ordering constraint context."

# Good calibration examples inside the same prompt:
# BAD:  // increment counter
# GOOD: // Retry capped at 3: vendor API rate-limits after the 4th call, see MAGE-4821

The same principle can be stored in a structured system prompt via the Anthropic API, so every call against a file receives the same commenting policy instead of it being retyped in every chat. The following excerpt shows such a system prompt with explicit few-shot examples for bad and good comments.


{
  "model": "claude-sonnet-4-5",
  "system": [
    {
      "type": "text",
      "text": "You add PHP comments. Only comment non-obvious reasoning: hidden constraints, ordering dependencies, workarounds for third-party bugs, and performance trade-offs. Never add a comment that restates the following line. Example BAD: '// increment counter' above $counter++. Example GOOD: '// Retry capped at 3, vendor API rate-limits after the 4th call, see MAGE-4821'.",
      "cache_control": { "type": "ephemeral" }
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": "Add comments to StockReservationService.php following the policy above. Ticket context: MAGE-4821 describes a stock indexer timing issue."
    }
  ]
}

6. Practical example: before and after

A concrete example from a Magento context makes the quality difference tangible. A function checks available stock after a specific event has been dispatched. At first glance the ordering looks arbitrary, but it is necessary because the responsible indexer only updates the stock value after this event fires. If the check runs before that, it returns a stale value without raising any error. This is exactly the kind of information that typically gets lost with naive AI commenting.

The comparison below shows both variants side by side: the naive version merely describes what each line does and loses the critical constraint in the process. The deliberately prompted version explains the ordering dependency, points to the root cause in the indexer's behavior, and thereby makes visible why a refactor at this spot would be risky without accounting for the indexer's timing.


# --- BEFORE: naive AI comments, restates the obvious, loses the real reason ---
- public function checkAvailability(int $productId): bool
- {
-     // Dispatch the stock update event
-     $this->eventManager->dispatch('stock_item_updated', ['id' => $productId]);
-
-     // Get the stock item
-     $stockItem = $this->stockRegistry->getStockItem($productId);
-
-     // Return whether it is in stock
-     return $stockItem->getIsInStock();
- }

# --- AFTER: comments capture the non-obvious ordering constraint ---
+ public function checkAvailability(int $productId): bool
+ {
+     // The stock indexer only refreshes qty after this event fires.
+     // Reading getStockItem() before dispatch returns a stale value
+     // without raising an error. Do not reorder these two calls.
+     // See MAGE-4821 for the indexer timing investigation.
+     $this->eventManager->dispatch('stock_item_updated', ['id' => $productId]);
+
+     $stockItem = $this->stockRegistry->getStockItem($productId);
+
+     return $stockItem->getIsInStock();
+ }

7. Documenting workarounds and technical debt

Workarounds for bugs in third-party code, temporary patches, and deliberately ugly solutions are the area where WHY comments provide the greatest benefit, because their absence becomes most expensive later. Without a rationale, a sleep(2) before an API call looks like a random artifact that gets removed without a second thought in the next refactor, even though it is guarding against a known race condition bug in a third-party API. A good prompting pattern deliberately asks the model to identify unusual constructs such as magic numbers, swallowed exceptions, fixed delays, or conspicuous retry logic, and to propose a structured comment for each occurrence.

A proven format for such comments has three parts: the rationale, since when the workaround has existed, and the condition under which it may be removed, for example "TODO: remove once vendor ticket #4821 is fixed." It is important to understand the limit of AI assistance here: the model can recognize the pattern and propose the structure, but the actual rationale has to come from a reliable source, such as commit history or the ticket system. If the model invents the rationale itself because the context is missing, the result is a comment worse than none at all, one that creates false confidence.

Before a comment is even drafted, a simple heuristic helps flag suspicious spots in the code automatically, so a developer can go add the missing rationale in a targeted way instead of manually scanning the entire file.


// Heuristic scan: flag suspicious constructs that likely need a WHY comment
const fs = require('fs');

const SUSPICIOUS_PATTERNS = [
  { regex: /sleep\(\s*\d+/i, label: 'fixed sleep/delay' },
  { regex: /catch\s*\([^)]*\)\s*\{\s*\}/i, label: 'swallowed exception' },
  { regex: /retry|maxAttempts|MAX_RETRIES/i, label: 'retry logic' },
  { regex: /\b\d{3,}\b/, label: 'magic number' },
];

function findUncommentedSuspects(filePath) {
  const lines = fs.readFileSync(filePath, 'utf8').split('\n');
  const suspects = [];

  lines.forEach((line, i) => {
    const prevLine = lines[i - 1] || '';
    const hasComment = prevLine.trim().startsWith('//');

    for (const { regex, label } of SUSPICIOUS_PATTERNS) {
      if (regex.test(line) && !hasComment) {
        suspects.push({ line: i + 1, label, code: line.trim() });
      }
    }
  });

  return suspects;
}

console.log(findUncommentedSuspects('app/code/Mironsoft/SeoSuite/Model/ImportRetryHandler.php'));

8. Reviewing comment quality

Claude Code can be used deliberately as an additional review pass that does not check code correctness at all, only the comment quality of a diff. Such a pass classifies every new or changed comment as a WHAT comment, flagged for removal, or a WHY comment, kept as is. The same pass can additionally point out spots in the code that would have deserved a comment but did not get one, such as an unusual regex, a disabled linter rule, or special handling for an edge case.

This practice can be codified as a CLAUDE.md convention or a repeatable prompt, so every team member applies the same standard instead of leaving comment quality to individual taste. The effort for this extra review step is small compared to the benefit, because it prevents redundant comments from accumulating unnoticed in the repository over months, burying the genuinely important WHY comments underneath them.


# Claude Code review pass: classify comments in a diff as redundant or valuable
import anthropic

client = anthropic.Anthropic()

with open("diff.patch") as f:
    diff_content = f.read()

response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    system=(
        "You review PHP diffs for comment quality only, not correctness. "
        "For every added or changed comment, classify it as WHAT (restates "
        "the following line, flag for removal) or WHY (explains a hidden "
        "constraint, workaround, or trade-off, keep it). Also flag lines "
        "with unusual constructs (magic numbers, swallowed exceptions, "
        "fixed sleeps) that have no comment at all."
    ),
    messages=[{"role": "user", "content": diff_content}],
)

print(response.content[0].text)

9. Common mistakes and limits compared

Beyond the basic WHAT-versus-WHY distinction, recurring failure patterns show up in AI-assisted commenting. Excessive commenting of every single line is the most common one, closely followed by generic phrases such as "improved error handling" that carry no concrete information. A more subtle risk is the invented but plausible-sounding rationale: when the model lacks the real context, it occasionally fills the gap with an explanation that reads convincingly but is simply wrong. That is more dangerous than a redundant comment, because it actively misleads.

Task Common mistake Recommended approach Benefit
Commenting a loop "Loop through the items" Rationale for iteration order or skip logic Explains non-obvious logic
Documenting a workaround No comment, or "fix for bug" Rationale, date, removal condition, ticket reference Traceable removability
Writing a prompt "Comment this file" Non-obvious reasoning only, with few-shot examples Markedly less noise
Commenting a try/catch "catch exception" "Deliberately swallowed: legacy API returns 500 on empty cart" Prevents misreading it as a bug
Accepting AI comments Merge them unreviewed Targeted review pass for WHY content Prevents comment noise in the repository

None of these patterns can be fully automated, because the actual WHY knowledge often lives outside the code, in people's heads, in tickets, and in commit histories. The realistic limit of AI-assisted commenting is therefore not text quality but access to context: a model with access to the ticket system and git history produces noticeably better comments than one that only sees the isolated file.

Mironsoft

Claude Code workflows, code quality, and AI-assisted Magento development

Want comments and documentation that actually help in review?

We help teams build prompt conventions and review processes that check AI-generated comments for real WHY content, instead of adding more noise to the repository.

Prompt conventions

Reusable instructions for meaningful commenting across the team

Review automation

Claude Code passes for comment quality in the CI pipeline

Legacy documentation

Retroactively documenting workarounds and technical debt in existing code

10. Summary

AI-generated code comments solve a real problem, but they carry an equally real risk: without a deliberate instruction, language models default to WHAT comments that merely restate the code in words, rather than WHY comments that explain hidden constraints, workarounds, and design decisions. The cause lies in the training signal and in missing access to context that is not present in the source code itself. The simple test, "would an experienced developer see this anyway," reliably separates the two categories.

Deliberate prompting with explicit instructions, few-shot examples, and supplementary context from tickets or commit history noticeably improves the hit rate, but it does not remove the need to supply real rationale from reliable sources. An additional review pass that specifically checks for WHY content prevents redundant AI comments from slipping unnoticed into the repository and burying the genuinely important information there.

Generating Meaningful Code Comments with AI: The essentials at a glance

The core problem

Generic instructions produce WHAT comments that just restate the code without adding any information.

The filter

Would an experienced developer see this anyway? If yes, the comment is redundant and should be removed.

Deliberate prompting

Explicit instructions, few-shot examples, and ticket context produce real WHY comments instead of paraphrases.

The limit of AI

Without real context, the model invents plausible but wrong rationale. Review passes catch that.

11. FAQ: Generating Meaningful Code Comments with AI

1Why does AI often just comment the obvious?
Training data contains a lot of tutorial code with redundant, explanatory comments. Without a counter-instruction, the model statistically produces this pattern.
2WHAT comment vs. WHY comment?
WHAT describes the mechanics and is usually redundant. WHY explains a decision or constraint that cannot be inferred from the code.
3How do I prompt Claude deliberately for meaningful comments?
Explicitly request only non-obvious reasoning, with few-shot examples of a bad and a good comment for calibration.
4Can AI detect hidden constraints without context?
Only to a limited degree. It can spot unusual patterns, but the actual rationale has to come from tickets or commit history.
5How do I document workarounds with AI assistance?
With a structured format of rationale, date, and removal condition. The AI proposes the structure, a human supplies the facts.
6What is the risk of too many AI comments?
High density looks well maintained but hides real gaps, and creates unnecessary maintenance overhead with no information value.
7How does Claude Code check comment quality in review?
Through a dedicated pass that classifies each comment as WHAT or WHY and flags missing comments on unusual code.
8Does AI sometimes invent false rationale?
Yes, without real context it occasionally fills the gap with plausible but incorrect explanation. That actively misleads.
9Should I accept AI comments unreviewed?
No, every comment should be checked for real WHY content before merging, ideally through a targeted review step.
10What is the simple rule of thumb for good comments?
Would an experienced developer see it anyway? If yes, remove it. If no, the comment is valuable and should stay.