1. Introduction
Comments are useful when they explain information that cannot be understood clearly from the code itself. However, excessive or unnecessary comments make Java code harder to read rather than easier.
In real company projects, developers frequently add comments such as:
// Get customer
Customer customer = customerRepository.findById(customerId).orElseThrow();
// Check if customer is active
if (customer.isActive()) {
processCustomer(customer);
}These comments do not provide new information. They simply repeat what the Java statements already communicate.
Unnecessary comments increase visual noise, create additional maintenance work, and can become incorrect when the code changes.
A clean codebase should rely primarily on:
- Meaningful variable names
- Clear method names
- Small focused methods
- Proper abstractions
- Straightforward control flow
- Appropriate types
Comments should be added only when they provide useful context that cannot reasonably be expressed through the code.
During Pull Request review, reviewers should therefore ask not only:
"Is a comment needed?"
but also:
"Can this comment be removed by making the code clearer?"
2. What This Topic Means
Avoiding unnecessary comments means removing comments that merely describe obvious Java statements or compensate for unclear code.
Consider:
// Create payment request
PaymentRequest request = new PaymentRequest(orderId, amount);The variable and class names already explain what is happening.
The comment adds no useful information.
Instead, comments should provide information such as:
- Why a specific implementation exists
- Why a business rule behaves unexpectedly
- Why an external API requires a workaround
- Why a performance optimization is necessary
- Why a concurrency-related implementation must not be simplified
- Why temporary compatibility logic exists
For example:
// Partner gateway rejects requests older than five minutes, so regenerate the timestamp before retrying.
paymentRequest.refreshTimestamp();This comment provides context that is not obvious from the method call itself.
The objective is not to eliminate all comments.
The objective is to eliminate comments that do not add meaningful information.
3. Why It Matters in Real Projects
Readability
Too many comments interrupt the natural flow of code.
A developer should be able to scan a method and understand its behavior without reading a comment before every statement.
Maintainability
Every comment becomes another piece of information that must be kept synchronized with the code.
When code changes but comments remain unchanged, developers may receive conflicting information.
Debugging
Outdated comments can mislead developers during production incident investigation.
A developer may trust the comment instead of verifying the actual code behavior.
Reliability
Incorrect comments can result in unsafe modifications when developers misunderstand business or technical behavior.
Team Development
Large development teams frequently modify the same services over several years.
Reducing low-value comments makes genuinely important comments easier to notice.
4. Core Concept
The key principle is:
Prefer self-explanatory code over comments that explain obvious implementation details.
Comments should not be used as a substitute for:
- Better variable names
- Better method names
- Smaller methods
- Better class design
- Proper enums
- Domain-specific types
- Clear exception handling
For example:
Bad:
// Check if status is 1
if (order.getStatus() == 1) {
process(order);
}Better:
if (order.getStatus() == OrderStatus.READY_FOR_PROCESSING) {
process(order);
}The better implementation removes the need for the comment entirely.
Another example:
Bad:
// Calculate final price
BigDecimal x = p.subtract(d).add(t);Better:
BigDecimal finalPrice = productPrice
.subtract(discountAmount)
.add(taxAmount);The code itself should communicate normal application behavior.
5. Important Rules
- Do not comment obvious Java statements.
- Do not explain meaningful method names with comments.
- Do not use comments to compensate for poor variable names.
- Do not add comments before every
if, loop, repository call, or return statement. - Remove commented-out production code.
- Avoid comments documenting source-control history.
- Avoid developer-name comments.
- Remove comments that are no longer accurate.
- Prefer extracting complicated logic into a clearly named method.
- Use constants and enums instead of comments explaining magic values.
- Keep comments that explain important business reasons.
- Keep comments that explain external-system limitations.
- Keep comments that document non-obvious concurrency assumptions.
- Keep comments that explain counter-intuitive performance optimizations.
- Never store sensitive production data or credentials inside comments.
- Review comments whenever the related code changes.
6. Bad Code Example
Consider a Spring Boot customer-account service.
@Service
public class CustomerAccountService {
private final CustomerRepository customerRepository;
private final NotificationService notificationService;
public CustomerAccountService(CustomerRepository customerRepository, NotificationService notificationService) {
this.customerRepository = customerRepository;
this.notificationService = notificationService;
}
public void deactivateCustomer(Long id) {
// Find customer by ID
Customer c = customerRepository.findById(id).orElseThrow();
// Check if customer is already inactive
if (!c.isActive()) {
// Return if inactive
return;
}
// Set active false
c.setActive(false);
// Save customer
customerRepository.save(c);
// Send notification
notificationService.sendAccountDeactivatedNotification(c);
// TODO check later
// customerRepository.flush();
}
}The method contains many comments, but almost none provide useful information.
7. Problems in the Bad Code
Redundant Comments
Comments such as:
// Find customer by ID
// Save customer
// Send notificationsimply repeat the statements below them.
Weak Variable Naming
The variable:
Customer cis unnecessarily abbreviated.
A meaningful name such as:
Customer customermakes the code clearer without comments.
Comment Explaining Control Flow
This comment:
// Return if inactiveadds no information because the return statement is obvious.
Weak TODO
// TODO check laterdoes not explain:
- What needs to be checked
- Why it matters
- Who should address it
- Whether it is tracked
- What production behavior may be affected
Commented-Out Code
// customerRepository.flush();is dead code.
Source control already preserves previous implementations.
Missing Domain-Specific Exception
orElseThrow() generates a generic exception rather than communicating a meaningful application failure.
8. Code Review Findings
A senior Java reviewer should identify the following:
- Most comments simply translate Java statements into English.
- The code would be clearer with better variable naming.
- Several comments should be deleted rather than improved.
- The TODO is not actionable.
- Commented-out repository code should not remain in production source.
- Customer-not-found behavior should be explicit.
- The method should communicate business intent through code first.
- No genuinely complex business behavior exists that requires this many comments.
The reviewer should avoid requesting additional comments.
The correct recommendation is to simplify the source and remove unnecessary documentation.
9. Reviewer Comment Example
A professional Pull Request comment could be:
Most of these comments repeat what the code already expresses. Could we remove them and use a more descriptive variable name such as
customerinstead ofc?
Another review comment:
Please remove the commented-out
flush()call. Git history already preserves previous implementations, and keeping dead code here creates unnecessary noise.
For the TODO:
Can we either link this TODO to a tracked issue and explain the expected follow-up, or remove it if no concrete action is required?
10. Improved Code
@Service
public class CustomerAccountService {
private final CustomerRepository customerRepository;
private final NotificationService notificationService;
public CustomerAccountService(CustomerRepository customerRepository, NotificationService notificationService) {
this.customerRepository = customerRepository;
this.notificationService = notificationService;
}
public void deactivateCustomer(Long customerId) {
Customer customer = customerRepository.findById(customerId)
.orElseThrow(() -> new CustomerNotFoundException(customerId));
if (!customer.isActive()) {
return;
}
customer.deactivate();
customerRepository.save(customer);
notificationService.sendAccountDeactivatedNotification(customer);
}
}The improved implementation does not need comments because the code communicates the behavior clearly.
11. Improved Code Explanation
Better Parameter Name
id became:
customerIdThis gives immediate domain context.
Better Variable Name
c became:
customerNo comment is required to explain what the variable represents.
Domain-Specific Exception
Instead of:
orElseThrow()the code now throws:
CustomerNotFoundExceptionThis makes failure behavior clearer.
Domain Method
Instead of:
customer.setActive(false);the code uses:
customer.deactivate();This expresses business intent rather than exposing a low-level state mutation.
Redundant Comments Removed
The implementation is now easier to scan because each statement is self-explanatory.
Dead Code Removed
The commented-out flush() statement no longer distracts future developers.
12. Bad Code vs Improved Code
| Area | Bad Code | Improved Code |
|---|---|---|
| Readability | Many comments interrupt code flow | Code explains itself |
| Maintainability | Comments must be updated with code | Less duplicated information |
| Testability | Similar behavior | Clearer domain operations simplify test intent |
| Reliability | Generic exception and vague TODO | Explicit failure behavior |
| Reviewability | Reviewer must inspect comment noise | Business behavior is immediately visible |
Performance is effectively unchanged because removing comments does not alter runtime execution.
The improvement is primarily in readability and maintainability.
13. Real Project Scenario
Consider an e-commerce inventory microservice.
A developer writes:
// Loop through products
for (Product product : products) {
// Check stock
if (product.getAvailableQuantity() > 0) {
// Add product
availableProducts.add(product);
}
}Every comment is unnecessary.
The code already describes the operation.
A cleaner implementation could be:
List<Product> availableProducts = products.stream()
.filter(Product::isAvailable)
.toList();Or, when a loop is clearer:
for (Product product : products) {
if (product.isAvailable()) {
availableProducts.add(product);
}
}Now suppose an unusual rule exists:
// Marketplace listings must remain visible for 10 minutes after stock reaches zero because partner inventory updates are eventually consistent.
if (product.hasRecentlyReachedZeroStock()) {
keepListingVisible(product);
}That comment is useful because it explains a non-obvious business reason.
The distinction is important.
Normal code does not need narration.
Unexpected behavior may need explanation.
14. Production Impact
Unnecessary comments usually do not directly cause application failures, but they create long-term engineering risks.
Difficult Maintenance
Large classes containing hundreds of redundant comments become slower to understand.
Outdated Documentation
Code may change while comments remain unchanged.
For example:
// Retry three times
for (int attempt = 0; attempt < 5; attempt++) {
retryRequest();
}A future developer now receives contradictory information.
Incorrect Debugging
During an incident, developers may rely on inaccurate comments and investigate the wrong behavior.
Hidden Important Information
If every statement has a comment, genuinely important comments are difficult to notice.
Unsafe Refactoring
A misleading comment may cause developers to preserve incorrect logic or modify correct logic based on outdated assumptions.
15. Common Developer Mistakes
Commenting Every Statement
Example:
// Create request
PaymentRequest request = createRequest();
// Validate request
validate(request);
// Process request
process(request);These comments provide no additional value.
Writing Comments Instead of Renaming Variables
Bad:
// Customer email
String e = customer.getEmail();Better:
String customerEmail = customer.getEmail();Explaining Magic Values With Comments
Bad:
if (retryCount > 5) { // Maximum retries
fail();
}Better:
private static final int MAX_RETRY_ATTEMPTS = 5;
if (retryCount > MAX_RETRY_ATTEMPTS) {
fail();
}Commenting Closing Braces
Avoid unnecessary constructs such as:
} // end if
} // end methodWell-structured Java code should make scopes easy to understand.
Keeping Old Implementations as Comments
Bad:
// oldPaymentService.process(payment);
newPaymentService.process(payment);Delete the old implementation.
Writing Author Comments
Avoid:
// Added by Dattatray on 08-08-2026Source control already records this information.
Writing Change History Inside Classes
Avoid source comments containing a manual change log.
Use:
- Git history
- Pull Requests
- Jira
- Azure Boards
- Issue trackers
Using Comments to Explain Large Methods
If a method requires comments such as:
// Step 1
// Step 2
// Step 3
// Step 4it may indicate that the method should be decomposed into smaller methods.
16. Edge Cases
Traditional runtime edge cases are not directly created by unnecessary comments, but reviewers should consider maintenance-related edge cases.
Comment Becomes Outdated
The most common issue occurs when behavior changes without updating the comment.
Business Rule Changes
A comment may describe an old business policy that is no longer valid.
Temporary Workarounds
A comment describing temporary logic can become permanent unless the removal condition is clear.
External Integration Changes
A comment describing an API limitation may become invalid after a vendor upgrade.
Concurrency Logic
Removing a comment explaining thread-safety assumptions may make future refactoring dangerous.
Therefore, the objective is not automatic comment deletion.
Reviewers must distinguish unnecessary comments from comments containing essential context.
17. Performance Considerations
Comments do not meaningfully affect Java runtime performance because comments are removed during compilation and are not executed by the JVM.
Therefore, unnecessary comments are primarily a readability and maintenance issue rather than a performance issue.
However, comments may legitimately explain performance-sensitive implementation decisions.
For example:
// Fetch only IDs because loading full entities here previously caused excessive heap usage during the nightly 3M-record batch.
List<Long> customerIds = customerRepository.findInactiveCustomerIds();This comment is useful.
Without the explanation, a future developer may replace the optimized projection with a full entity query.
Avoid comments such as:
// This is fasterInstead, explain the actual reason:
- Large dataset
- Database round trips
- Vendor throttling
- Heap usage
- Query-plan behavior
- Measured latency
18. Security Considerations
Unnecessary comments can become a security issue when developers place sensitive data inside them.
Never commit comments containing:
- Passwords
- API keys
- JWT secrets
- Database credentials
- Private keys
- Access tokens
- Real customer records
- Internal security bypass instructions
Bad:
// Temporary production password: Prod@123Deleting such a comment later may not completely solve the problem because the secret could remain in Git history.
The credential should be rotated.
Comments can still be useful for security-sensitive design decisions.
Example:
// Tenant ID must come from the authenticated principal, never from request payload data.
String tenantId = currentUser.getTenantId();This comment explains an important authorization rule.
19. Testing Considerations
Removing unnecessary comments normally does not require new tests because comments are not executable.
However, refactoring code to make it self-explanatory may involve:
- Renaming methods
- Extracting methods
- Introducing domain methods
- Replacing magic values with constants
- Simplifying conditions
Existing tests should confirm that business behavior remains unchanged.
Unit Tests
Verify important business behavior.
For the customer-deactivation example:
- Active customer becomes inactive.
- Already inactive customer is ignored.
- Missing customer produces the expected exception.
- Notification is sent after successful deactivation.
Integration Tests
Where repository behavior matters, verify persistence state using an integration test.
Important Principle
Comments should never replace tests.
Bad:
// Customer cannot be null here.Better:
Define and test the actual contract.
20. Refactoring Guidelines
When removing unnecessary comments from existing Java code:
- Read the comment and associated implementation.
- Determine whether the comment explains
whatorwhy. - Do not immediately delete comments explaining important business context.
- Rename unclear variables.
- Rename unclear methods.
- Extract complicated blocks into focused methods.
- Replace magic numbers with named constants.
- Replace primitive status codes with enums where appropriate.
- Remove commented-out code.
- Remove manual source-history comments.
- Verify old TODOs against the issue tracker.
- Run automated tests after structural refactoring.
- Review Git history if a strange comment appears to protect unusual production behavior.
- Keep comments that document genuinely non-obvious constraints.
The safest approach is:
Improve the code first, then evaluate whether the comment is still necessary.
21. Best Practices
Use Meaningful Names
Instead of:
// Calculate customer discount
BigDecimal d = calculate(c);Use:
BigDecimal customerDiscount = calculateDiscount(customer);Extract Methods Instead of Writing Section Comments
Instead of:
// Validate request
...
// Create payment
...
// Save payment
...use:
validatePaymentRequest(request);
Payment payment = createPayment(request);
paymentRepository.save(payment);Use Domain Methods
Instead of:
// Mark invoice as paid
invoice.setStatus(InvoiceStatus.PAID);prefer:
invoice.markAsPaid();when the domain model supports the behavior.
Replace Magic Values
Instead of:
if (attempts == 3) { // Max retry count
return;
}prefer:
private static final int MAX_RETRY_ATTEMPTS = 3;Explain Genuine Constraints
Keep comments explaining information such as:
// Vendor accepts no more than 100 customer IDs per API request.
List<List<Long>> batches = partition(customerIds, 100);Review Comments Like Code
Comments should be checked for:
- Accuracy
- Relevance
- Security
- Maintainability
- Continued necessity
22. Practices to Avoid
Narrating Java Syntax
Avoid:
// Increment count
count++;The code is obvious.
Comments Before Clear Method Calls
Avoid:
// Validate order
validateOrder(order);The method name already explains the action.
Commented-Out Code
Avoid:
// oldRepository.save(entity);Delete it.
Vague TODOs
Avoid:
// TODO improveNo developer knows what "improve" means.
Manual History
Avoid:
// Changed by John
// Modified by Mike
// Fixed by SarahUse Git.
Comments Explaining Poor Names
Avoid:
String x; // Customer account numberRename the variable.
Long Comments Hiding Poor Design
If a comment needs several paragraphs to explain a method's flow, consider restructuring the method.
Duplicate Javadoc
Avoid:
/**
* Gets customer name.
* @return customer name
*/
public String getCustomerName() {
return customerName;
}Unless the API contract contains non-obvious information, this documentation adds little value.
23. Code Review Checklist
- Does this comment provide information that the code cannot communicate clearly?
- Is the comment merely describing the statement below it?
- Could better variable naming eliminate this comment?
- Could a better method name eliminate this comment?
- Could extracting a method remove the need for this explanation?
- Is the comment still accurate?
- Does the comment explain why rather than what?
- Is there commented-out code that should be deleted?
- Does the TODO contain actionable information?
- Should the TODO reference a tracked issue?
- Is source-control history being duplicated inside the source file?
- Are developer names or dates unnecessarily stored in comments?
- Does any comment contain sensitive information?
- Are magic values being explained through comments instead of constants?
- Are status codes being explained instead of represented by enums?
- Is an important business constraint being lost if this comment is removed?
- Is a performance optimization documented only where genuinely needed?
- Are concurrency assumptions documented where appropriate?
- Are external API limitations clearly explained?
- Would the code remain understandable if this unnecessary comment were deleted?
24. Common Pull Request Review Comments
- *This comment repeats what the method name already communicates. Can we remove it?*
- *Could we rename
ctocustomerinstead of relying on the comment to explain the variable?*
- *The implementation is clear without this comment. Removing it would reduce noise and maintenance overhead.*
- *Please remove the commented-out code. Git history already preserves the previous implementation.*
- *Can we replace this magic value with a named constant instead of explaining it through a comment?*
- *This TODO is not actionable. Please reference the tracking issue and describe the required follow-up.*
- *The comment no longer matches the current condition. Please update or remove it so it does not mislead future maintainers.*
- *These section comments suggest that this method may be doing too much. Could we extract these blocks into well-named methods?*
- *Please avoid adding the developer name/date here; Git already tracks authorship and change history.*
- *This comment explains an important vendor limitation and is useful. Please keep it, but consider adding the related ticket/reference for additional context.*
25. Code Review Exercise
Review the following Spring Boot payment-processing code.
Identify:
- Unnecessary comments
- Poor naming
- Code smells
- Maintainability problems
- Potential risks
- Better refactoring opportunities
Do not reveal the solution until completing your review.
@Service
public class PaymentProcessor {
private final PaymentRepository paymentRepository;
private final PaymentGateway paymentGateway;
public PaymentProcessor(PaymentRepository paymentRepository, PaymentGateway paymentGateway) {
this.paymentRepository = paymentRepository;
this.paymentGateway = paymentGateway;
}
public void process(Long id) {
// Get payment
Payment p = paymentRepository.findById(id).orElseThrow();
// Check if payment is already processed
if (p.getStatus() == PaymentStatus.COMPLETED) {
// Return
return;
}
// Maximum retry count
int x = 3;
// Try payment three times
for (int i = 0; i < x; i++) {
// Call gateway
PaymentResponse r = paymentGateway.charge(p);
// Check success
if (r.isSuccessful()) {
// Set status
p.setStatus(PaymentStatus.COMPLETED);
// Save
paymentRepository.save(p);
// Return
return;
}
}
// Set failed
p.setStatus(PaymentStatus.FAILED);
// Save failed payment
paymentRepository.save(p);
// TODO handle this properly later
// paymentRepository.flush();
}
}26. Exercise Solution
Issue 1: Excessive Statement Comments
Comments such as:
// Get payment
// Check success
// Save
// Returndo not add useful information.
Issue 2: Weak Variable Names
These variables are unclear:
p
x
i
rWhile i is acceptable for a small loop index, the important domain variables should be meaningful.
Use:
payment
maxRetryAttempts
paymentResponseIssue 3: Magic Configuration
The retry limit is stored as:
int x = 3;A named constant or configuration property communicates intent better.
Issue 4: Comment Explaining Magic Value
// Maximum retry count
int x = 3;The comment is being used because the variable name is poor.
Rename the value instead.
Issue 5: Retry Logic Inside Main Method
The retry loop makes the business method more difficult to read.
A focused helper method can communicate the behavior without section comments.
Issue 6: Generic Missing-Payment Exception
Use a domain-specific exception.
Issue 7: Vague TODO
// TODO handle this properly laterprovides no actionable information.
Issue 8: Commented-Out Code
// paymentRepository.flush();should be deleted.
Improved Code
@Service
public class PaymentProcessor {
private static final int MAX_PAYMENT_ATTEMPTS = 3;
private final PaymentRepository paymentRepository;
private final PaymentGateway paymentGateway;
public PaymentProcessor(PaymentRepository paymentRepository, PaymentGateway paymentGateway) {
this.paymentRepository = paymentRepository;
this.paymentGateway = paymentGateway;
}
public void process(Long paymentId) {
Payment payment = paymentRepository.findById(paymentId)
.orElseThrow(() -> new PaymentNotFoundException(paymentId));
if (payment.getStatus() == PaymentStatus.COMPLETED) {
return;
}
if (chargePayment(payment)) {
payment.markCompleted();
} else {
payment.markFailed();
}
paymentRepository.save(payment);
}
private boolean chargePayment(Payment payment) {
for (int attempt = 1; attempt <= MAX_PAYMENT_ATTEMPTS; attempt++) {
PaymentResponse paymentResponse = paymentGateway.charge(payment);
if (paymentResponse.isSuccessful()) {
return true;
}
}
return false;
}
}Why This Is Better
Comments Are No Longer Needed for Obvious Behavior
The method names communicate intent:
chargePayment(payment)
payment.markCompleted()
payment.markFailed()Named Constant Replaces Comment
Instead of:
int x = 3;the code uses:
MAX_PAYMENT_ATTEMPTSClear Domain Names
The implementation is easier to understand without explanatory comments.
Smaller Method
Retry behavior has been extracted into:
chargePayment()The main process() method now reads like a high-level business workflow.
Domain-Specific Exception
Missing-payment behavior is explicit.
Dead Code Removed
The commented repository operation is gone.
Important Production Note
In a real payment system, simply retrying a charge may create duplicate transactions unless the payment gateway supports idempotency.
If the provider requires a specific idempotency mechanism, that would be an appropriate place for a useful comment.
For example:
// Reuse the same idempotency key across retries so the provider cannot create duplicate charges.
PaymentResponse paymentResponse = paymentGateway.charge(payment);This explains a critical integration requirement rather than obvious Java syntax.
27. Interview Perspective
Avoiding unnecessary comments commonly appears in senior Java and code-review interviews as part of clean-code discussions.
An interviewer may provide a method with comments before every line and ask:
- Is this well-documented code?
- Which comments would you remove?
- When should comments be retained?
- How would you make this method self-explanatory?
- Why is commented-out code problematic?
- When is a TODO acceptable?
- Can comments become a maintenance risk?
- How can naming reduce comments?
- When should a performance-related comment remain?
- How would you review an important workaround comment?
A strong senior-level answer should distinguish between:
Code narration
and:
Context documentation
Code narration usually adds little value.
Context documentation may be extremely valuable.
28. Interview Questions and Answers
Basic Question
Question: Why should Java developers avoid unnecessary comments?
Answer:
Because comments that simply repeat code:
- Add visual noise
- Increase maintenance effort
- Can become outdated
- Make important comments harder to notice
- Often hide poor naming or design
Readable code should communicate normal behavior directly.
Intermediate Question
Question: How can you remove the need for comments?
Answer:
Use:
- Meaningful variable names
- Clear method names
- Small focused methods
- Domain methods
- Named constants
- Enums
- Explicit exception types
- Simple control flow
For example:
Instead of:
// Maximum retry count
int x = 3;use:
int maxRetryAttempts = 3;or preferably:
private static final int MAX_RETRY_ATTEMPTS = 3;Advanced Question
Question: Are comments always a code smell?
Answer:
No.
Comments become valuable when they document information that cannot be expressed clearly through code.
Examples include:
- External API constraints
- Legacy-system workarounds
- Non-obvious business rules
- Concurrency assumptions
- Security decisions
- Performance constraints
- Migration compatibility logic
The presence of a comment is not automatically bad.
The important question is whether the comment adds unique and accurate information.
Scenario-Based Question
Question: You see this code during review:
// Wait 2 seconds
Thread.sleep(2000);What would you recommend?
Answer:
The comment is not useful because the statement already communicates the delay.
I would first investigate why the application needs to wait two seconds.
If it represents an external constraint, the intent should be explicit.
For example:
// Vendor reporting API exposes newly uploaded files with up to a two-second consistency delay.
Thread.sleep(REPORT_VISIBILITY_DELAY_MS);However, blocking with Thread.sleep() in application logic should also be reviewed carefully because another retry or asynchronous design may be more appropriate.
Code-Review Question
Question: Should commented-out Java code be kept in a Pull Request?
Answer:
Normally no.
Source control already stores previous versions.
Commented-out code:
- Creates noise
- Becomes stale
- Is not compiled
- Is not tested
- Confuses future maintainers
It should generally be deleted.
Real-Project Question
Question: Give an example of a comment that should remain in production code.
Answer:
Consider an external payment API:
// HTTP 409 means the idempotency key was processed previously.
// Treat it as an already-completed payment rather than retrying the charge.
if (response.statusCode() == HttpStatus.CONFLICT) {
return PaymentResult.ALREADY_PROCESSED;
}The Java condition itself cannot explain the vendor-specific meaning of HTTP 409.
The comment therefore preserves important integration knowledge.
29. Quick Rule to Remember
If a comment only tells you what the next line does, improve the code and remove the comment. Keep comments that explain why non-obvious code exists.
30. Final Takeaway
Avoiding unnecessary comments is an important part of writing maintainable Java code.
The goal is not to produce comment-free applications.
The goal is to ensure every comment earns its place.
What the Developer Should Remember
Developers should first make code understandable through:
- Meaningful names
- Small methods
- Clear domain concepts
- Constants
- Enums
- Explicit exceptions
- Simple control flow
Only then should comments be added where important context is still missing.
What the Reviewer Should Check
During Pull Request review, check whether:
- Comments duplicate code.
- Naming can replace comments.
- Complex methods should be refactored instead of narrated.
- Comments are accurate.
- TODOs are actionable.
- Dead commented-out code has been removed.
- Important business or technical constraints remain documented.
- Sensitive information is absent.
What Should Be Avoided in Production Code
Avoid:
- Comments before obvious statements
- Comments explaining poor variable names
- Comments explaining magic values that should be constants
- Commented-out code
- Manual change logs
- Developer-name comments
- Vague TODO comments
- Outdated comments
- Sensitive information in comments
- Excessive Javadoc that duplicates method signatures
Clean Java code should explain normal behavior through the implementation itself.
Comments should be reserved for information that future developers would otherwise be unable to discover easily.
The best comment is not the one that explains complicated code. Often, the better solution is to simplify the code so that the comment is no longer necessary.