Introduction to Code Formatting
Code formatting is the practice of structuring and styling code to enhance readability, maintainability, and collaboration. Well-formatted code reduces cognitive load, makes debugging easier, and creates a consistent codebase that all team members can navigate efficiently. While programming languages have different syntactic requirements, universal formatting principles help create clean, professional code regardless of language. This cheat sheet covers formatting best practices across popular languages, automatic formatting tools, and strategies for implementing consistent formatting in your projects.
Core Principles of Code Formatting
Principle | Description | Benefits |
---|
Consistency | Follow the same formatting rules throughout the codebase | Reduces cognitive overhead when reading code |
Readability | Format code to be easily read and understood | Improves comprehension and maintenance speed |
Simplicity | Keep formatting rules simple and intuitive | Ensures adoption and compliance |
Automation | Use automatic formatting tools where possible | Eliminates manual formatting effort |
Convention | Follow established language/framework conventions | Aligns with community standards |
Indentation and Line Length
Indentation Strategies
Style | Description | Common In | Example |
---|
Spaces | Use spaces for indentation (2, 4, or 8 spaces) | Python, Ruby, JavaScript | def function(): <br> statement |
Tabs | Use tab characters for indentation | Go, Makefiles | function() { <br> statement <br>} |
Mixed | Tabs for indentation, spaces for alignment | Rare, legacy codebases | Not recommended |
Line Length Guidelines
- Traditional limit: 80 characters (historical terminal width)
- Modern standard: 100-120 characters (wider screens)
- Special cases:
- Documentation comments: 72-80 characters for better readability
- URLs and long strings may exceed limits when breaking would reduce clarity
- Data literals might have specific formatting requirements
Handling Long Lines
# Bad: exceeding line limit
result = perform_complicated_calculation(first_parameter, second_parameter, third_parameter, fourth_parameter, fifth_parameter)
# Good: line break with alignment
result = perform_complicated_calculation(first_parameter,
second_parameter,
third_parameter,
fourth_parameter,
fifth_parameter)
# Good: line break with consistent indentation
result = perform_complicated_calculation(
first_parameter,
second_parameter,
third_parameter,
fourth_parameter,
fifth_parameter
)
Whitespace Usage
Vertical Whitespace
Rule | Description | Example |
---|
Group related code | Use blank lines to separate logical sections | Functions, class definitions, logical blocks |
Limit consecutive blanks | Maximum 1-2 blank lines within functions | Avoid excessive spacing that causes scrolling |
Consistency in blocks | Keep blank line usage consistent | Same pattern throughout the codebase |
Horizontal Whitespace
Location | Recommendation | Examples |
---|
Around operators | Space around most operators | x = y + z , not x=y+z |
Function calls | No space between name and parenthesis | function() , not function () |
Function definitions | Language-dependent | JavaScript: function name() { |
After commas | Space after comma, not before | foo(a, b, c) , not foo(a ,b ,c) |
Brackets/braces | Language/style guide dependent | if (condition) { vs if(condition){ |
Line endings | No trailing whitespace | Remove spaces/tabs at line ends |
Braces and Block Formatting
Common Brace Styles
Style | Description | Example |
---|
K&R | Opening brace on same line | if (condition) { <br> statement; <br>} |
Allman | Opening brace on new line | if (condition) <br>{ <br> statement; <br>} |
Stroustrup | K&R but with functions having braces on next line | int main() <br>{ <br> statement; <br>} |
1TBS | One True Brace Style (K&R variant) | if (x) { <br> foo(); <br>} else { <br> bar(); <br>} |
Block Structure by Language
Language | Dominant Style | Notes |
---|
Java | K&R | Oracle Java Style Guide recommends K&R |
C# | Allman | Microsoft guidelines prefer Allman |
JavaScript | K&R | Majority of style guides use K&R |
PHP | K&R/PSR-2 | PSR standards recommend K&R |
Python | Indentation-based | No braces, consistent indentation |
Ruby | K&R | Though many blocks use do...end |
Go | K&R | Enforced by gofmt |
Swift | K&R | Swift API Design Guidelines |
Comments and Documentation
Comment Types and Formatting
Type | Purpose | Format |
---|
Line comments | Brief explanations | Start with // , # , or -- depending on language |
Block comments | Multi-line explanations | Use /* */ , """ """ , ''' ''' , etc. |
Documentation comments | Generate documentation | Special formats like JSDoc, Javadoc, etc. |
TODO comments | Mark incomplete work | Include a tag: // TODO: Fix this later |
Comment Placement
// Bad: Comment after code on same line
performComplexOperation(); // Performs the operation
// Good: Comment on line before code
// Performs the complex operation
performComplexOperation();
// Good: Multi-line comments for longer explanations
/**
* This method handles the user authentication process.
* It validates credentials and returns a session token.
*
* @param username The user's login name
* @param password The user's password
* @return A valid session token or null if authentication fails
*/
function authenticate(username, password) { ... }
Language-Specific Formatting Guidelines
JavaScript/TypeScript
// Variables and assignments
const firstName = 'John';
let counter = 0;
// Function declarations
function calculateTotal(items) {
return items.reduce((total, item) => total + item.price, 0);
}
// Arrow functions
const multiply = (a, b) => a * b;
// Classes
class User {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
// Conditionals
if (condition) {
doSomething();
} else if (otherCondition) {
doSomethingElse();
} else {
doDefault();
}
// Imports (grouped and sorted)
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import * as moment from 'moment';
Python
# Imports (grouped by standard, third-party, local)
import os
import sys
import numpy as np
import pandas as pd
from mymodule import helper
# Function definitions (2 blank lines before)
def calculate_average(numbers):
"""Calculate the average of a list of numbers.
Args:
numbers: A list of integers or floats
Returns:
float: The average value
"""
if not numbers:
return 0
return sum(numbers) / len(numbers)
# Classes (2 blank lines before)
class DataProcessor:
def __init__(self, data):
self.data = data
def process(self):
# Use 4 spaces for indentation
result = []
for item in self.data:
if self._is_valid(item):
result.append(self._transform(item))
return result
def _is_valid(self, item):
# Private methods with leading underscore
return item is not None and item > 0
Java
package com.example.project;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a user in the system.
*/
public class User {
// Constants in ALL_CAPS
private static final int MAX_USERNAME_LENGTH = 50;
// Instance variables in camelCase
private String firstName;
private String lastName;
private List<Order> orders;
/**
* Creates a new User with the given name.
*
* @param firstName The user's first name
* @param lastName The user's last name
*/
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.orders = new ArrayList<>();
}
public String getFullName() {
return firstName + " " + lastName;
}
public void addOrder(Order order) {
if (order != null) {
orders.add(order);
}
}
}
C#
using System;
using System.Collections.Generic;
using System.Linq;
namespace Example.Project
{
/// <summary>
/// Represents a customer in the system.
/// </summary>
public class Customer
{
// Properties with PascalCase
public int Id { get; private set; }
public string Name { get; set; }
// Private fields with _camelCase
private readonly List<Order> _orders = new List<Order>();
public Customer(int id, string name)
{
Id = id;
Name = name;
}
public void AddOrder(Order order)
{
if (order == null)
{
throw new ArgumentNullException(nameof(order));
}
_orders.Add(order);
}
public decimal CalculateTotalSpent()
{
return _orders.Sum(o => o.TotalAmount);
}
}
}
Automatic Formatting Tools
Popular Formatters by Language
Language | Tool | Configuration | Usage Example |
---|
Multiple | EditorConfig | .editorconfig file | Defines indent style, size, line endings |
JavaScript/TS | Prettier | .prettierrc | npx prettier --write . |
JavaScript/TS | ESLint | .eslintrc | npx eslint --fix . |
Python | Black | pyproject.toml | black . |
Python | YAPF | .style.yapf | yapf -i file.py |
Java | Google Java Format | N/A | java -jar google-java-format.jar --replace file.java |
C# | dotnet format | .editorconfig | dotnet format |
Go | gofmt | Built-in | gofmt -w file.go |
Rust | rustfmt | rustfmt.toml | cargo fmt |
PHP | PHP-CS-Fixer | .php-cs-fixer.php | php-cs-fixer fix |
Ruby | RuboCop | .rubocop.yml | rubocop -a |
Swift | SwiftFormat | .swiftformat | swiftformat . |
EditorConfig Example
# EditorConfig helps maintain consistent coding styles across editors
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.{py,java}]
indent_size = 4
[*.md]
trim_trailing_whitespace = false
Prettier Configuration Example
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": true,
"arrowParens": "avoid"
}
Implementing Formatting Standards in a Team
Pre-commit Hooks
# Example pre-commit configuration (.pre-commit-config.yaml)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/psf/black
rev: 23.1.0
hooks:
- id: black
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.0-alpha.4
hooks:
- id: prettier
Continuous Integration Checks
# GitHub Action for checking code formatting
name: Code Formatting Check
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
format-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Check formatting
run: npx prettier --check .
IDE Integration
IDE | Formatting Support | Notes |
---|
VSCode | Built-in + extensions | Configure in settings.json, extensions for language-specific formatting |
IntelliJ/JetBrains | Built-in | Customize in Settings > Editor > Code Style |
Eclipse | Built-in + plugins | Configure in Window > Preferences > [Language] > Code Style |
Sublime Text | Plugins | Requires plugins like JsPrettier, HTML-CSS-JS Prettify |
Atom | Plugins | Various formatter plugins available |
VSCode Settings Example
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"[python]": {
"editor.defaultFormatter": "ms-python.python",
"editor.formatOnSave": true
},
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--line-length", "88"]
}
Common Formatting Patterns
Import/Include Ordering
- Standard/built-in libraries
- Third-party libraries/frameworks
- Local application imports
- Relative imports
Each group should be separated by a blank line and typically alphabetized.
Class Member Ordering
public class Example {
// 1. Constants
private static final String DEFAULT_NAME = "Unknown";
// 2. Static fields
private static int instanceCount = 0;
// 3. Instance fields
private String name;
private int age;
// 4. Constructors
public Example(String name, int age) {
this.name = name;
this.age = age;
instanceCount++;
}
// 5. Static methods
public static int getInstanceCount() {
return instanceCount;
}
// 6. Public instance methods
public String getName() {
return name;
}
// 7. Protected methods
protected void doSomethingInternal() {
// Implementation
}
// 8. Private methods
private void initialize() {
// Implementation
}
}
Chain Method Call Formatting
// Short chains on one line
const names = users.map(user => user.name).filter(name => name.length > 3);
// Long chains with one method per line
const processedData = data
.filter(item => item.isValid)
.map(item => transformItem(item))
.sort((a, b) => a.id - b.id)
.reduce((result, item) => {
result[item.id] = item;
return result;
}, {});
Best Practices for Special Cases
Formatting Complex Conditionals
// Bad: Hard to read complex condition
if (user.isActive && user.hasPermission(ADMIN_ROLE) || user.isSystem && !system.isInMaintenance()) {
// Do something
}
// Good: Breaking into multiple lines with clear operator precedence
if (
(user.isActive && user.hasPermission(ADMIN_ROLE)) ||
(user.isSystem && !system.isInMaintenance())
) {
// Do something
}
// Better: Extract into meaningful variables or functions
const isAdminUser = user.isActive && user.hasPermission(ADMIN_ROLE);
const isAvailableSystemUser = user.isSystem && !system.isInMaintenance();
if (isAdminUser || isAvailableSystemUser) {
// Do something
}
Formatting SQL in Code
# Bad: SQL query hard to read
query = "SELECT u.id, u.name, COUNT(o.id) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE u.status = 'active' GROUP BY u.id, u.name HAVING COUNT(o.id) > 0 ORDER BY order_count DESC LIMIT 10"
# Good: Format SQL for readability
query = """
SELECT
u.id,
u.name,
COUNT(o.id) as order_count
FROM
users u
LEFT JOIN
orders o ON u.id = o.user_id
WHERE
u.status = 'active'
GROUP BY
u.id, u.name
HAVING
COUNT(o.id) > 0
ORDER BY
order_count DESC
LIMIT 10
"""
Formatting Regular Expressions
// Bad: Complex regex on one line
const emailRegex = /^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6})*$/;
// Good: Using RegExp constructor with comments
const emailRegex = new RegExp(
'^([a-zA-Z0-9._%-]+' + // username
'@' + // @ symbol
'[a-zA-Z0-9.-]+' + // domain name
'\\.' + // dot
'[a-zA-Z]{2,6})*$' // domain extension
);
// Alternatively, using verbose flag in languages that support it (like Python)
Common Formatting Anti-Patterns to Avoid
Anti-Pattern | Issue | Better Alternative |
---|
Inconsistent indentation | Mixed tabs/spaces or varying indent depths | Use editor config to enforce consistency |
Extremely long lines | Requires horizontal scrolling | Break lines at logical points |
Deep nesting | Makes code hard to read and follow | Extract nested code into functions |
Comment clutter | Excessive or outdated comments | Keep comments meaningful and maintain them |
Trailing whitespace | Invisible characters causing diffs | Configure editor to remove automatically |
Mixing formatting styles | Inconsistent brace style or spacing | Use automatic formatters |
“Wall of text” code | No visual separation between logical blocks | Use blank lines to group related code |
Misaligned code | Manual alignment that’s hard to maintain | Use standard indentation instead of alignment |
Resources for Further Learning
Style Guides
- Google Style Guides: Comprehensive guidelines for multiple languages
- Airbnb JavaScript Style Guide: Popular JavaScript style reference
- PEP 8: Python’s official style guide
- Microsoft .NET Coding Conventions: Guidelines for C# and .NET development
- Swift API Design Guidelines: Apple’s official Swift style guide
Tools and Documentation
- Prettier Documentation: Configuration options and plugin information
- ESLint Documentation: Rules and customization
- EditorConfig Specification: Property definitions and usage
- IDE-specific formatting guides: VSCode, IntelliJ, Eclipse, etc.
Git Integration Resources
- pre-commit Framework: Documentation and hook examples
- husky: Git hooks for JavaScript projects
- lint-staged: Run linters on staged files
By applying these formatting principles and leveraging automated tools, you can create codebases that are easier to read, maintain, and collaborate on—ultimately saving time and reducing errors in your software development process.