Coding Style and Conventions¶
Section Overview
Standards for code formatting, naming, structure, and documentation that ensure consistency across our codebase.
Code Formatting Standards¶
General Guidelines¶
Core Principle: Code should be immediately readable and maintainable without requiring clarification from the original author.
Key Guidelines:
- Maintain visual clarity through consistent spacing and alignment
- Keep code width within comfortable reading limits
- Group related code elements visually
- Use meaningful whitespace to improve readability
Why This Matters
Clear visual structure reduces cognitive load and makes code easier to understand, debug, and maintain. When code is visually organized, developers can quickly grasp its structure and purpose.
Implementation:
- Configure IDE settings to display formatting guides
- Use vertical alignment for related code elements
- Implement automated formatting checks
- Regular code review focusing on readability
Examples:
# Python -- PEP 8 compliant formatting
from typing import List, Optional
class OrderProcessor:
def process_items(
self,
items: List[dict],
user_id: Optional[int] = None
) -> dict:
processed_items = [
self._format_item(item)
for item in items
if self._validate_item(item)
]
return {
'items': processed_items,
'user_id': user_id,
'timestamp': self._get_timestamp()
}
// JavaScript -- Clear visual structure
function processOrder(orderItems, customerInfo) {
// Group related calculations
const subtotal = orderItems.reduce((sum, item) => sum + item.price, 0);
const tax = calculateTax(subtotal);
const shipping = calculateShipping(orderItems);
// Group related validations
if (!orderItems.length) {
throw new Error("Order must contain items");
}
if (!customerInfo.address) {
throw new Error("Shipping address required");
}
return {
orderTotal: subtotal + tax + shipping,
taxApplied: tax,
shippingFee: shipping
};
}
// Java -- Consistent visual organization
public class OrderProcessor {
public OrderResult processOrder(List<OrderItem> orderItems,
CustomerInfo customerInfo) {
// Group related calculations
double subtotal = calculateSubtotal(orderItems);
double tax = calculateTax(subtotal);
double shipping = calculateShipping(orderItems);
// Group related validations
if (orderItems.isEmpty()) {
throw new IllegalArgumentException("Order must contain items");
}
if (customerInfo.getAddress() == null) {
throw new IllegalArgumentException("Shipping address required");
}
return OrderResult.builder()
.orderTotal(subtotal + tax + shipping)
.taxApplied(tax)
.shippingFee(shipping)
.build();
}
}
Language-Specific Formatting¶
Core Principle: Each programming language should follow its ecosystem's established formatting conventions while maintaining project-wide consistency.
Key Guidelines:
- Python
- Indentation: 4 spaces
- Maximum line length: 88 characters (Black default)
-
Follow PEP 8 guidelines
-
JavaScript/TypeScript
- Indentation: 2 spaces
- Maximum line length: 80 characters
- Use semicolons consistently
-
Follow Standard JS style or Google Style for Typescript
-
Java
- Indentation: 4 spaces
- Maximum line length: 120 characters
- Follow K&R style bracing
Follow the Ecosystem
Following established language conventions makes code more predictable and easier to maintain. It also helps new team members adapt quickly to the codebase.
Examples:
# Python - Strategic whitespace usage
class OrderManager:
def __init__(self, db_connection, logger):
self.db = db_connection
self.logger = logger
def process_order(self, order_data):
# Validation block
if not order_data:
self.logger.error("Empty order received")
return None
# Processing block
try:
validated_items = self._validate_items(order_data['items'])
total_amount = self._calculate_total(validated_items)
# Database operations block
order_id = self._save_to_database(
items=validated_items,
amount=total_amount
)
return {"order_id": order_id, "status": "success"}
except Exception as e:
self.logger.error(f"Order processing failed: {e}")
return {"status": "error", "message": str(e)}
// JavaScript - Standard JS style
class OrderProcessor {
async processItems(items, userId = null) {
const processedItems = await Promise.all(
items
.filter(item => this.validateItem(item))
.map(async item => this.formatItem(item))
);
return {
items: processedItems,
userId,
timestamp: this.getTimestamp()
};
}
}
// Java - Google Style
public class OrderProcessor {
public ProcessResult processItems(
List<Item> items, @Nullable Integer userId) {
List<FormattedItem> processedItems = items.stream()
.filter(this::validateItem)
.map(this::formatItem)
.collect(Collectors.toList());
return ProcessResult.builder()
.items(processedItems)
.userId(userId)
.timestamp(getTimestamp())
.build();
}
}
Whitespace Usage¶
Core Principle: Whitespace should be used deliberately to improve code readability and indicate logical groupings.
Key Guidelines:
- Use blank lines to separate logical blocks of code
- Maintain consistent spacing around operators
- Group related code elements with consistent spacing
- Use indentation to show hierarchy and scope
Visual Patterns
Strategic use of whitespace creates visual patterns that make code structure immediately apparent, reducing the time needed to understand code organization and relationships.
Examples:
# Python - Strategic whitespace usage
class OrderManager:
def __init__(self, db_connection, logger):
self.db = db_connection
self.logger = logger
def process_order(self, order_data):
# Validation block
if not order_data:
self.logger.error("Empty order received")
return None
# Processing block
try:
validated_items = self._validate_items(order_data['items'])
total_amount = self._calculate_total(validated_items)
# Database operations block
order_id = self._save_to_database(
items=validated_items,
amount=total_amount
)
return {"order_id": order_id, "status": "success"}
except Exception as e:
self.logger.error(f"Order processing failed: {e}")
return {"status": "error", "message": str(e)}
// JavaScript - Logical grouping with whitespace
class OrderManager {
constructor(dbConnection, logger) {
this.db = dbConnection;
this.logger = logger;
}
async processOrder(orderData) {
// Validation block
if (!orderData) {
this.logger.error('Empty order received');
return null;
}
// Processing block
try {
const validatedItems = await this._validateItems(orderData.items);
const totalAmount = this._calculateTotal(validatedItems);
// Database operations block
const orderId = await this._saveToDatabase({
items: validatedItems,
amount: totalAmount
});
return { orderId, status: 'success' };
} catch (error) {
this.logger.error(`Order processing failed: ${error}`);
return { status: 'error', message: error.message };
}
}
}
Tool Configuration and Enforcement¶
Core Principle: Automated tools and consistent configurations should be used to enforce coding standards and maintain code quality across the team.
Automation is Key
Automated enforcement reduces cognitive load on developers, ensures consistent code quality, and prevents style debates by automatically enforcing agreed-upon standards.
Python Tool Setup¶
What You'll Need:
- black: A code formatter
- isort: Sorts and organizes import statements
Setup:
# 1. Install the tools
pip install black isort
# 2. Run formatting
black . # Formats all Python files
isort . # Sorts import statements
Configuration File (pyproject.toml):
[tool.black]
line-length = 88
include = '\.pyx?$'
[tool.isort]
profile = "black"
multi_line_output = 3
JavaScript/TypeScript Tool Setup¶
What You'll Need:
- eslint: Finds and fixes code quality issues
- prettier: Enforces consistent code formatting
Setup:
# 1. Install tools
npm install --save-dev eslint prettier
# 2. Run formatting and linting
prettier --write "**/*.{js,jsx,ts,tsx}"
eslint .
Configuration (.prettierrc):
Java Tool Setup¶
What You'll Need:
- Google Java Format: An opinionated code formatter
- Maven Plugin: Integrates formatting into the build process
Setup:
Add Maven Plugin to pom.xml:
<plugin>
<groupId>com.googlejavaformat</groupId>
<artifactId>google-java-format-maven-plugin</artifactId>
<version>1.15.0</version>
<executions>
<execution>
<goals>
<goal>format</goal>
</goals>
<phase>validate</phase>
</execution>
</executions>
</plugin>
Run formatting:
# Format all Java files
mvn google-java-format:format
# Verify formatting compliance
mvn google-java-format:check
Best Practices
- Run formatter before each commit
- Integrate with CI/CD pipeline
- Configure IDE to format on save
- Use pre-commit hooks for automatic checking
Shared IDE Configuration¶
To maintain consistency across the team when using different editors and IDEs, we use a shared .editorconfig:
.editorconfig Example:
# Root configuration file
root = true
# Rules for all files
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
# JavaScript/TypeScript specific
[*.{js,jsx,ts,tsx}]
indent_style = space
indent_size = 2
# Python specific
[*.py]
indent_style = space
indent_size = 4
VSCode Settings:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": null,
"editor.codeActionsOnSave": {
"source.fixAll": true
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
}
}
Enforcement Mechanisms¶
We implement a multi-layered approach to enforce these standards:
Four-Layer Enforcement
1. Pre-commit Hooks - Run checks before allowing commits
2. CI/CD Pipeline - Validate in continuous integration
3. IDE Integration - Real-time feedback while coding
4. Code Review - Human validation with automated checklists
Code Organization and Structure¶
Project Structure¶
Core Principle: Code should be organized in a hierarchical, domain-driven structure that promotes maintainability, scalability, and clear separation of concerns.
Key Guidelines:
- Organize code by business domain or feature
- Maintain consistent project structure across all services
- Follow the Single Responsibility Principle
- Keep related code close together
- Implement clear dependency management
Reduce Cognitive Load
Well-organized code reduces cognitive load, improves team collaboration, and makes the system easier to maintain and extend over time.
Standard Project Structure:
project-root/
├── src/
│ ├── feature1/
│ │ ├── models/
│ │ ├── services/
│ │ ├── utils/
│ │ └── tests/
│ ├── feature2/
│ │ └── ...
│ └── shared/
├── config/
├── scripts/
└── docs/
Examples:
payment_service/
└── payment/
├── models/
│ ├── payment.py
│ └── transaction.py
├── services/
│ ├── payment_processor.py
│ └── refund_handler.py
└── utils/
└── payment_validator.py
# payment_processor.py
from typing import Optional
from .models.payment import Payment
from .utils.payment_validator import validate_payment
class PaymentProcessor:
def __init__(self, payment_gateway):
self.payment_gateway = payment_gateway
def process_payment(self, payment_data: dict) -> Optional[Payment]:
if not validate_payment(payment_data):
return None
payment = Payment.from_dict(payment_data)
return self.payment_gateway.process(payment)
OrderModule/
├── components/
│ ├── OrderList.js
│ └── OrderDetail.js
├── services/
│ └── orderService.js
└── utils/
└── orderValidator.js
// orderService.js
import { orderValidator } from '../utils/orderValidator';
export class OrderService {
constructor(orderRepository) {
this.orderRepository = orderRepository;
}
async createOrder(orderData) {
if (!orderValidator.isValid(orderData)) {
throw new ValidationError('Invalid order data');
}
const order = await this.orderRepository.create(orderData);
return this.enrichOrderData(order);
}
}
inventory/
├── domain/
│ └── Product.java
├── repository/
│ └── ProductRepository.java
└── service/
└── ProductService.java
// ProductService.java
@Service
public class ProductService {
private final ProductRepository repository;
private final ValidationService validator;
@Autowired
public ProductService(
ProductRepository repository,
ValidationService validator) {
this.repository = repository;
this.validator = validator;
}
public Product createProduct(ProductDTO dto) {
validator.validate(dto);
return repository.save(Product.fromDTO(dto));
}
}
Language-Specific Idioms and Constructs¶
Core Principle: Leverage language-specific features and idioms to write clean, efficient, and idiomatic code while maintaining consistency across the codebase.
Use Idiomatic Code
Using language-specific idioms properly results in more maintainable, efficient code that follows established patterns familiar to developers in that ecosystem.
Examples:
# Python - Idiomatic constructs
from dataclasses import dataclass
from typing import List, Optional
from contextlib import contextmanager
@dataclass
class OrderItem:
product_id: int
quantity: int
price: float
class OrderProcessor:
def __init__(self, db_session):
self.db_session = db_session
@contextmanager
def transaction(self):
"""Idiomatic transaction handling"""
try:
yield self.db_session
self.db_session.commit()
except Exception:
self.db_session.rollback()
raise
def process_items(self, items: List[OrderItem]) -> Optional[dict]:
"""Pythonic list processing and error handling"""
if not items:
return None
with self.transaction() as session:
# List comprehension for transformation
processed = [
self._process_item(item)
for item in items
]
# Dictionary comprehension for results
return {
'items': processed,
'total': sum(item.price for item in processed)
}
// JavaScript - Modern idioms
class OrderManager {
constructor(repository) {
this.repository = repository;
}
async processOrder({ items, userId, ...metadata }) {
// Destructuring and rest parameters
const processedItems = await Promise.all(
items.map(async item => {
// Arrow functions and async/await
const { price, ...itemData } = item;
return {
...itemData,
processedPrice: await this.calculatePrice(price)
};
})
);
// Object spread and computed properties
return {
orderItems: processedItems,
metadata: {
...metadata,
timestamp: new Date().toISOString()
}
};
}
}
// Java - Modern patterns and features
public class OrderProcessor {
private final OrderRepository repository;
// Constructor injection
@Inject
public OrderProcessor(OrderRepository repository) {
this.repository = repository;
}
public Optional<Order> processOrder(OrderRequest request) {
// Stream API and method references
return Optional.of(request)
.filter(OrderValidator::isValid)
.map(this::createOrder)
.flatMap(repository::save);
}
// Builder pattern
private Order createOrder(OrderRequest request) {
return Order.builder()
.items(request.getItems())
.status(OrderStatus.PENDING)
.timestamp(LocalDateTime.now())
.build();
}
}
Commenting and Documentation¶
Core Principle: Comments should explain why rather than what, and documentation should provide clear context for code usage and maintenance.
Document the Why, Not the What
Good documentation and comments make code easier to maintain, understand, and modify while reducing the time needed for new developers to become productive.
Key Guidelines:
- Write self-documenting code where possible
- Document the why, not the what
- Keep comments up to date with code changes
- Provide clear API documentation
- Add examples for complex logic
Examples:
# Python - Documentation and comments
from typing import List, Optional
from datetime import datetime
class OrderProcessor:
"""Handles the processing and validation of customer orders.
This class coordinates the entire order processing workflow,
including inventory checks, payment processing, and notification
handling.
Attributes:
max_retries: Maximum number of payment processing attempts
retry_delay: Delay between retry attempts in seconds
"""
def process_order(
self,
order_items: List[dict],
customer_id: str
) -> Optional[dict]:
"""Process a customer order with inventory and payment validation.
Args:
order_items: List of items in the order, each containing
'product_id' and 'quantity'
customer_id: Unique identifier for the customer
Returns:
Dict containing order details if successful, None if failed
Raises:
InvalidOrderException: If order validation fails
PaymentProcessingError: If payment cannot be processed
"""
# Validate inventory before processing payment
# This prevents charging customer for unavailable items
if not self._validate_inventory(order_items):
return None
try:
# Process payment first to ensure funds are available
# before modifying inventory
payment_result = self._process_payment(order_items, customer_id)
return self._finalize_order(payment_result, order_items)
except Exception as e:
# Log error and rollback any partial changes
self._handle_processing_error(e)
return None
// JavaScript - Documentation and comments
/**
* Manages the processing and fulfillment of customer orders.
*
* @class OrderProcessor
* @description Coordinates order processing workflow including
* validation, payment processing, and fulfillment.
*/
class OrderProcessor {
/**
* Process a new customer order.
*
* @async
* @param {Object} orderData - The order information
* @param {Array<Object>} orderData.items - Order items
* @param {string} orderData.customerId - Customer identifier
* @returns {Promise<Object>} Processing result with order details
* @throws {ValidationError} If order validation fails
*/
async processOrder({ items, customerId }) {
// Validate order before processing to prevent invalid submissions
// This includes checking inventory and customer eligibility
const validationResult = await this.validateOrder(items, customerId);
if (!validationResult.isValid) {
throw new ValidationError(validationResult.errors);
}
try {
// Process payment first to ensure funds are available
// This prevents inventory issues during high concurrency
const paymentResult = await this.processPayment(items, customerId);
return this.finalizeOrder(paymentResult, items);
} catch (error) {
// Ensure all changes are rolled back if any part fails
await this.handleProcessingError(error);
throw error;
}
}
}
/**
* Manages order processing and fulfillment workflows.
*
* <p>This class handles the entire lifecycle of an order, including:
* <ul>
* <li>Order validation</li>
* <li>Payment processing</li>
* <li>Inventory management</li>
* <li>Fulfillment tracking</li>
* </ul>
*
* <p>Thread-safe and supports concurrent order processing.
*/
public class OrderProcessor {
/**
* Processes a customer order through all stages of the workflow.
*
* @param orderRequest Contains order details and customer information
* @return OrderResult containing the processing outcome and order details
* @throws ValidationException if order validation fails
* @throws PaymentException if payment processing fails
*/
public OrderResult processOrder(OrderRequest orderRequest) {
// Validate order before processing
// This prevents invalid orders from entering the system
ValidationResult validation = validateOrder(orderRequest);
if (!validation.isValid()) {
throw new ValidationException(validation.getErrors());
}
try {
// Process payment first to ensure funds are available
// This prevents inventory holds on unpaid orders
PaymentResult payment = processPayment(orderRequest);
return finalizeOrder(payment, orderRequest);
} catch (Exception e) {
// Roll back any partial changes to maintain system consistency
handleProcessingError(e);
throw e;
}
}
}
Last updated: October 2025