Writing Useful Comments

20 min read

Clean Code and Readability — review Java comments that explain why code exists instead of restating what it already says.

1. Introduction

Comments are useful when they explain something that the code itself cannot clearly communicate.

In production Java applications, comments should not describe obvious syntax. Their purpose is to capture information such as:

  • Why a non-obvious implementation was chosen
  • Why a business rule exists
  • Why seemingly unnecessary code cannot be removed
  • Why a workaround exists
  • What external-system limitation influenced the implementation
  • Why a particular concurrency, performance, or transactional decision was made

A good comment provides context that would otherwise be lost when the original developer leaves the project.

A bad comment creates noise, duplicates the code, becomes outdated, or gives a false impression about what the application actually does.

During Pull Request review, reviewers should therefore evaluate comments with the same care as executable code.

2. What This Topic Means

Writing useful comments means documenting information that cannot be expressed clearly through Java code, naming, structure, tests, or API design.

For example, this comment provides little value:

JAVA
// Check if order status is completed
if (order.getStatus() == OrderStatus.COMPLETED) {
    sendInvoice(order);
}

The code already explains what is happening.

A more useful comment might explain why a particular condition exists:

JAVA
// Legacy billing API rejects invoices during settlement reconciliation between 01:00 and 01:15 UTC.
if (settlementWindowService.isReconciliationRunning()) {
    scheduleInvoiceForRetry(order);
    return;
}

The second comment captures external operational knowledge that cannot be understood simply by reading the Java statement.

Useful comments generally explain why, while clean code should explain what and how.

3. Why It Matters in Real Projects

Readability

Useful comments help developers understand unusual business rules without reverse-engineering requirements, tickets, or production history.

Maintainability

A future developer can modify code safely when the reason behind an implementation is documented.

Debugging

Comments explaining external dependencies, legacy behavior, retry rules, or known edge conditions can significantly reduce investigation time.

Reliability

Some apparently unnecessary conditions exist to prevent known production failures. Explaining them reduces the chance that someone removes them during refactoring.

Team Development

Large projects often contain code written by developers who are no longer on the team. Comments preserve important technical and business context.

Comments become harmful, however, when they are outdated. An incorrect comment may be more dangerous than having no comment at all.

4. Core Concept

The main principle is:

Code should explain what it does. Comments should explain why something non-obvious is necessary.

Before adding a comment, ask whether the code can be made clearer instead.

Instead of:

JAVA
// Get active customers
List<Customer> list = repository.findByActiveTrue();

Use a meaningful name:

JAVA
List<Customer> activeCustomers = customerRepository.findByActiveTrue();

No comment is required.

Comments become valuable when the reason cannot reasonably be encoded into a class name, method name, variable name, test, or type.

For example:

JAVA
// Do not replace this with LocalDate.now().
// Billing dates must always be calculated using the tenant's configured timezone.
LocalDate billingDate = LocalDate.now(tenantZoneId);

This protects an important domain requirement.

5. Important Rules

  • Prefer self-explanatory code over explanatory comments.
  • Explain why the implementation exists, not what individual Java statements do.
  • Document non-obvious business rules.
  • Document external-system constraints when they affect implementation.
  • Explain temporary workarounds and reference the reason for them.
  • Keep comments close to the code they describe.
  • Update comments whenever the related implementation changes.
  • Delete comments that are no longer accurate.
  • Avoid commented-out production code.
  • Never place passwords, API keys, tokens, customer data, or other sensitive information inside comments.
  • Avoid writing comments that merely translate Java syntax into English.
  • Explain unexpected performance optimizations when the simpler implementation would otherwise appear preferable.
  • Explain concurrency assumptions where incorrect modification could create race conditions.
  • Use Javadoc primarily for API contracts and externally useful documentation rather than narrating implementation details.
  • Treat TODO comments as temporary engineering work, not permanent documentation.

6. Bad Code Example

Consider an order-processing service.

JAVA
@Service
public class OrderService {
    private final OrderRepository orderRepository;
    private final PaymentClient paymentClient;

    public OrderService(OrderRepository orderRepository, PaymentClient paymentClient) {
        this.orderRepository = orderRepository;
        this.paymentClient = paymentClient;
    }

    public void processOrder(Long id) {
        // Get order
        Order o = orderRepository.findById(id).orElseThrow();

        // Check status
        if (o.getStatus() == OrderStatus.CANCELLED) {
            return;
        }

        // Call payment
        PaymentResponse response = paymentClient.charge(o.getPaymentId());

        // Check payment
        if (response.isSuccessful()) {
            // Change status
            o.setStatus(OrderStatus.CONFIRMED);

            // Save order
            orderRepository.save(o);
        }

        // TODO fix later
        // orderRepository.flush();
    }
}

The code contains many comments, but almost none provide useful information.

7. Problems in the Bad Code

Comments Repeat the Code

Comments such as:

JAVA
// Get order

// Check status

// Save order

simply describe the Java statement immediately below them.

They increase visual noise without adding knowledge.

Poor Naming Hidden Behind Comments

The variable:

JAVA
Order o

is unclear.

Instead of compensating with comments, the developer should use:

JAVA
Order order

Unclear Business Reason

The code silently ignores cancelled orders:

JAVA
if (o.getStatus() == OrderStatus.CANCELLED) {
    return;
}

A reviewer may reasonably ask why cancelled orders are silently ignored instead of throwing an exception or returning a result.

If this behavior represents a business rule, the reason should be clear.

Weak TODO Comment

JAVA
// TODO fix later

This provides no useful information.

It does not explain:

  • What is broken
  • Why it cannot be fixed now
  • What ticket tracks the work
  • Whether production behavior is affected

Commented-Out Code

JAVA
// orderRepository.flush();

Commented-out code should normally be deleted.

Git already stores code history.

Missing Payment-Failure Behavior

The method does nothing when payment fails.

This is primarily a code-design issue rather than a comment issue, but comments should never be used to hide incomplete business behavior.

8. Code Review Findings

A senior reviewer should notice:

  • Most comments merely repeat Java statements.
  • Variable naming should be improved instead of explained through comments.
  • The cancelled-order behavior is not obvious from the method contract.
  • The payment failure path is unclear.
  • The TODO does not contain actionable information.
  • Commented-out repository code should be removed.
  • The implementation lacks documentation for any genuinely unusual business behavior.
  • The comments will require maintenance despite providing almost no value.

A reviewer should not request more comments everywhere.

The correct review direction is usually:

Improve the code first, then keep only comments that explain important context.

9. Reviewer Comment Example

A professional PR review comment could be:

These comments mostly repeat what the statements already express. Could we remove them and use clearer naming instead? Please keep comments only where we need to explain non-obvious business behavior, such as why cancelled orders are intentionally ignored.

Another useful comment:

Can we remove the commented-out flush() call? Git history already preserves previous implementations, and leaving dead code here may confuse future maintainers.

For the TODO:

Please either link this TODO to a tracked issue and explain the required follow-up, or remove it if no action is currently planned.

10. Improved Code

JAVA
@Service
public class OrderService {
    private final OrderRepository orderRepository;
    private final PaymentClient paymentClient;

    public OrderService(OrderRepository orderRepository, PaymentClient paymentClient) {
        this.orderRepository = orderRepository;
        this.paymentClient = paymentClient;
    }

    public void processOrder(Long orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new OrderNotFoundException(orderId));

        if (order.getStatus() == OrderStatus.CANCELLED) {
            return;
        }

        PaymentResponse paymentResponse = paymentClient.charge(order.getPaymentId());

        if (!paymentResponse.isSuccessful()) {
            throw new PaymentFailedException(orderId, paymentResponse.getFailureReason());
        }

        order.setStatus(OrderStatus.CONFIRMED);
        orderRepository.save(order);
    }
}

Most comments disappeared because the code now communicates its intent directly.

Suppose the cancelled-order behavior exists because of a specific external requirement. Then a comment may be justified:

JAVA
// Cancellation events may be delivered more than once by the legacy order gateway.
// Returning here keeps processing idempotent for already-cancelled orders.
if (order.getStatus() == OrderStatus.CANCELLED) {
    return;
}

That comment provides information the condition itself cannot communicate.

11. Improved Code Explanation

Meaningful Names

id became:

JAVA
orderId

o became:

JAVA
order

response became:

JAVA
paymentResponse

These names eliminate the need for explanatory comments.

Explicit Failure Handling

Payment failure now produces a meaningful exception.

The behavior is visible directly from the code.

Removed Redundant Comments

Statements such as:

JAVA
orderRepository.save(order);

do not need:

JAVA
// Save order

Removed Dead Code

The commented-out flush() call was removed.

Previous versions remain available through source control.

Useful Comments Remain Possible

A comment should remain only when additional business or operational context cannot reasonably be expressed through the implementation itself.

12. Bad Code vs Improved Code

AreaBad CodeImproved Code
ReadabilityComments compensate for weak namingCode explains normal behavior itself
MaintainabilityMany comments must be synchronizedFewer comments reduce maintenance
TestabilityFailure behavior is unclearPayment failure behavior is explicit
ReliabilityHidden business assumptionsImportant behavior can be documented clearly
ReviewabilityReviewer must separate noise from useful informationImportant decisions are easier to identify

The improved solution does not attempt to eliminate comments completely.

It eliminates unnecessary comments.

13. Real Project Scenario

Consider a banking application integrating with an old core-banking platform.

A developer encounters this code:

JAVA
if (transaction.getAmount().compareTo(BigDecimal.ZERO) == 0) {
    return;
}

Without context, the developer may think zero-value transactions should still be sent to the downstream service for audit purposes.

However, the existing implementation may intentionally skip them because the external system rejects zero-value transactions.

A useful comment could be:

JAVA
// CoreBank v4 rejects zero-value settlement transactions with error CB-2041.
// Keep them internal rather than sending them to the settlement endpoint.
if (transaction.getAmount().compareTo(BigDecimal.ZERO) == 0) {
    return;
}

Months later, another developer sees the condition during refactoring.

Instead of removing it as "unnecessary," the developer immediately understands the production dependency.

That is the type of knowledge comments should preserve.

14. Production Impact

Poor comments can create several production risks.

Incorrect Refactoring

A developer may remove an unusual condition because its purpose is not documented.

Misleading Debugging

An outdated comment may say one thing while the actual code does something different.

Developers may investigate the wrong behavior during an incident.

Maintenance Problems

Hundreds of redundant comments make important documentation difficult to notice.

Regression Bugs

Workarounds for external services, data migrations, legacy schemas, or race conditions may be removed because nobody knows why they exist.

Security Exposure

Sensitive information accidentally stored in comments may appear in:

  • Git history
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps
  • Code-review tools
  • CI logs
  • Source packages

Comments are part of the source code and should never be treated as a secure storage location.

15. Common Developer Mistakes

Describing Every Statement

Bad:

JAVA
// Increment retry count
retryCount++;

Using Comments Instead of Good Names

Bad:

JAVA
int x = 5; // Maximum retries

Better:

JAVA
int maxRetries = 5;

Leaving Commented-Out Code

Bad:

JAVA
// paymentService.refund(payment);
// auditService.recordRefund(payment);

Remove dead code unless there is an exceptional and explicitly documented reason to retain it temporarily.

Writing Vague TODOs

Bad:

JAVA
// TODO handle this

Better:

JAVA
// TODO PAY-1842: Remove fallback after Payment Gateway v2 migration is complete.

Even better, where project policy permits, track the issue externally and avoid a permanent TODO.

Allowing Comments to Become Incorrect

Bad:

JAVA
// Retry payment three times
for (int attempt = 0; attempt < 5; attempt++) {
    processPayment();
}

The comment now contradicts the code.

Writing Large Historical Essays

Comments should not become a complete history of every previous implementation.

Source control and issue tracking systems are better places for detailed history.

Adding Developer Names

Avoid:

JAVA
// Added by Rahul on 12/01/2025

Git already records authorship.

Explaining Bad Code Instead of Refactoring It

A complicated method should not receive twenty comments if it can instead be divided into well-named methods.

16. Edge Cases

For comments themselves, traditional runtime edge cases such as null or empty strings are not directly relevant.

However, reviewers should consider several maintenance edge cases.

Business Rule Changes

If a business rule changes, does the related comment still describe the current requirement?

External API Upgrades

A workaround comment may no longer be valid after the dependency is upgraded.

Temporary Migration Logic

Temporary comments should make it possible to determine when the temporary logic can be removed.

Concurrency Assumptions

If thread-safety depends on a specific execution model, document the assumption carefully.

Example:

JAVA
// This cache is modified only by the single-threaded reconciliation executor.
pendingReconciliations.put(transactionId, reconciliation);

Such a comment becomes especially important if future developers may change the execution model.

Boundary Behavior

When an unusual boundary exists because of business policy, explain the reason rather than restating the comparison.

17. Performance Considerations

Comments themselves usually have no runtime performance cost because Java comments are not executed by the JVM.

Therefore, performance should not be invented as a concern for ordinary comments.

However, comments can be valuable when explaining non-obvious performance-sensitive code.

For example:

JAVA
// Fetch IDs first to avoid loading full Order entities for approximately 2M archived records.
List<Long> orderIds = orderRepository.findArchivedOrderIds(cutoffDate);

Without the comment, a developer might replace the optimization with a simpler entity query and unintentionally increase memory consumption.

Another example:

JAVA
// Keep batch size below 500 because the downstream API begins throttling larger requests.
List<List<Customer>> batches = partition(customers, 500);

The comment explains why the apparently arbitrary value matters.

Important principle:

Do not comment that code is "faster." Explain the actual constraint or measured reason whenever it matters.

18. Security Considerations

Comments can create serious security problems when developers include sensitive information.

Never write comments such as:

JAVA
// Production DB password: admin123

// Temporary API key: abc123

// JWT secret used by mobile service

Also avoid exposing sensitive customer information:

JAVA
// Issue occurs for customer John Smith account 8472991

Use secure incident-management or ticketing systems instead.

Comments can appropriately explain security decisions.

For example:

JAVA
// Do not accept tenantId from the request body.
// Authorization is based exclusively on the tenant resolved from the authenticated principal.
String tenantId = authenticatedUser.getTenantId();

This comment explains an important security boundary.

Another example:

JAVA
// Constant-time comparison is intentional to avoid timing leakage for API signatures.
return MessageDigest.isEqual(expectedSignature, suppliedSignature);

Security comments are particularly valuable when a future "simplification" could introduce a vulnerability.

19. Testing Considerations

Comments do not normally require automated tests.

Instead, tests should verify the behavior that important comments describe.

Suppose the comment says:

JAVA
// Duplicate webhook events are ignored to keep payment processing idempotent.

There should be a test verifying that behavior.

Example test scenarios:

Positive Case

A new payment webhook is processed successfully.

Duplicate Case

The same webhook ID is submitted twice and the payment is not processed twice.

Failure Case

A malformed webhook produces the expected error behavior.

Integration Test

Verify idempotency against the persistence layer when duplicate requests arrive.

A comment must never replace a test.

Bad approach:

JAVA
// This method works when customer is null.

Better approach:

Write a test proving the expected null behavior.

Comments describe intent.

Tests verify behavior.

20. Refactoring Guidelines

When refactoring comments in an existing project:

  1. Read the associated code carefully.
  2. Determine whether the comment explains what the code does or why it exists.
  3. Replace unclear names before adding more documentation.
  4. Remove comments that merely duplicate statements.
  5. Verify business-rule comments against current requirements.
  6. Check issue trackers before removing workaround comments.
  7. Search Git history if the reason behind unusual logic is unclear.
  8. Preserve comments that describe critical external constraints.
  9. Update comments whenever implementation behavior changes.
  10. Run existing tests to ensure code refactoring has not changed behavior.

Do not mechanically delete every comment.

Some comments may contain critical production knowledge.

Refactoring should distinguish:

  • Noise
  • Obsolete documentation
  • Important engineering context

21. Best Practices

Let Names Explain Normal Behavior

Prefer:

JAVA
Customer customer = customerRepository.findById(customerId)
        .orElseThrow(() -> new CustomerNotFoundException(customerId));

instead of:

JAVA
// Find customer
Customer c = customerRepository.findById(customerId).orElseThrow();

Explain Business Reasons

Good:

JAVA
// Premium customers retain reservation priority for 15 minutes after payment timeout.
reservation.extendPriorityWindow(Duration.ofMinutes(15));

Explain External Constraints

Good:

JAVA
// Vendor API accepts a maximum of 100 IDs per request.
for (List<Long> batch : partition(productIds, 100)) {
    inventoryClient.fetchAvailability(batch);
}

Explain Counter-Intuitive Code

Good comments are especially valuable where developers may otherwise "simplify" code incorrectly.

Keep Comments Local

Place the comment near the relevant logic.

Keep Comments Current

Updating behavior without updating documentation should be considered an incomplete change.

Reference Trackable Work

For temporary technical debt:

JAVA
// TODO ORDER-428: Remove compatibility mapping after all clients migrate to API v3.

Use Javadoc for Contracts

Javadoc is useful for:

  • Public APIs
  • Reusable libraries
  • Non-obvious parameters
  • Return-value contracts
  • Exception behavior
  • Important preconditions

Avoid Javadoc that merely repeats method names.

22. Practices to Avoid

Obvious Comments

Avoid:

JAVA
// Return result
return result;

They create noise.

Commented-Out Code

Avoid:

JAVA
// customer.setActive(false);

Use version control.

Change Logs Inside Source Files

Avoid:

JAVA
// 2024-03-01 Rahul changed timeout
// 2024-05-08 Amit changed timeout again
// 2025-01-10 Sneha fixed timeout

Git already maintains change history.

Vague Warnings

Avoid:

JAVA
// Important!
// Don't change this!

Explain why.

Better:

JAVA
// Settlement file names are consumed by the partner's fixed-width parser.
// Changing this format requires coordinating a partner-side deployment.

Misleading Comments

A wrong comment is worse than no comment because developers may trust it.

Excessive Javadoc

Avoid:

JAVA
/**
 * Gets customer ID.
 * @return customer ID
 */
public Long getCustomerId() {
    return customerId;
}

This provides almost no value.

Sensitive Information

Never store:

  • Passwords
  • Access tokens
  • Private keys
  • Customer identifiers
  • Security bypass instructions
  • Production credentials

inside source comments.

23. Code Review Checklist

During Pull Request review, ask:

  • Does this comment provide information that the code itself cannot communicate?
  • Is the comment explaining why rather than merely describing what?
  • Could clearer naming remove the need for this comment?
  • Could a smaller method remove the need for this explanation?
  • Is the documented business rule still valid?
  • Does the comment accurately match the current implementation?
  • Is an external-service limitation documented where necessary?
  • Is a non-obvious performance decision explained?
  • Is a concurrency assumption documented where modification could be dangerous?
  • Are temporary workarounds linked to actionable cleanup work?
  • Are there vague TODO comments?
  • Is commented-out code being committed?
  • Does any comment contain sensitive information?
  • Does Javadoc describe a useful API contract rather than repeat the method name?
  • Would a future developer understand why this unusual code must remain?
  • Should the behavior described by the comment also have an automated test?

24. Common Pull Request Review Comments

  1. *This comment repeats the method call below it. Can we remove it and let the code remain self-explanatory?*
  1. *Could we rename this variable instead of using a comment to explain what it contains?*
  1. *Why is this retry limit fixed at 3? If this comes from a vendor constraint or production finding, please document that reason.*
  1. *Please remove the commented-out implementation. Git history already preserves the previous version.*
  1. *This TODO is difficult to act on. Can we reference the tracking ticket and describe the condition under which this workaround can be removed?*
  1. *The comment says five retries, but the loop currently performs three. Please update either the implementation or the comment so they remain consistent.*
  1. *This condition is not obvious from the business flow. A short comment explaining why duplicate callbacks are intentionally ignored would help future reviewers.*
  1. *Please avoid including the real customer/account details in this comment. Use the incident ticket for sensitive production examples.*
  1. *The Javadoc currently repeats the method signature. Could we document the non-obvious error behavior or remove the Javadoc?*
  1. *This optimization makes the code less obvious. Please add a short explanation of the database/performance constraint that requires it.*

25. Code Review Exercise

Review the following Spring Boot service.

Identify:

  • Problems
  • Code smells
  • Risks
  • Unnecessary comments
  • Missing useful comments
  • Possible improvements

Do not assume every comment should remain.

JAVA
@Service
public class NotificationService {
    private final NotificationRepository notificationRepository;
    private final SmsClient smsClient;

    public NotificationService(NotificationRepository notificationRepository, SmsClient smsClient) {
        this.notificationRepository = notificationRepository;
        this.smsClient = smsClient;
    }

    public void send(Long id) {
        // Get notification
        Notification n = notificationRepository.findById(id).orElseThrow();

        // Check if processed
        if (n.isProcessed()) {
            return;
        }

        // Phone number
        String p = n.getPhoneNumber();

        // Send SMS
        smsClient.send(p, n.getMessage());

        // Set processed true
        n.setProcessed(true);

        // Save
        notificationRepository.save(n);

        // TODO fix duplicate issue later

        // notificationRepository.flush();

        // Production API token used during testing was abc-test-123
    }
}

26. Exercise Solution

The implementation contains several important code-review issues.

Issue 1: Redundant Comments

These comments add no value:

JAVA
// Get notification
// Check if processed
// Phone number
// Send SMS
// Set processed true
// Save

They simply translate Java statements into English.

Issue 2: Poor Variable Names

n and p should become:

JAVA
notification
phoneNumber

Clear names eliminate several comments automatically.

Issue 3: Weak Exception Handling

This:

JAVA
orElseThrow()

produces a generic NoSuchElementException.

A domain-specific exception provides more useful behavior.

Issue 4: Duplicate Processing Risk

The TODO says:

JAVA
// TODO fix duplicate issue later

but gives no explanation.

More importantly, duplicate notification delivery is a real production issue.

Two concurrent requests could both execute:

JAVA
if (notification.isProcessed())

before either transaction updates the row.

Both may send the SMS.

The code therefore requires an actual concurrency/idempotency solution rather than a TODO comment.

Issue 5: Commented-Out Code

JAVA
// notificationRepository.flush();

should be removed.

Issue 6: Sensitive Information

This is unacceptable:

JAVA
// Production API token used during testing was abc-test-123

Secrets must never be stored in source comments.

If a real credential had been committed, simply deleting the comment would not be enough because it may remain in Git history.

The credential should be revoked or rotated according to the organization's security process.

Improved Code

One possible approach is to use a database-backed state transition that prevents multiple workers from claiming the same notification.

JAVA
@Service
public class NotificationService {
    private final NotificationRepository notificationRepository;
    private final SmsClient smsClient;

    public NotificationService(NotificationRepository notificationRepository, SmsClient smsClient) {
        this.notificationRepository = notificationRepository;
        this.smsClient = smsClient;
    }

    @Transactional
    public void send(Long notificationId) {
        Notification notification = notificationRepository.findByIdForUpdate(notificationId)
                .orElseThrow(() -> new NotificationNotFoundException(notificationId));

        if (notification.isProcessed()) {
            return;
        }

        smsClient.send(notification.getPhoneNumber(), notification.getMessage());

        notification.markProcessed();
    }
}

Repository example:

JAVA
public interface NotificationRepository extends JpaRepository<Notification, Long> {
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("select n from Notification n where n.id = :notificationId")
    Optional<Notification> findByIdForUpdate(@Param("notificationId") Long notificationId);
}

Why the Changes Help

Better Naming

The code now communicates the meaning of each value without comments.

Domain-Specific Exception

Missing notifications produce meaningful application behavior.

Duplicate Protection

The database lock reduces the possibility that two application threads process the same notification simultaneously.

Whether pessimistic locking is the correct strategy depends on the application's traffic, database characteristics, and delivery architecture.

Other production designs may use:

  • Atomic status transitions
  • Optimistic locking
  • Idempotency keys
  • Message broker deduplication
  • Outbox processing
  • Distributed coordination

The important code-review point is that a comment saying "fix duplicate issue later" does not solve concurrency.

Removed Dead Code

The commented flush() statement was deleted.

Removed Credential

Sensitive data is not stored in the repository.

Where a Useful Comment Might Be Appropriate

Suppose the SMS provider guarantees only one accepted message for a particular provider idempotency key.

A comment explaining that integration constraint may be appropriate near the idempotency implementation.

The comment should describe the provider contract, not ordinary Java statements.

27. Interview Perspective

Comment-related questions often appear indirectly in senior Java and code-review interviews.

An interviewer may provide code containing dozens of comments and ask:

  • Is this clean code?
  • Which comments should remain?
  • Which comments indicate weak naming?
  • When would you add a comment during code review?
  • Would you allow TODO comments?
  • Why is commented-out code problematic?
  • When should a workaround be documented?
  • How do you prevent comments from becoming outdated?
  • What should Javadoc contain?
  • How would you review comments containing security-sensitive information?

For experienced developers, interviewers usually care less about the statement:

"Comments are good."

They want to hear that comments have a specific purpose.

A strong response is:

Prefer expressive code for normal behavior. Use comments to preserve important context, constraints, decisions, and reasons that cannot be expressed clearly by the code itself.

28. Interview Questions and Answers

Basic Question

Question: When should you write a comment in Java code?

Answer:

Write a comment when important information cannot be communicated clearly through code structure, naming, types, tests, or API design.

Typical examples include:

  • Non-obvious business rules
  • External API limitations
  • Compatibility workarounds
  • Concurrency assumptions
  • Security decisions
  • Performance constraints
  • Temporary migration behavior

Do not comment obvious statements.

Intermediate Question

Question: Why are comments that explain what code does usually considered weak?

Answer:

Well-written code should normally communicate what it does through:

  • Class names
  • Method names
  • Variable names
  • Types
  • Method extraction
  • Clear control flow

A comment such as:

JAVA
// Save customer
customerRepository.save(customer);

duplicates information and increases maintenance effort.

If the implementation changes and the comment does not, the comment may become misleading.

Advanced Question

Question: Can comments reduce maintainability?

Answer:

Yes.

Comments create additional information that developers must keep synchronized with executable code.

Problems include:

  • Outdated comments
  • Incorrect comments
  • Duplicated information
  • Excessive visual noise
  • Dead commented-out code
  • Historical notes that belong in Git
  • Important documentation being hidden among low-value comments

The goal is not maximum comments. It is maximum clarity with minimum unnecessary documentation.

Scenario-Based Question

Question: You see this code during review:

JAVA
// Do not change this timeout.
Duration timeout = Duration.ofSeconds(17);

What would you do?

Answer:

I would ask why 17 seconds is required.

The current comment warns against modification but does not provide enough context.

If the timeout comes from an external dependency, the code could be improved to something like:

JAVA
// Vendor closes idle settlement connections after 20 seconds.
// Use 17 seconds to fail locally before the vendor terminates the socket.
Duration settlementTimeout = Duration.ofSeconds(17);

A configuration property may also be more appropriate depending on the application.

Code-Review Question

Question: A Pull Request contains large blocks of commented-out Java code. Would you approve it?

Answer:

Normally no.

The developer should remove dead code because:

  • Git retains history
  • Commented code creates noise
  • Developers cannot know whether it is intentionally preserved
  • The code may become incompatible with the surrounding implementation
  • Static analysis and tests do not verify commented code

I would request removal unless there is a very unusual and clearly justified temporary reason.

Real-Project Question

Question: Give an example where a comment is important in a Spring Boot application.

Answer:

Suppose an application deliberately avoids retrying HTTP 409 responses because a payment provider treats that status as successful duplicate detection.

The implementation may contain:

JAVA
// Provider returns HTTP 409 when the idempotency key was already processed.
// Do not retry because retrying creates unnecessary duplicate requests.
if (response.statusCode() == HttpStatus.CONFLICT) {
    return PaymentResult.ALREADY_PROCESSED;
}

Without the comment, someone might treat 409 as a generic failure and add automatic retries.

The comment protects an important integration rule.

29. Quick Rule to Remember

If the code explains what, use the comment to explain why. If the comment only repeats the code, remove it.

30. Final Takeaway

Useful comments are not about adding more text to Java files.

They are about preserving information that developers genuinely need to understand the system.

What the Developer Should Remember

Write clean code first.

Use:

  • Meaningful names
  • Small focused methods
  • Clear domain models
  • Explicit error handling
  • Good tests

Then add comments only where meaningful context is still missing.

What the Reviewer Should Check

During Pull Request review, verify that:

  • Comments add information rather than repeat statements.
  • Important business reasons are documented.
  • External-system limitations are understandable.
  • Temporary workarounds are trackable.
  • Comments match current implementation behavior.
  • Commented-out code is removed.
  • Sensitive information is never included.
  • Non-obvious production decisions are preserved for future maintainers.

What Should Be Avoided in Production Code

Avoid:

  • Obvious comments
  • Misleading comments
  • Outdated comments
  • Commented-out code
  • Vague TODOs
  • Developer change logs
  • Sensitive information
  • Comments compensating for poor naming
  • Large explanations that could be replaced with cleaner design

The best production Java code does not need a comment beside every statement.

It uses comments selectively, where the reason behind the code is more important than the syntax visible on the screen.