AI Changed How Code Is Written, Not Why Quality Matters
If an agent writes and reads the code, who are code comments for? People and agents both need them when the code cannot explain a rule on its own. At Webdelo, our rule is simple: type what can be typed, name what can be named, comment what cannot be inferred.
A coding agent is an AI tool that reads files and proposes or makes changes. Clear names, types, and comments help it understand what those changes must preserve. A complex B2B system may live for years, with people and agents maintaining it together.
This is our engineering perspective from working on ERP, CRM, and B2B platforms. The research below supports the value of meaningful context. The order in which we put that context into a codebase is Webdelo's own practical approach.
Compiler vs Coding Agent: Valid Code Is Not Readable Code
A compiler or interpreter follows language rules. A coding agent also uses names, types, comments, tests, and repository context to infer intent. Code can execute correctly while leaving that intent unclear.
Renaming $availableCredit to $x1 does not change the calculation. It removes a clue about what the value means. The agent needs that clue when deciding whether a requested change belongs in credit checks or settlement logic.
The 2021 CodeT5 paper treats developer-assigned identifiers as meaningful signals during model training. The 2024 paper Code Needs Comments reports improvements from comment-augmented training data. Both concern model training, so neither establishes a rule to comment every method.
The publicly described workflows of Claude Code and Codex work with source files and retrieve relevant context as needed. Their documentation does not describe a mandatory step that removes all comments and renames identifiers before the model sees the code. That also does not mean an agent reads the entire repository for every task.
Where Should Knowledge Live: Types, Names, Then Comments
We put business knowledge where tools can check it and readers can find it. Domain types come first, followed by meaningful names and structure. Comments preserve the reasoning that those tools cannot express.
For example, a crm integration may handle both customer IDs and settlement account IDs. Both can be integers, but they are not interchangeable. Separate types make that distinction visible and checkable.
Our order for code documentation is:
- Domain types: represent business concepts and enforce their rules.
- Names and structure: show what a value or operation means.
- Tests and contracts: check expected behavior and interface requirements.
- WHY comments: explain decisions that local code cannot reveal.
- Repository documentation: explain rules spanning multiple modules.
PHP: From Primitives and PHPDoc to Domain Types
Consider these alternative method declarations from a settlement interface. The first has native types, but leaves important questions unanswered:
public function settle(
int $accountId,
int $amount,
string $currency,
int $status
): void;
Is the amount in dollars or cents? Which statuses are allowed? PHP's type declarations and strict typing cannot answer those business questions. declare(strict_types=1) governs scalar type coercion, not domain design or full static typing.
PHPDoc can supply the missing information:
/**
* @param int $accountId Settlement account ID, not customer ID.
* @param int $amount Amount in minor units.
* @param string $currency Supported three-letter currency code.
* @param int $status 0 = pending, 1 = approved, 2 = settled.
*/
public function settle(
int $accountId,
int $amount,
string $currency,
int $status
): void;
Now the reader has answers, but these descriptions alone do not enforce the rules. A caller can still pass a customer ID where an account ID belongs.
The third version gives those concepts their own types:
enum SettlementStatus
{
case Pending;
case Approved;
case Settled;
}
// Closed batches must remain unchanged for reconciliation.
public function settle(
SettlementAccountId $account,
Money $amount,
SettlementStatus $status
): void;
Money is a value object: it keeps an amount and its currency together. Martin Fowler's Money pattern explains this design. SettlementStatus uses a PHP enum to define a closed set of values.
These declarations are only the interface. The value objects must validate their inputs, and the settlement implementation must enforce batch and status-transition rules. The remaining comment explains why one of those rules exists.
This distinction applies equally to Go and Java. An int, long, or generic EntityId can satisfy the language while saying little about the business.
When PHPDoc Still Adds Real Information
We keep PHPDoc when it communicates something native types cannot express. Static analysis tools can also check some PHPDoc annotations.
- Legacy interfaces with incomplete native types.
- Array shapes describing required keys and their values.
- Generic collection types for static analysis.
- Contracts, measurement units, and external API restrictions.
- Exceptions and side effects that callers must handle.
@param OrderStatus $status Order status adds nothing to an already typed parameter. Our review question is simple: does this line tell the reader something the signature does not?
Good Code Comments Explain WHY, Not WHAT
A useful comment preserves information that cannot reliably be inferred from nearby code. That might be a business reason, an integration restriction, or a safety rule. Repeating the operation's name adds no such information.
These illustrative backend examples show the difference. The useful versions explain a decision that a future change must respect.
// Redundant: update status.
$order->setStatus(OrderStatus::Settled);
// Useful: Only the provider's confirmed callback authorizes settlement.
$order->setStatus(OrderStatus::Settled);
A payment integration for an ecommerce website often crosses a unit boundary. Keep conversion in a named method, then document the external reason for using that representation.
// Redundant: set amount.
$request->amount = $payment->minorUnits();
// Useful: This provider accepts integer minor units, not decimal amounts.
$request->amount = $payment->minorUnits();
In a trading system, unrealized profit and loss means gains or losses on positions that remain open. A settlement calculation may deliberately exclude them.
// Redundant: calculate total.
$exposure = $settledTrades->total();
// Useful: Unrealized P&L is excluded because it has not settled.
$exposure = $settledTrades->total();
Without that explanation, a reader could mistake an intentional omission for a missing term in the calculation.
The Comment That Prevents a Deadlock: A Go Example
A mutex is a lock that protects shared data from simultaneous changes. In this simplified Go excerpt, the portfolio service acquires the lock before calling updatePosition().
func (p *Portfolio) ApplyFill(symbol string, quantity int64) {
p.portfolioMu.Lock()
defer p.portfolioMu.Unlock()
p.updatePosition(symbol, quantity)
}
func (p *Portfolio) updatePosition(symbol string, quantity int64) {
// Do not lock here - caller already holds portfolioMu.
p.positions[symbol] += quantity
}
An agent looking only at the helper could add a lock to protect the shared map. Acquiring the same Go mutex again would block the call indefinitely. Adding a separate positionMu can create a deadlock if another path acquires the two locks in reverse order.
The comment protects a new human developer too. We still review every caller and test concurrent behavior, because a comment cannot enforce lock ownership.
Signal-to-Noise: Why Redundant Comments Hurt AI Context
An agent has a limited context budget: the material it can consider at once. Repeated PHPDoc and line-by-line narration consume that budget without adding meaning. A stale comment is more dangerous because it supplies a competing version of the rules.
Anthropic's context engineering guidance favors high-signal information and retrieving relevant details when needed. OpenAI's harness engineering article describes the repository as the system of record and explains why oversized instruction files get in the way.
Our application of that guidance is practical: put a rule close to the code it governs, and keep cross-module explanations in discoverable repository documents. Progressive disclosure means opening those detailed documents when the task requires them.
Shortening $settlementAccount to $x1 removes semantic signal, or useful meaning. It does not automatically reduce token use, because models split text differently. We measure project outcomes rather than promise a percentage of token, cost, or error savings.
Which Clean Code Principles Still Hold Up With AI Agents
The naming and comment principles in Robert Martin's Clean Code remain useful for AI-readable code. Names should expose intent, and comments should preserve reasoning or warnings. We apply these ideas selectively, rather than treating every recommendation in the book as mandatory.
The Meaningful Names chapter provides practical rules for both human and agent readers:
- Reveal intent: use
settledExposureinstead ofvalue. - Make meaningful distinctions: distinguish
customerIdfromsettlementAccountId. - Use searchable names: give a business limit a recognizable constant name.
- Avoid mental translation: do not make readers remember what
x1represents. - Use one word per concept: avoid calling the same operation settlement, clearing, and posting without a real distinction.
That vocabulary should also reach the interface. When working with a web design agency, shared business terms help keep screen labels and backend behavior aligned.
The Comments chapter does not amount to "never comment." Comments cannot compensate for confusing code, but explanations of intent and warnings have value. Self documenting code still needs help when the reason for a decision lives outside the implementation.
Should AI Coding Agents Be Told to Write Comments?
Yes, but "comment every method" is the wrong instruction. Ask agents to document hidden rules and leave obvious syntax alone. Short, explicit project guidance makes that expectation repeatable.
Anthropic's Claude Code best practices discuss CLAUDE.md as a place for project instructions. We keep shared engineering rules separate from model-specific tuning, such as the subject of OpenAI's skills and prompts guidance.
A compact instruction block can make our comment policy explicit:
Prefer domain types and meaningful names over explanatory comments.
Comment non-obvious business rules and intentional omissions.
Document architectural rules, lock ownership, and external API quirks.
Explain security and compliance constraints that local code cannot show.
Do not restate signatures or obvious syntax.
Update affected comments with code, and verify rules against tests and docs.
We review generated comments as claims about the system. If an agent cannot establish why a rule exists, it should flag the uncertainty rather than invent a plausible explanation.
AI First Is Not Vibe Coding
At Webdelo, AI First means incorporating AI into engineering work with human oversight. Human in the Loop means engineers review consequential decisions and remain responsible for the result. A strong model can accelerate work in a poorly designed environment too.
A personal AI account is a useful way to explore an idea or build a working prototype. Operating a production B2B system adds responsibilities that continue after the first version works:
- Domain modeling and architecture that accommodate future changes.
- Tests and integration contracts that detect broken behavior.
- Observability: logs, metrics, and alerts that reveal failures.
- Security controls and clear access boundaries.
- Human review and ownership of releases.
How Webdelo Applies AI First and Human in the Loop
We prepare the codebase with domain types, meaningful names, WHY comments, and short repository instructions. Agents assist with bounded refactoring, boilerplate, tests, and code exploration. Engineers own the domain model, architecture, and review.
"AI does not replace engineering discipline. Good types should carry business meaning, and comments should explain only what the code cannot show on its own. Our goal is not to give an agent more text, but better context. That is how AI speeds up a complex system without speeding up technical debt."
We work with B2B mid-market companies, particularly in Germany/EU and the United States. Our Web Development work includes complex platforms and integrations that need ongoing engineering ownership. The same approach supports ERP, CRM, high-load systems, and AI integration.
Responsibility boundaries also matter when automation reaches customer-facing operations. For seo, technical changes need validation before release. For geo, published business claims need a reliable source. For digital marketing, automated tracking changes need review against consent requirements.
The Business Outcome: Systems That Are Safer and More Efficient to Evolve
The business goal is a system that remains understandable as it changes. Clear code helps engineers and agents assess the impact of a request before modifying it. That supports more predictable maintenance, without guaranteeing a particular saving.
Consider a corporate website connected to a customer portal and ERP. A change to customer eligibility may affect every layer. Named domain rules and documented integration boundaries help the team find those dependencies before release.
For modernization, we start with the rules that are hardest to recover from the existing code. For AI automation, we define what the agent may change and what needs approval. Useful measures include review rework, escaped defects, and the time needed to validate a change.
Talk to Webdelo about developing or modernizing a complex B2B/ERP system, or integrating AI automation into your engineering and business processes. Start with the workflow you want to improve and the business rules it must preserve.
Better Context, Not More Text
Useful code comments for AI coding agents explain what the code cannot show. Put business meaning into types and names first. Keep comments for hidden reasons, and keep them accurate as the system changes.
Valid code is only the starting point. AI First works when engineers preserve architectural judgment, verify changes, and remain accountable for production behavior.
Frequently Asked Questions
What should code comments for AI coding agents explain?
A good comment explains why, not what. It keeps information that cannot be inferred from nearby code: a business reason, an architectural rule, an integration limit, a concurrency constraint, or an intentional omission. Comments like "update status" above obvious code add nothing. Webdelo's rule is: type what can be typed, name what can be named, comment what cannot be inferred.
Why do names and types matter to an AI coding agent if the code runs anyway?
A compiler only follows language rules, so code with a name like $x1 runs the same as code with $availableCredit. A coding agent also uses names, types, comments, tests, and repository context to work out what the code is meant to do. Remove a meaningful name and the agent loses a clue about where a change belongs. Valid code is not the same as understandable code.
How do domain types reduce the need for comments and PHPDoc?
Domain types such as SettlementAccountId, Money, and SettlementStatus carry business meaning that int and string do not. Tools can check them, so a caller can no longer pass a customer ID where an account ID belongs. A PHPDoc description only states the rule, it does not enforce it. With domain types, the remaining comments can focus on why a rule exists.
When is PHPDoc still worth writing?
PHPDoc is useful when it says something native types cannot express. Typical cases are legacy interfaces with incomplete types, array shapes, generic collection types for static analysis, contracts, measurement units, external API restrictions, exceptions, and side effects. A line like "@param OrderStatus $status Order status" only repeats the signature. A simple review question helps: does this line tell the reader something the signature does not?
How can a single comment prevent a deadlock in Go code?
Sometimes the calling code already holds a mutex before it calls a helper function. An agent or a new developer who sees only the helper may add another lock to protect the shared data. Locking the same Go mutex again blocks the call forever, and a second lock can cause a deadlock. A short comment stating that the caller holds the lock keeps this rule visible, but callers still need review and concurrency tests.
Do redundant comments hurt AI coding agents?
Yes. An agent can consider only a limited amount of material at once, and repeated PHPDoc or line-by-line narration uses that space without adding meaning. Stale comments are worse, because they give the agent a competing version of the rules. The fix is not to shorten names to save tokens: meaningful names are useful signal. Webdelo does not promise a fixed percentage of token, cost, or error savings.
Should AI coding agents be instructed to write comments, and how is AI First different from vibe coding?
Yes, but not with a "comment every method" rule. Project instructions should ask for comments only on non-obvious business rules, architectural and concurrency rules, intentional omissions, external-system quirks, and security or compliance constraints. This is part of AI First with Human in the Loop: agents help with bounded tasks, while engineers own the domain model, architecture, and review. A strong model speeds up a poorly designed environment too, so engineering discipline still decides the result.