BMAD-METHOD/expansion-packs/bmad-technical-writing/data/code-style-guides.md

474 lines
10 KiB
Markdown

# Code Style Guides for Technical Writing
This document summarizes language-specific coding standards for technical book code examples.
## Universal Code Example Standards
These apply to ALL code examples regardless of language:
### Readability First
- Use descriptive variable and function names
- Prefer clarity over cleverness
- Add inline comments for WHY, not WHAT
- Keep functions focused and small
### Educational Code vs Production Code
Technical book code should prioritize:
- **Clarity** over performance (unless teaching performance)
- **Explicitness** over brevity
- **Simplicity** over DRY (some repetition acceptable for clarity)
- **Readability** over advanced language features
### Comments
```
❌ Bad: Obvious comments
// increment counter
counter++;
✅ Good: Explain decisions
// Use exponential backoff to avoid overwhelming API during retry
await sleep(Math.pow(2, retryCount) * 1000);
```
### Error Handling
- Always demonstrate proper error handling
- Show common error scenarios
- Provide meaningful error messages
- Use language-appropriate patterns
### Magic Numbers
```
❌ Bad
if (age >= 18) { ... }
✅ Good
const MINIMUM_AGE = 18;
if (age >= MINIMUM_AGE) { ... }
```
---
## Python (PEP 8)
**Official Style Guide:** PEP 8 - Style Guide for Python Code
### Key Principles
**Indentation:**
- Use 4 spaces (not tabs)
- No mixing tabs and spaces
**Line Length:**
- Maximum 79 characters for code
- Maximum 72 for comments and docstrings
**Naming Conventions:**
```python
# Variables and functions: snake_case
user_name = "Alice"
def calculate_total(items): ...
# Constants: UPPER_CASE
MAX_CONNECTIONS = 100
API_TIMEOUT = 30
# Classes: PascalCase
class UserAccount: ...
class DatabaseConnection: ...
# Private: leading underscore
_internal_variable = 42
def _private_method(self): ...
```
**Imports:**
```python
# Standard library first
import os
import sys
# Then third-party
import requests
import numpy as np
# Then local imports
from myapp import models
from myapp.utils import helpers
# Avoid wildcard imports
from module import * # ❌ Bad
from module import SpecificClass # ✅ Good
```
**Docstrings:**
```python
def fetch_user(user_id: int) -> dict:
"""
Fetch user data from the database.
Args:
user_id: The unique identifier for the user
Returns:
Dictionary containing user data
Raises:
UserNotFoundError: If user doesn't exist
"""
...
```
**Type Hints (Python 3.5+):**
```python
def greet(name: str) -> str:
return f"Hello, {name}"
def process_items(items: list[dict]) -> None:
...
```
---
## JavaScript (Airbnb Style Guide)
**Official Style Guide:** Airbnb JavaScript Style Guide (github.com/airbnb/javascript)
### Key Principles
**Variables:**
```javascript
// Use const for values that won't be reassigned
const API_URL = 'https://api.example.com';
const user = { name: 'Alice' };
// Use let for values that will change
let counter = 0;
// Never use var
var oldStyle = 'bad'; // ❌
```
**Naming Conventions:**
```javascript
// Variables and functions: camelCase
const userName = "Alice";
function calculateTotal(items) { ... }
// Constants: UPPER_CASE (by convention)
const MAX_RETRY_COUNT = 3;
const API_TIMEOUT = 30000;
// Classes: PascalCase
class UserAccount { ... }
class DatabaseConnection { ... }
// Private (by convention): leading underscore
class Example {
_privateMethod() { ... }
}
```
**Functions:**
```javascript
// Arrow functions for callbacks
const numbers = [1, 2, 3];
const doubled = numbers.map((n) => n * 2);
// Named functions for clarity
function processOrder(order) {
// Implementation
}
// Avoid function hoisting confusion
// Declare before use
const helper = () => { ... };
helper();
```
**Strings:**
```javascript
// Use template literals for interpolation
const message = `Hello, ${userName}!`; // ✅ Good
const bad = 'Hello, ' + userName + '!'; // ❌ Avoid
// Use single quotes for simple strings
const apiKey = 'abc123';
```
**Objects and Arrays:**
```javascript
// Use shorthand
const name = 'Alice';
const user = { name }; // ✅ Good (shorthand)
const user2 = { name: name }; // ❌ Verbose
// Destructuring
const { id, email } = user;
const [first, second] = array;
// Spread operator
const newUser = { ...user, status: 'active' };
const newArray = [...oldArray, newItem];
```
---
## Java (Google Style Guide)
**Official Style Guide:** Google Java Style Guide
### Key Principles
**Indentation:**
- Use 2 spaces (not 4, not tabs)
- Continuation indent: 4 spaces
**Naming Conventions:**
```java
// Classes: PascalCase
public class UserAccount { }
public class DatabaseConnection { }
// Methods and variables: camelCase
public void calculateTotal() { }
private int userCount = 0;
// Constants: UPPER_CASE
private static final int MAX_CONNECTIONS = 100;
public static final String API_URL = "https://api.example.com";
// Packages: lowercase
package com.example.myapp;
```
**Braces:**
```java
// Braces on same line (K&R style)
if (condition) {
// code
} else {
// code
}
// Always use braces, even for single statements
if (condition) {
doSomething(); // ✅ Good
}
if (condition)
doSomething(); // ❌ Bad (no braces)
```
**Javadoc:**
```java
/**
* Fetches user data from the database.
*
* @param userId the unique identifier for the user
* @return User object containing user data
* @throws UserNotFoundException if user doesn't exist
*/
public User fetchUser(int userId) throws UserNotFoundException {
// Implementation
}
```
**Ordering:**
```java
public class Example {
// 1. Static fields
private static final int CONSTANT = 42;
// 2. Instance fields
private int count;
// 3. Constructor
public Example() { }
// 4. Public methods
public void doSomething() { }
// 5. Private methods
private void helper() { }
}
```
---
## Code Example Best Practices by Language
### Python
```python
# ✅ Good Example
def authenticate_user(username: str, password: str) -> dict:
"""
Authenticate user and return JWT token.
Args:
username: User's login name
password: User's password (will be hashed)
Returns:
Dictionary with 'token' and 'expires_at' keys
Raises:
AuthenticationError: If credentials are invalid
"""
# Hash password for comparison
password_hash = hash_password(password)
# Query database
user = User.query.filter_by(username=username).first()
if not user or user.password_hash != password_hash:
raise AuthenticationError("Invalid credentials")
# Generate JWT token with 1-hour expiration
token = jwt.encode(
{"user_id": user.id, "exp": datetime.utcnow() + timedelta(hours=1)},
SECRET_KEY,
algorithm="HS256",
)
return {"token": token, "expires_at": datetime.utcnow() + timedelta(hours=1)}
```
### JavaScript/Node.js
```javascript
// ✅ Good Example
async function authenticateUser(username, password) {
// Hash password for comparison
const passwordHash = await bcrypt.hash(password, SALT_ROUNDS);
// Query database
const user = await User.findOne({ where: { username } });
if (!user || !(await bcrypt.compare(password, user.passwordHash))) {
throw new AuthenticationError('Invalid credentials');
}
// Generate JWT token with 1-hour expiration
const token = jwt.sign({ userId: user.id }, SECRET_KEY, { expiresIn: '1h' });
return {
token,
expiresAt: new Date(Date.now() + 3600000), // 1 hour from now
};
}
```
### Java
```java
// ✅ Good Example
public class AuthService {
private static final int TOKEN_EXPIRY_HOURS = 1;
/**
* Authenticates user and returns JWT token.
*
* @param username user's login name
* @param password user's password (will be hashed)
* @return AuthResponse containing token and expiration
* @throws AuthenticationException if credentials are invalid
*/
public AuthResponse authenticateUser(String username, String password)
throws AuthenticationException {
// Hash password for comparison
String passwordHash = PasswordUtil.hash(password);
// Query database
User user = userRepository.findByUsername(username);
if (user == null || !user.getPasswordHash().equals(passwordHash)) {
throw new AuthenticationException("Invalid credentials");
}
// Generate JWT token with 1-hour expiration
String token = Jwts.builder()
.setSubject(String.valueOf(user.getId()))
.setExpiration(new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(TOKEN_EXPIRY_HOURS)))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
return new AuthResponse(token, new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(TOKEN_EXPIRY_HOURS)));
}
}
```
---
## Testing Code Examples
For technical books, include test examples:
### Python (pytest)
```python
def test_authenticate_user_success():
"""Test successful authentication."""
response = authenticate_user("alice", "correct_password")
assert "token" in response
assert response["expires_at"] > datetime.utcnow()
def test_authenticate_user_invalid_password():
"""Test authentication with wrong password."""
with pytest.raises(AuthenticationError):
authenticate_user("alice", "wrong_password")
```
### JavaScript (Jest)
```javascript
describe('authenticateUser', () => {
it('returns token for valid credentials', async () => {
const response = await authenticateUser('alice', 'correct_password');
expect(response).toHaveProperty('token');
expect(response.expiresAt).toBeInstanceOf(Date);
});
it('throws error for invalid password', async () => {
await expect(authenticateUser('alice', 'wrong_password')).rejects.toThrow(AuthenticationError);
});
});
```
---
## Official Style Guide Links
- **Python PEP 8**: https://peps.python.org/pep-0008/
- **JavaScript Airbnb**: https://github.com/airbnb/javascript
- **Java Google**: https://google.github.io/styleguide/javaguide.html
- **TypeScript**: https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html
- **Go**: https://go.dev/doc/effective_go
- **Rust**: https://doc.rust-lang.org/book/appendix-07-syntax-guide.html
- **C#**: https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions
Always check official documentation for your target language version.