Documentation

Documentation is not an afterthought — it is a core engineering deliverable. Code without documentation becomes legacy code the moment its author walks away. As a senior developer, the documentation you write falls into a handful of categories, each with a clear purpose and audience.

Code Comments: Good vs Bad

Comments should explain why, not what. If your code needs a comment to explain what it does, the code itself should be rewritten to be clearer. Good comments capture intent, trade-offs, and context that the code alone cannot convey.

Bad comments:

  • Restating the code: i++ // increment i
  • Commented-out code left for “just in case” — use version control instead
  • Outdated comments that no longer match the code (worse than no comment at all)

Good comments:

  • Explaining business logic: // Tax exempt for orders from non-profit orgs (see IRS rule 501c3)
  • Clarifying non-obvious decisions: // Using insertion sort here because n is always < 20
  • Marking known limitations: // TODO: This breaks if the input contains Unicode surrogates
  • Legal or licensing notices required by your organization

Javadoc (Java)

Javadoc is the standard for documenting public APIs in Java. Every public class, method, and interface should have a Javadoc comment. Tools generate browsable HTML documentation directly from these annotations.

/**
 * Transfers funds between two accounts within the same bank.
 * The operation is atomic — both accounts are updated in a single transaction.
 * If either account is frozen, the transfer is rejected.
 *
 * @param fromAccountId  the source account ID
 * @param toAccountId    the destination account ID
 * @param amount         the transfer amount in cents (must be positive)
 * @return the resulting transaction ID
 * @throws InsufficientFundsException if the source account balance is too low
 * @throws AccountFrozenException     if either account is frozen
 */
public String transferFunds(String fromAccountId, String toAccountId, long amount)
        throws InsufficientFundsException, AccountFrozenException {
    // implementation
}

Key rules: document parameters, return values, and exceptions. State preconditions and side effects. Keep the first sentence short — it becomes the summary in generated docs.

Docstrings (Python)

Python uses triple-quoted docstrings following the Google, NumPy, or Sphinx conventions. They serve the same purpose as Javadoc — documenting the contract of your functions and classes.

def retry_with_backoff(func, max_retries=3, base_delay=1.0):
    """Execute a function with exponential backoff on failure.

    Retries the given callable up to max_retries times, doubling
    the delay after each failed attempt. Useful for flaky network
    calls or rate-limited APIs.

    Args:
        func: A callable that takes no arguments and returns a result.
        max_retries: Maximum number of retry attempts. Defaults to 3.
        base_delay: Initial delay in seconds before first retry. Defaults to 1.0.

    Returns:
        The return value of func upon successful execution.

    Raises:
        Exception: Re-raises the last exception if all retries are exhausted.
    """
    delay = base_delay
    for attempt in range(max_retries + 1):
        try:
            return func()
        except Exception:
            if attempt == max_retries:
                raise
            time.sleep(delay)
            delay *= 2

README Files

A README is the front door to your project. Every repository should have one. A solid README answers five questions fast:

  • What does this project do? (one sentence)
  • How do I set it up locally? (prerequisites, install steps)
  • How do I run it? (commands, environment variables)
  • How do I run the tests?
  • How do I contribute? (branch strategy, PR process)

Keep it current. A README that describes a build process from two years ago will actively mislead new developers and waste hours of their time.

API Documentation

If your application exposes an API, document every endpoint with its method, path, request/response format, status codes, and authentication requirements. Use tools like Swagger/OpenAPI for REST APIs or GraphQL introspection for GraphQL. Auto-generated docs from code annotations stay in sync far better than manually maintained wikis.

Architecture Decision Records (ADRs)

An ADR captures a single architectural decision — the context, the options considered, and the rationale for the choice made. They are short (one page), numbered, and stored in the repository alongside the code, typically in a docs/adr/ directory.

ADRs solve a specific problem: six months from now, nobody will remember why you chose PostgreSQL over MongoDB, or why the service uses event sourcing instead of CRUD. ADRs preserve that reasoning so future developers (including your future self) do not revisit settled decisions.

A typical ADR structure:

  • Title: ADR-001: Use PostgreSQL for the billing service
  • Status: Accepted
  • Context: What is the problem or situation?
  • Decision: What did we decide?
  • Consequences: What are the trade-offs?

Key Principles

  • Write for the reader, not yourself. Your audience is a developer joining the team six months from now.
  • Keep docs close to the code. Documentation in the repo gets updated with the code. Documentation in a wiki does not.
  • Automate what you can. Generate API docs from annotations. Generate dependency docs from build files. Manual docs rot.
  • Delete outdated docs. Wrong documentation is worse than no documentation. If it is stale, update it or remove it.
  • Treat docs like code. Review them in PRs. Hold them to a quality standard. Refactor them when they get unwieldy.

Documentation is not overhead — it is leverage. A few hours of writing saves weeks of onboarding, debugging, and re-learning across the lifetime of a project.




Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published. Required fields are marked *