Skip to content

Standards and Guidelines

This page provides cross-language reference material that applies regardless of which stack you are working in. For language-specific rules, see the dedicated section for your language.

Naming Conventions — Cross-Language Reference

Naming is one of the most impactful decisions you make as a developer. A well-named variable, function, or class communicates intent without requiring a comment. The rules below apply universally — the specific casing style varies per language.

Casing styles

Style Format Used for
PascalCase UserService, OrderStatus Classes, interfaces, types, React components
camelCase getUserById, totalAmount Functions/methods, variables (JS/TS/Java)
snake_case get_user_by_id, total_amount Functions, variables (Python, Go, SQL columns)
UPPER_SNAKE_CASE MAX_RETRY_COUNT, SESSION_TIMEOUT Constants in all languages
kebab-case user-profile, order-service File names (React components), URL paths, CSS classes
dotted.lowercase com.cygnus.service.user Java/C# package and namespace names

Universal naming rules

These rules apply across all languages and frameworks:

Be descriptive — names should reveal intent

# ✅ Correct — intent is clear
user_registration_count = 0
is_payment_confirmed = False
eligible_orders = get_orders_eligible_for_refund()

# ❌ Incorrect — vague, cryptic, or abbreviated without reason
n = 0
flag = False
data = get_data()

Booleans should read as true/false questions

// ✅ Correct — reads naturally as a question
const isActive = user.status === 'active';
const hasPermission = roles.includes('admin');
const canRetry = attemptCount < MAX_RETRIES;

// ❌ Incorrect — does not read as a boolean
const active = user.status === 'active';
const permission = roles.includes('admin');
const retry = attemptCount < MAX_RETRIES;

Functions should be named with a verb

// ✅ Correct — verb makes the action clear
getUserById(id)
calculateOrderTotal(items)
validatePaymentMethod(card)
sendWelcomeEmail(user)
isEligibleForDiscount(user)

// ❌ Incorrect — noun or vague name
user(id)
orderTotal(items)
paymentMethod(card)
email(user)
discount(user)

Collections should be plural

// ✅ Correct
var orders []Order
var userIDs []int64
activeUsers := getActiveUsers()

// ❌ Incorrect
var order []Order
var userID []int64
activeUser := getActiveUsers()

Avoid abbreviations unless universally known

// ✅ Acceptable abbreviations — universally understood
const userId = req.params.id;
const apiUrl = process.env.API_URL;
const htmlContent = renderTemplate(dto);

// ❌ Avoid — saves a few characters, costs clarity
const usrId = req.params.id;
const au = process.env.API_URL;
const cnt = items.length;
const mgr = new OrderManager();

Universally accepted abbreviations: id, url, api, dto, html, css, db, ui, io, err, ctx, req, res, idx.

Avoid generic names

Names like data, info, temp, obj, val, item, thing, stuff, and result (when used without a qualifier) convey nothing about what the value represents.

# ✅ Correct — name reflects the actual value
order_response = fetch_order(order_id)
user_email = extract_email(payload)
discounted_total = apply_promo(cart, promo_code)

# ❌ Incorrect — generic names that force the reader to trace the value
data = fetch_order(order_id)
temp = extract_email(payload)
result = apply_promo(cart, promo_code)

File and Module Naming

Language Convention Example
Java PascalCase, matches class name OrderService.java
Python snake_case order_service.py
TypeScript / JavaScript camelCase for utilities, PascalCase for classes/components orderUtils.ts, UserCard.tsx
Go snake_case order_service.go
C# PascalCase, matches class name OrderService.cs
SQL migrations Timestamp prefix + description 20260315_001_add_is_gift_to_orders.sql
Test files Match the file under test + test suffix order_service_test.go, test_order_service.py

Error Naming

Errors and exceptions should always end with Error or Exception (language convention) and describe the condition that caused them — not the technical mechanism.

# ✅ Correct — describes the business condition
class OrderNotFoundError(Exception): ...
class InsufficientFundsError(Exception): ...
class InvalidPromoCodeError(Exception): ...

# ❌ Incorrect — describes implementation, not the condition
class DatabaseLookupError(Exception): ...  # too vague — what was being looked up?
class NullValueException(Exception): ...   # language-level detail — not business language
class Exception1(Exception): ...          # completely meaningless

Constants and Configuration

All constants must be:

  • Defined in a single place — never duplicated across files.
  • Named in UPPER_SNAKE_CASE in every language.
  • Accompanied by a comment if the value is not self-explanatory (e.g. why 1800 seconds, why 5 attempts).
# ✅ Correct — named, justified, centralised
MAX_LOGIN_ATTEMPTS = 5          # lock account after 5 failed attempts (security policy SP-03)
SESSION_TIMEOUT_SECONDS = 1800  # 30 minutes — per compliance requirement
DEFAULT_CURRENCY = "GBP"
API_VERSION = "v1"
// ✅ Correct — typed constants with explanation where needed
const MAX_FILE_UPLOAD_BYTES = 10 * 1024 * 1024; // 10 MB — matches nginx limit in infra config
const SUPPORTED_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/webp'] as const;
const DEFAULT_PAGE_SIZE = 20;

Code Organisation Principles

Files and modules should be organised around features or domains, not technical layers. Co-locating the service, repository, model, and tests for a feature makes it easier to find and change related code.

# ✅ Feature-based organisation (preferred)
src/
  orders/
    order.model.ts
    order.service.ts
    order.repository.ts
    order.controller.ts
    order.service.test.ts

# ❌ Layer-based organisation (avoid for large codebases)
src/
  models/
    order.model.ts
  services/
    order.service.ts
  repositories/
    order.repository.ts

One public class or function per file

Each file should export one primary concept. Multiple exports in a single file are acceptable for closely related helpers, but the file name should reflect the primary export.

Limit file length

Files over 300 lines are a signal that the file is doing too much. Split by responsibility before the file grows further.

Formatting Principles

The following apply across all languages. Language-specific formatting tools enforce these automatically — see each language section for the approved tool and configuration.

Principle Rule
Indentation Use spaces, not tabs. 4 spaces for Java/Python/C#, 2 spaces for JS/TS/Go
Line length Maximum 120 characters. Break long lines logically
Trailing whitespace Never. Configure your editor to strip it on save
Blank lines One blank line between logical sections. Two between top-level declarations
Braces Always use braces for control flow — even single-line bodies (Java, C#, Go, JS/TS)
Semicolons Follow language convention. TypeScript/JavaScript: always use semicolons

Let the formatter decide

Most formatting decisions should be made by your language's approved auto-formatter — not by personal preference or code review debate. Black (Python), Prettier (JS/TS), Google Java Format, and gofmt (Go) are non-negotiable. Configure them and move on.

Dependency Management

Rule Why
Pin dependency versions in package.json, requirements.txt, or equivalent Unpinned versions cause non-reproducible builds
Never commit node_modules, .venv, or build artefacts They belong in .gitignore
Run dependency vulnerability scans in CI (npm audit, pip-audit, trivy) Catch known vulnerabilities before they reach production
Review the changelog before upgrading a major version Major version upgrades can introduce breaking changes
Use a lockfile (package-lock.json, poetry.lock, go.sum) Lockfiles ensure consistent installs across environments