Coding Standards Configuration
Coding standards are the key configuration for ensuring Claude Code produces high-quality, maintainable code. This guide covers best practices for TypeScript, Python, and PHP.
1. Why Coding Standards Matter
1.1 Problems Without Coding Standards
Without explicit coding standards, Claude’s output often suffers from:
1.2 The Value of Coding Standards
Core principle: Coding standards are not a constraint — they make code easier for people (including future you) to understand.
2. Naming Convention Configuration
Naming is the most fundamental and important part of coding standards. Good naming makes code self-documenting.
2.1 File Naming
| Language | Regular files | Class/Component files | Test files |
|---|---|---|---|
| TypeScript | kebab-case.ts | PascalCase.tsx | *.test.ts / *.spec.ts |
| Python | snake_case.py | snake_case.py | test_*.py / *_test.py |
| PHP | snake_case.php | PascalCase.php | *Test.php |
2.2 Variables and Functions
// Variables: camelCase, noun-form
const userName = 'john';
const itemCount = 10;
const isActive = true;
// Functions: camelCase, verb-first
function getUserById(id: string) { }
function calculateTotal(items: Item[]) { }
function validateEmail(email: string) { }
// Constants: SCREAMING_SNAKE_CASE
const MAX_RETRY_COUNT = 3;
const API_BASE_URL = 'https://api.example.com';2.3 Classes and Interfaces
All languages use PascalCase consistently:
// Classes: PascalCase, noun
class UserService { }
class OrderRepository { }
// Interfaces: PascalCase, optional I prefix (per team convention)
interface User { }
interface IUserService { } // optional style
// Types: PascalCase
type UserRole = 'admin' | 'user' | 'guest';
type ApiResponse<T> = { data: T; error?: string };2.4 Boolean Naming
Booleans should use is/has/can/should prefixes to make their meaning immediately clear:
✅ Good naming ❌ Bad naming
isActive active
hasPermission permission
canEdit editable
shouldUpdate update
isValid valid2.5 Naming Convention Configuration Examples
## Naming Conventions (TypeScript)
### File Naming
- Regular files: kebab-case.ts (e.g. user-service.ts)
- React components: PascalCase.tsx (e.g. UserProfile.tsx)
- Test files: *.test.ts or *.spec.ts
### Identifier Naming
- Variables/functions: camelCase (e.g. getUserById)
- Classes/interfaces/types: PascalCase (e.g. UserService)
- Constants: SCREAMING_SNAKE_CASE (e.g. MAX_RETRY)
- Booleans: is/has/can/should prefix (e.g. isActive)
### Naming Principles
- Variables are nouns, functions are verbs
- Names must be meaningful — avoid a, b, x, temp
- No abbreviations unless widely recognized (e.g. id, url)3. Function Rules Configuration
Functions are the basic unit of code. Good function design is the foundation of high-quality code.
3.1 Function Length Limits
Recommended Standards
Under 30 lines: ideal length
Under 50 lines: acceptable upper limit
Over 50 lines: must be split
Why Limit Length
• Long functions are hard to understand
• Long functions are hard to test
• Long functions often violate single responsibility
3.2 Single Responsibility Principle
A function does one thing, and its name accurately describes that one thing.
// ❌ Bad: one function doing multiple things
function processUser(user: User) {
// validate
if (!user.email) throw new Error('Invalid email');
// save to database
db.save(user);
// send welcome email
sendEmail(user.email, 'Welcome!');
// log
logger.info('User created');
}
// ✅ Good: each function does one thing
function validateUser(user: User): void {
if (!user.email) throw new Error('Invalid email');
}
function saveUser(user: User): void {
db.save(user);
}
function sendWelcomeEmail(email: string): void {
sendEmail(email, 'Welcome!');
}
function createUser(user: User): void {
validateUser(user);
saveUser(user);
sendWelcomeEmail(user.email);
logger.info('User created');
}3.3 Parameter Count Limits
When more than 3–4 parameters are needed, use an object/DTO:
// ❌ Bad: too many parameters
function createUser(
name: string,
email: string,
age: number,
address: string,
phone: string,
role: string
) { }
// ✅ Good: use object parameter
interface CreateUserParams {
name: string;
email: string;
age: number;
address: string;
phone: string;
role: string;
}
function createUser(params: CreateUserParams) { }3.4 Return Value Standards
// ✅ Explicit return type
function getUserById(id: string): User | null {
const user = db.find(id);
return user ?? null;
}
// ✅ Result pattern for error handling
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
function parseJson(str: string): Result<unknown, Error> {
try {
return { ok: true, value: JSON.parse(str) };
} catch (e) {
return { ok: false, error: e as Error };
}
}3.5 Function Rules Configuration Example
## Function Rules
### Length Limits
- Single function no more than 30 lines (recommended)
- Absolute maximum 50 lines — must split if exceeded
- Nesting depth no more than 3 levels
### Single Responsibility
- A function does one thing
- Function name must accurately describe its purpose
- If the function name needs "and", it should be split
### Parameter Limits
- No more than 4 parameters
- Use object/DTO when exceeded
- Avoid boolean parameters (use enums or split into two functions)
### Return Values
- Must declare return type
- Avoid returning null (use Optional/Result pattern)
- A function returns one type only4. Error Handling Configuration
Error handling is the key to code robustness. Different languages have different best practices.
4.1 TypeScript Error Handling
// ❌ Bad: using any
try {
await fetchData();
} catch (error: any) {
console.log(error.message); // may crash
}
// ✅ Good: use unknown + type guard
try {
await fetchData();
} catch (error: unknown) {
if (error instanceof Error) {
console.log(error.message);
} else {
console.log('Unknown error:', String(error));
}
}
// ✅ Better: custom error class
class ApiError extends Error {
constructor(
message: string,
public statusCode: number,
public context?: Record<string, unknown>
) {
super(message);
this.name = 'ApiError';
}
}
function handleError(error: unknown): void {
if (error instanceof ApiError) {
logger.error(`API Error ${error.statusCode}: ${error.message}`, error.context);
} else if (error instanceof Error) {
logger.error(`Error: ${error.message}`);
} else {
logger.error('Unknown error', { error });
}
}4.2 Python Error Handling
# ❌ Bad: bare except
try:
fetch_data()
except: # catches everything, including KeyboardInterrupt
print('Error')
# ❌ Bad: overly broad
try:
fetch_data()
except Exception as e:
pass # swallowed exception
# ✅ Good: catch specific exceptions
try:
fetch_data()
except ConnectionError as e:
logger.error(f'Connection failed: {e}')
raise
except TimeoutError as e:
logger.error(f'Request timed out: {e}')
raise
# ✅ Better: custom exception class
class ApiError(Exception):
def __init__(self, message: str, status_code: int, context: dict = None):
super().__init__(message)
self.status_code = status_code
self.context = context or {}
def handle_error(error: Exception) -> None:
if isinstance(error, ApiError):
logger.error(f'API Error {error.status_code}: {error}', extra=error.context)
else:
logger.error(f'Error: {error}')4.3 PHP Error Handling
// ❌ Bad: using @ to suppress errors
$data = @file_get_contents($url);
// ❌ Bad: catch Exception but do nothing
try {
$this->fetchData();
} catch (Exception $e) {
// empty catch block
}
// ✅ Good: catch specific exceptions
try {
$this->fetchData();
} catch (ConnectionException $e) {
$this->logger->error('Connection failed: ' . $e->getMessage());
throw $e;
} catch (TimeoutException $e) {
$this->logger->error('Request timed out: ' . $e->getMessage());
throw $e;
}
// ✅ Better: custom exception hierarchy
class ApiException extends Exception {
public function __construct(
string $message,
public readonly int $statusCode,
public readonly array $context = [],
?Throwable $previous = null
) {
parent::__construct($message, $statusCode, $previous);
}
}
class ValidationException extends ApiException {}
class AuthenticationException extends ApiException {}4.4 Null Value Handling
// ✅ Optional chaining
const userName = user?.profile?.name;
// ✅ Nullish coalescing
const displayName = userName ?? 'Anonymous';
// ✅ Early return to avoid deep nesting
function getDisplayName(user: User | null): string {
if (!user) return 'Anonymous';
if (!user.profile) return user.email;
return user.profile.name ?? user.email;
}4.5 Error Handling Configuration Examples
## Error Handling (TypeScript)
### Type Safety
- Never use any — use unknown in catch blocks
- Use type guards to validate error types
- Custom error classes extend Error
### Error Handling Principles
- Never swallow exceptions (empty catch blocks)
- Caught exceptions must be logged or re-thrown
- Error messages must include context
### Null Handling
- Use optional chaining (?.) for potentially null properties
- Use nullish coalescing (??) to provide defaults
- Explicitly check null/undefined — don't rely on implicit coercion5. Code Organization Standards
5.1 DRY Principle (Don’t Repeat Yourself)
When the same logic appears more than twice, extract it into a standalone function or module.
Rule:
- Same code appears 2 times → consider extracting
- Same code appears 3 times → must extract
- Similar code → extract into a parameterized general function5.2 File Structure and Import Order
// 1. External packages (node_modules)
import express from 'express';
import { z } from 'zod';
// 2. Internal modules (absolute paths)
import { UserService } from '@/services/user';
import { logger } from '@/utils/logger';
// 3. Relative paths
import { validateUser } from './validators';
import type { User } from './types';5.3 Comment Standards
When to write comments
• Complex business logic
• Non-obvious design decisions
• Public API usage documentation
• Temporary workarounds (with issue link)
When NOT to write comments
• When the code itself is already clear
• When the comment just repeats the code
• When comments compensate for bad naming
• Commented-out code (should be deleted)
/**
* Retrieve a user by their ID
*
* @param id - The unique user identifier
* @returns The user object, or null if not found
* @throws {ApiError} When the database connection fails
*
* @example
* ```ts
* const user = await getUserById('123');
* if (user) {
* console.log(user.name);
* }
* ```
*/
async function getUserById(id: string): Promise<User | null> {
// ...
}6. Complete Configuration Templates
6.1 TypeScript Project Template
## Coding Standards (TypeScript)
### Naming Conventions
- Files: kebab-case.ts, components PascalCase.tsx
- Variables/functions: camelCase
- Classes/interfaces/types: PascalCase
- Constants: SCREAMING_SNAKE_CASE
- Booleans: is/has/can/should prefix
### Function Rules
- Single function no more than 30 lines
- No more than 4 parameters — use object when exceeded
- Must declare return type
- A function does one thing only
### Error Handling
- catch blocks use unknown, not any
- Never swallow exceptions
- Use optional chaining (?.) and nullish coalescing (??)
### Code Organization
- Import order: external packages → internal modules → relative paths
- Public APIs must have TSDoc comments
- Same code appearing 3 times must be extracted6.2 Python Project Template
## Coding Standards (Python)
### Naming Conventions
- Files/variables/functions: snake_case
- Classes: PascalCase
- Constants: SCREAMING_SNAKE_CASE
- Private members: _leading_underscore
- Booleans: is/has/can/should prefix
### Function Rules
- Single function no more than 30 lines
- No more than 4 parameters — use dataclass when exceeded
- Must add type annotations
- A function does one thing only
### Error Handling
- Never use bare except
- Catch specific exception types
- Use Optional to handle values that may be None
### Code Organization
- Import order: standard library → third-party → local
- Public functions must have Docstrings
- Follow PEP 86.3 PHP Project Template
## Coding Standards (PHP)
### Naming Conventions
- Class files: PascalCase.php
- Variables/methods: camelCase
- Classes/interfaces/traits: PascalCase
- Constants: SCREAMING_SNAKE_CASE
- Booleans: is/has/can/should prefix
### Function Rules
- Single method no more than 30 lines
- No more than 4 parameters — use DTO when exceeded
- Must declare parameter types and return types
- A method does one thing only
### Error Handling
- Never use the @ error suppressor
- Catch specific exception types
- Use nullable types and the ?? operator
### Code Organization
- Follow PSR-12
- use statements sorted alphabetically
- Public methods must have PHPDoc comments6.4 Multi-Language Project Template
## Coding Standards (Multi-Language Project)
### General Principles
- Follow each language's official style guide
- Maintain internal consistency within the project
- New code follows the existing code style
### Language-Specific Standards
See individual language configurations:
- TypeScript: see 6.1 above
- Python: see 6.2 above
- PHP: see 6.3 above
### Cross-Language Consistency
- Constants: SCREAMING_SNAKE_CASE universally
- Class names: PascalCase universally
- Booleans: is/has/can/should prefix universally
- API naming style: consistent (REST/GraphQL)7. FAQ
Q: What if Claude doesn’t follow naming conventions?
Solution: Add concrete examples to your configuration and emphasize “must” rather than “suggested.”
## Naming Conventions (Enforced)
**Must strictly follow — no exceptions:**
### Variable Naming
- ✅ Correct: `userName`, `orderCount`, `isActive`
- ❌ Wrong: `user_name`, `OrderCount`, `active`
### Function Naming
- ✅ Correct: `getUserById`, `calculateTotal`
- ❌ Wrong: `get_user_by_id`, `GetUserById`
**Code output that does not conform to the above is considered non-compliant**Q: How do I get Claude to automatically split long functions?
Solution: State the length limit explicitly and require Claude to explain the split rationale.
## Function Length Limit
**Functions over 50 lines are absolutely prohibited**
When a function exceeds 30 lines, you must:
1. Identify sub-tasks that can stand alone
2. Extract each sub-task into its own function
3. Use a meaningful name to describe each sub-task
4. Call the sub-functions from the main function
**Every extracted function should be describable in one sentence**Q: The existing codebase has mixed styles — how do I unify them progressively?
Solution: Add a “follow existing style” principle and set a long-term goal.
## Code Style Principles
### Short-term (existing code)
- When modifying an existing file, follow that file's current style
- Never mix feature changes and style changes in one PR
- Style unification should be an independent refactoring task
### Long-term goal (new code)
- New files must follow the coding standards in this document
- New modules should serve as style-unified examples
- Gradually unify old code style during refactoringQ: How do I configure standards for a multi-language project?
Solution: Extract universal principles while retaining language-specific standards.
## Multi-Language Project Configuration
### Universal Principles (all languages)
- Class names: PascalCase
- Constants: SCREAMING_SNAKE_CASE
- Booleans: is/has/can/should prefix
- Function length: no more than 30 lines
### Language-Specific (choose as needed)
Based on the current file's language, follow the corresponding detailed standards:
- .ts/.tsx files → TypeScript standards
- .py files → Python standards
- .php files → PHP standards8. Summary
Coding standards configuration is the foundation for improving code quality:
| Module | Core Points |
|---|---|
| Naming conventions | Consistent style, names that mean what they say |
| Function rules | Small and focused, single responsibility |
| Error handling | Type-safe, never swallow exceptions |
| Code organization | DRY principle, clear structure |
Working with other configurations:
- Pair with Quality Gates: promote key standards to hard gates
- Pair with Three-Phase Workflow: follow coding standards during the implementation phase
Next Steps
- Quality Gates Configuration — set non-negotiable floors
- Three-Phase Workflow Configuration — ensure standards are followed
- Back to Configuration Guide Home