Code Documentation Excellence
Code Documentation Excellence
Write code documentation that developers actually read and find useful—from API references to error messages to changelogs
Table of Contents
🎯 Introduction
Code documentation occupies a unique position—it lives at the intersection of technical precision and human communication. Developers read it while debugging at 2 AM, implementing features under deadline pressure, or trying to understand code they wrote six months ago.
This article covers:
- API references - Structured documentation for functions, classes, and endpoints
- Inline comments - When and how to comment within code
- Code examples - Patterns for effective documentation examples
- Error messages - Writing errors that help rather than frustrate
- Changelogs - Communicating changes clearly to users
- READMEs - First impressions that set projects up for success
Prerequisites: Understanding of writing style principles and documentation structure.
📡 API reference documentation
API reference documentation must be simultaneously comprehensive (complete information) and scannable (quickly findable). This creates a unique writing challenge.
Anatomy of good API documentation
Each API element (function, method, endpoint) should include:
1. Signature/Syntax
def create_user(name: str, email: str, role: str = "user") -> User:2. Brief description (one line) > Creates a new user account with the specified attributes.
3. Detailed description (if needed) > Creates a new user account and sends a welcome email. The user is assigned the default permission set for their role. If the email already exists, raises DuplicateUserError.
4. Parameters | Parameter | Type | Required | Description | |———–|——|———-|————-| | name | str | Yes | User’s display name (2-50 characters) | | email | str | Yes | Valid email address | | role | str | No | User role. Default: "user". Options: "user", "admin" |
5. Return value > Returns: User - The newly created user object with id, name, email, role, and created_at fields populated.
6. Exceptions/Errors | Exception | Condition | |———–|———–| | DuplicateUserError | Email already registered | | ValidationError | Invalid name or email format | | PermissionError | Caller lacks user creation permission |
7. Example
user = create_user(
name="Alice Developer",
email="alice@example.com",
role="admin"
)
print(f"Created user {user.id}: {user.name}")8. Related items > See also: delete_user(), update_user(), get_user()
REST API documentation pattern
## POST /users
Creates a new user account.
### Request
**Headers**
| Header | Value | Required |
|--------|-------|----------|
| `Authorization` | `Bearer {token}` | Yes |
| `Content-Type` | `application/json` | Yes |
**Body Parameters**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Display name (2-50 chars) |
| `email` | string | Yes | Valid email address |
| `role` | string | No | `"user"` (default) or `"admin"` |
**Example Request**
```bash
curl -X POST https://api.example.com/users \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "email": "alice@example.com"}'Response
Success (201 Created)
{
"id": "usr_123abc",
"name": "Alice",
"email": "alice@example.com",
"role": "user",
"created_at": "2026-01-14T10:30:00Z"
}Errors | Status | Code | Description | |——–|——|————-| | 400 | INVALID_EMAIL | Email format invalid | | 409 | EMAIL_EXISTS | Email already registered | | 401 | UNAUTHORIZED | Invalid or missing token |
### API documentation anti-patterns
❌ **Missing parameter details:**
```markdown
## create_user(name, email, role)
Creates a user.
What are the types? What values are valid? What happens if something’s wrong?
❌ No examples:
Parameters: name (string), email (string), role (string)
Returns: User objectShow me what it looks like in practice.
❌ Incomplete error documentation:
Throws: ErrorWhat kind of error? When? What should I do about it?
API documentation from major projects
Microsoft Azure SDK pattern:
- Summary + detailed description
- Parameters with types, defaults, constraints
- Return value with type and description
- Exceptions with conditions
- Multiple examples (basic, advanced, error handling)
- Thread safety notes
- Version availability
Stripe API pattern:
- Interactive examples you can run
- Multiple language examples side-by-side
- Response objects fully documented
- Error codes searchable
- Idempotency key documentation
- Pagination guidance
💬 Inline code comments
Comments in code serve different purposes than external documentation. They explain why, not what.
The golden rule
Code tells you how; comments tell you why.
✅ Good comment (explains why):
# Use insertion sort for small arrays (<10 elements)
# because quicksort's overhead outweighs its benefits
if len(array) < 10:
return insertion_sort(array)❌ Bad comment (restates code):
# Check if length is less than 10
if len(array) < 10:
# Return insertion sort result
return insertion_sort(array)When to comment
Comment when:
- Explaining non-obvious decisions
- Documenting workarounds for bugs (with issue links)
- Clarifying complex algorithms
- Warning about non-obvious side effects
- Noting performance implications
Don’t comment when:
- Code is self-explanatory
- Comment would just repeat variable/function names
- Better solution is to rename or refactor
Documentation string standards
Python (PEP 257 / Google style):
def function(arg1, arg2):
"""Summary line (one line).
Extended description if needed. Can span
multiple paragraphs.
Args:
arg1: Description of arg1.
arg2: Description of arg2.
Returns:
Description of return value.
Raises:
ErrorType: When this error occurs.
"""C# (XML documentation):
/// <summary>
/// Creates a new user account with the specified attributes.
/// </summary>
/// <param name="name">User's display name (2-50 characters)</param>
/// <param name="email">Valid email address</param>
/// <returns>The newly created user object</returns>
/// <exception cref="DuplicateUserException">Email already registered</exception>
public User CreateUser(string name, string email)JavaScript (JSDoc):
/**
* Creates a new user account.
* @param {string} name - User's display name
* @param {string} email - Valid email address
* @returns {User} The newly created user
* @throws {DuplicateUserError} If email exists
*/
function createUser(name, email) {📝 Code examples in documentation
Code examples are often the most-read part of documentation. Users scan to examples, copy them, modify them. Good examples make or break developer experience.
Example characteristics
Complete: Can be copied and run with minimal modification Realistic: Resembles actual use cases, not abstract demos Progressive: Start simple, build complexity Commented: Explain non-obvious parts Tested: Verified to work (ideally via automated testing)
Example patterns
Pattern 1: Basic → Advanced progression
### Basic Usage
Get a single user by ID:
```python
user = client.get_user("usr_123")
print(user.name)With Error Handling
try:
user = client.get_user("usr_123")
print(user.name)
except NotFoundError:
print("User not found")
except AuthenticationError:
print("Check your API key")Async Usage
async def fetch_user(user_id):
async with AsyncClient(api_key=KEY) as client:
return await client.get_user(user_id)
**Pattern 2: Before/After transformation**
```markdown
### Before: Manual HTTP requests
```python
import requests
response = requests.get(
"https://api.example.com/users/123",
headers={"Authorization": f"Bearer {token}"}
)
user = response.json()
After: Using our SDK
user = client.get_user("usr_123")
**Pattern 3: Common scenarios**
```markdown
## Common Tasks
### Create a user and send welcome email
```python
user = client.create_user(name="Alice", email="alice@example.com")
client.send_welcome_email(user.id)
Bulk import users from CSV
with open("users.csv") as f:
for row in csv.DictReader(f):
client.create_user(name=row["name"], email=row["email"])
### Example anti-patterns
❌ **Incomplete example:**
```python
# Create a user
user = create_user(...)
What arguments? What imports are needed?
❌ Unrealistic example:
user = create_user("foo", "bar", "baz")What are foo, bar, baz? Use realistic values.
❌ Too much in one example:
# 50-line example doing five different thingsBreak into focused examples.
❌ Examples that don’t work:
# Example written but never tested
# Contains syntax error on line 3Test all examples before publishing.
Multi-language examples
For APIs used from multiple languages, provide examples in common languages:
<details>
<summary>Python</summary>
```python
user = client.get_user("usr_123")JavaScript
const user = await client.getUser("usr_123");cURL
curl https://api.example.com/users/usr_123 \
-H "Authorization: Bearer $TOKEN"
## ⚠️ Error message design
Error messages are documentation that appears when something goes wrong—precisely when users need the most help.
### Good error messages
**Components of a helpful error:**
1. **What happened** - Clear description of the problem
2. **Why it happened** - Context about the cause
3. **What to do** - Actionable next steps
### Error message patterns
**Pattern: Full context**
Error: Cannot connect to database Cause: Connection refused at localhost:5432 Action: Ensure PostgreSQL is running: systemctl start postgresql
**Pattern: With error codes**
Error [AUTH_001]: Invalid authentication token The token has expired or is malformed. Get a new token: https://docs.example.com/auth
**Pattern: Multiple possible causes**
Error: Build failed
Possible causes:
- Missing dependencies - Run
npm install - Invalid configuration - Check tsconfig.json syntax
- Network issue - Verify proxy settings
For detailed logs: build-output.log
### Error message anti-patterns
❌ **Cryptic:**
Error: ECONNREFUSED
*What refused? How do I fix it?*
❌ **Blaming the user:**
Error: You entered an invalid email
*Use neutral language: "Invalid email format"*
❌ **Too technical:**
NullPointerException at com.example.service.UserService.createUser(UserService.java:142)
*For end users, wrap in friendly message*
❌ **No path forward:**
Error: Operation failed
*What operation? What should I try?*
### Error documentation
Document errors in your API reference:
```markdown
## Errors
### AuthenticationError
Raised when authentication fails.
**Causes:**
- Invalid API key
- Expired token
- Revoked credentials
**Resolution:**
1. Verify API key in dashboard
2. Generate new token if expired
3. Contact support if credentials revoked
**Example:**
```python
try:
client.create_user(...)
except AuthenticationError as e:
print(f"Auth failed: {e.message}")
print(f"Error code: {e.code}")
# e.code will be one of: INVALID_KEY, EXPIRED_TOKEN, REVOKED
## 📋 Changelog and release notes
Changelogs communicate what changed between versions. They serve multiple audiences: developers upgrading, managers evaluating, and security teams auditing.
### Keep a Changelog format
The [Keep a Changelog](https://keepachangelog.com/) standard provides a proven format:
```markdown
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- French translation
## [1.1.0] - 2026-01-14
### Added
- OAuth 2.0 authentication support
- Rate limiting configuration options
### Changed
- Improved error messages with error codes
- Updated minimum Python version to 3.9
### Deprecated
- API key authentication (use OAuth instead)
### Fixed
- Memory leak in connection pooling (#234)
- Incorrect date parsing for ISO 8601 (#256)
### Security
- Updated dependencies to address CVE-2026-1234
## [1.0.0] - 2025-12-01
### Added
- Initial release
Change categories
- Added - New features
- Changed - Changes to existing functionality
- Deprecated - Features to be removed in future
- Removed - Features removed in this release
- Fixed - Bug fixes
- Security - Security-related changes
Writing good changelog entries
✅ Good entries:
### Added
- OAuth 2.0 support with authorization code and client credentials flows
### Fixed
- Connection timeout now properly respects configured value (#234)
### Security
- Updated `requests` to 2.28.0 to address SSRF vulnerability (CVE-2026-1234)❌ Bad entries:
### Changed
- Various improvements
- Bug fixes
- Updated dependenciesChangelog vs. release notes
Changelog: Complete record of all changes, primarily for developers Release notes: Curated highlights for broader audience
# Release Notes - v1.1.0
## Highlights
**OAuth 2.0 Support** 🎉
We've added full OAuth 2.0 authentication! Migrate from API keys for better security.
[Migration guide →](./oauth-migration.md)
**Better Error Messages**
All errors now include error codes and actionable suggestions.
## Breaking Changes
None in this release.
## Upgrade Notes
- Minimum Python version is now 3.9
- API key authentication is deprecated (removed in v2.0)
[Full changelog →](./CHANGELOG.md#110---2026-01-14)📄 README files
The README is often the first documentation users see. It must quickly convey what a project does and how to get started.
README structure
# Project Name
One-paragraph description: what it does, who it's for.
## Features
- Feature 1
- Feature 2
## Quick Start
```bash
pip install project-namefrom project import Client
client = Client(api_key="...")
result = client.do_thing()Documentation
Installation
Detailed installation instructions…
Usage
More detailed usage examples…
Contributing
License
MIT License - see LICENSE
### README best practices
**1. Lead with value**
- What problem does this solve?
- Why would someone use this?
**2. Show, don't tell**
- Include working code example in first 30 seconds of reading
- Use badges for build status, version, etc.
**3. Make it scannable**
- Clear headings
- Bullet lists
- Code blocks
**4. Keep it current**
- README lies are worse than no README
- Automate what you can (version badges, etc.)
### README for this repository
From [README.md](../../README.md):
- **Purpose statement:** What this repository contains
- **Structure overview:** How content is organized
- **Getting started:** Links to setup documentation
- **Navigation aids:** Links to key sections
## ⚙️ Documentation generators
Many languages have documentation generators that produce reference documentation from code comments.
### Popular documentation generators
| Language | Tool | Comment Style |
|----------|------|---------------|
| Python | Sphinx, pdoc | Docstrings (various formats) |
| JavaScript | JSDoc, TypeDoc | JSDoc comments |
| C# | DocFX, Sandcastle | XML comments |
| Java | Javadoc | Javadoc comments |
| Go | godoc | Standard comments |
| Rust | rustdoc | Documentation comments |
### Documentation generator best practices
**1. Write for both human and machine readers**
```python
def create_user(name: str, email: str) -> User:
"""
Create a new user account.
This function validates the email format and checks for duplicates
before creating the user record. A welcome email is sent automatically.
Args:
name: User's display name. Must be 2-50 characters.
email: Valid email address. Must not already be registered.
Returns:
User: The newly created user with populated id and timestamps.
Raises:
ValidationError: If name or email format is invalid.
DuplicateUserError: If email is already registered.
Example:
>>> user = create_user("Alice", "alice@example.com")
>>> print(user.id)
'usr_abc123'
"""
2. Use type hints/annotations
# Types in signature help generators produce better documentation
def get_users(
limit: int = 10,
offset: int = 0,
role: Optional[str] = None
) -> List[User]:3. Document at the right level
- Public API: Full documentation
- Internal API: Brief documentation
- Private helpers: Minimal or none
4. Keep generated docs with source
- Version control generated documentation
- Or regenerate as part of CI/CD
📌 Applying code documentation standards to this repository
This repository’s code
IQPilot MCP Server (from src/IQPilot/):
- C# XML documentation comments
- README with setup instructions
- Inline comments for complex logic
PowerShell Scripts (from scripts/):
- Comment-based help
- README.md for the scripts folder
Documentation standards by file type
| File Type | Documentation Standard |
|---|---|
.cs |
XML documentation comments |
.py |
Google-style docstrings |
.ps1 |
Comment-based help |
.md |
N/A (is documentation) |
.json/.yml |
Inline comments where supported |
Code example standards
For documentation in this repository:
Include language identifier:
```python
# Not just ``` but ```pythonShow realistic values:
# Not foo/bar but realistic data
user = create_user(name="Alice Developer", email="alice@example.com")Indicate placeholder values:
client = APIClient(api_key="YOUR_API_KEY") # ← Replace with your keyTest examples before publishing:
# All examples should be runnable
# Consider automated testing of documentation examples✅ Conclusion
Code documentation requires balancing completeness with usability. The best code documentation helps developers understand, use, and troubleshoot your code efficiently.
Key takeaways
- API reference needs completeness — Parameters, returns, errors, examples for every public element
- Comments explain why, not what — Code shows how; comments provide context
- Examples are often most valuable — Realistic, complete, progressive examples that users can copy and modify
- Error messages are documentation — Write errors that help users solve problems
- Changelogs track history — Keep a Changelog format with meaningful entries
- READMEs create first impressions — Lead with value, show working code quickly
Next steps
- Next article: 05-validation-and-quality-assurance.md — Validating code documentation quality
- Related: 00-foundations-of-technical-documentation.md — How reference documentation fits Diátaxis
- Related: 03-accessibility-in-technical-writing.md — Accessible code examples
📚 References
API documentation standards
Google API Design Guide 📘 [Official]
Google’s comprehensive guide to designing REST APIs, including documentation requirements.
Microsoft REST API Guidelines 📘 [Official]
Microsoft’s REST API design and documentation standards.
Stripe API Documentation 📗 [Verified Community]
Widely considered best-in-class API documentation, worth studying as a model.
OpenAPI Specification 📘 [Official]
Standard for describing REST APIs, enabling documentation generation.
Code comment standards
PEP 257 - Docstring Conventions 📘 [Official]
Python’s official docstring standard.
Google Python Style Guide - Docstrings 📘 [Official]
Google’s Python docstring conventions, widely adopted.
JSDoc Documentation 📘 [Official]
Standard for JavaScript documentation comments.
XML Documentation Comments (C#) 📘 [Official]
Microsoft’s C# documentation comment standard.
Error message design
Microsoft Error Message Guidelines 📘 [Official]
Microsoft’s comprehensive guide to writing error messages.
Nielsen Norman Group - Error Message Guidelines 📗 [Verified Community]
UX research-backed guidance on error messages.
Changelog standards
Keep a Changelog 📗 [Verified Community]
De facto standard for changelog formatting.
Semantic Versioning 📗 [Verified Community]
Versioning standard that pairs with changelogs.
README standards
Make a README 📗 [Verified Community]
Guide to creating effective README files.
Standard Readme 📗 [Verified Community]
Specification for README structure and content.
Documentation generators
Sphinx Documentation 📘 [Official]
Python documentation generator, used for major Python projects.
DocFX 📘 [Official]
Microsoft’s documentation generator for .NET projects.
TypeDoc 📗 [Verified Community]
Documentation generator for TypeScript projects.
Comment patterns
TODO comments:
FIXME comments:
Warning comments:
Documentation comments (docstrings):