A variable naming brainstorm is a focused, collaborative session to refine and standardize variable names across a codebase or project. It matters when a team begins a new module, refactors a monolithic service, or discovers that inconsistent naming undermines readability, maintainability, and onboarding. The goal is to produce a shared vocabulary of variables that reflect intent, avoid ambiguity, and reduce cognitive load across the codebase.

Preparing for the Brainstorm

Before the session, gather all variables currently used in the domain under discussion. Use a standard tool to extract them from source code. For example, with rg (ripgrep), run:

rg '\b[a-zA-Z_][a-zA-Z0-9_]*\b' --type=js --files-with-matches src/

This yields a list of all identifiers in JavaScript files. Filter for variables (not functions, classes, or types) by scanning for let, const, var, and function definitions. For a more precise extraction, use ast-based tools like ts-morph or babel to build a flat list of variable declarations.

Export the raw list to a CSV or Markdown table:

name, type, scope, usage, file
userProfile, Object, function, "used to store user preferences", src/auth/userService.ts
items, Array, module, "list of products from API", src/cart/cartReducer.ts
idx, number, loop, "index in for-of loop", src/ui/ItemList.tsx

This list becomes the foundation of the brainstorm. Share it in a collaborative document (e.g., Google Docs, Notion, or Markdown in a GitHub repo). Each participant should review the list before the session.

Conducting the Brainstorm

1. Surface the Current State

Begin by reviewing the variable list as a group. For each variable, clarify its role: what it represents, how it’s constructed, and where it’s used. Use the following questions:

  • What is the *unit* of this variable? (e.g., “a user profile” vs. “a list of users”)
  • What is the *scope* of its lifetime? (e.g., “per HTTP request”, “per session”, “global across app”)
  • What operations are performed on it? (e.g., “updated on login”, “filtered before rendering”)
  • Is its name *self-documenting*? Does it communicate intent without reading the code?

For each variable, write a concise definition in the format:

> userProfile: A full object containing user preferences, identity, and settings, updated on login and persisted to storage.

If a name is ambiguous, flag it. Common issues include:

  • Type confusion: data is used for Array, Object, string, and number interchangeably.
  • Scope leakage: config is used both as a module-level constant and as a runtime object.
  • Ambiguous abbreviations: ctx for context, cfg for config, res for result, usr for user.
  • Inconsistent capitalization: userName, username, UserName, user_name.

2. Apply Naming Principles

Use a checklist of naming principles to guide discussion. These are not abstract ideals, but concrete, actionable rules.

Principle: Use the Unit as the Base

A variable name should reflect the *thing* it represents, not the *data* about it.

  • ✅ userProfile instead of userProfileData
  • ✅ orderTotal instead of totalAmountOfOrder
  • ✅ invoiceLines instead of linesInInvoice

Apply this principle to all variables. For each, ask: “If I showed this variable to a non-technical stakeholder, would they understand what it is?”

Principle: Prefer Descriptive Over Short

Short names are good for local scope, but avoid i, j, k unless in tight loops. Use longer, clearer names in function signatures and module-level variables.

  • ✅ cartItems over items in a cart module
  • ✅ billingAddress over addr
  • ✅ sessionTimeoutInSeconds over timeout

Principle: Use Consistent Suffixes for Categories

Define a standard suffix pattern for common types:

  • id: userId, productId, sessionId
  • list, array, items: userList, orderItems, productArray
  • count, total, sum: itemCount, orderTotal, cartSum
  • is, has, can, should: isAuthenticated, hasPendingOrders, canCheckout
  • error, response, result: validationError, fetchUsersResponse, loginResult

Apply the pattern across the codebase. If fetchUsersResponse exists, use fetchProductsResponse, fetchCartResult, etc.

Principle: Distinguish Mutable and Immutable Variables

Use current, next, updated, new, original, prev, latest to distinguish state transitions.

  • currentCart vs. newCart
  • updatedUser vs. user
  • prevOrder vs. latestOrder

This helps avoid confusion between “the current state” and “the original state”.

3. Resolve Ambiguities and Conflicts

Use the group’s list of flagged variables to resolve naming conflicts. For each variable, propose alternatives and vote on them.

For example, consider data:

  • Proposal: Rename data to apiResponse when it comes from a remote endpoint.
  • Rationale: data is now used for in-memory objects, while apiResponse clearly signals network origin.

Similarly, resolve config vs. settings:

  • Decision: Use config for module-level constants (e.g., config.maxRetries), settings for user-facing, persisted values (settings.theme, settings.language).

Create a naming glossary in a shared document:

| Name           | Meaning                                      | Example Usage                        |
|----------------|----------------------------------------------|--------------------------------------|
| `userProfile` | Full user object with preferences, identity | `const profile = await fetchProfile()` |
| `apiResponse` | Response from a remote API                   | `const response = await fetch('/users')` |
| `currentCart` | The cart in the user’s session               | `updateCart(currentCart, newItems)` |
| `newOrder`    | A draft order being built                    | `const newOrder = createEmptyOrder()` |
| `isAuthenticated` | Flag indicating login state             | `if (isAuthenticated) renderDashboard()` |

4. Identify and Resolve Naming Patterns

Look for recurring patterns across the codebase. When two variables serve similar roles, they should follow the same naming convention.

For example, if fetchUsers, fetchProducts, and fetchOrders exist, standardize on the pattern:

> fetch[Entity][Action] → fetch[Entity][Action] where: > - [Entity] is the noun (e.g., User, Product, Order) > - [Action] is the verb (e.g., List, ById, Recent, All)

Apply this pattern to other functions:

  • fetchUserById → fetchProductById, fetchOrderById
  • fetchUserList → fetchProductList, fetchOrderList

Also identify and define composite patterns:

  • load[Entity] → loadUser, loadCart, loadSettings
  • create[Entity] → createUser, createOrder, createSession
  • [Entity]Updated → userUpdated, orderUpdated, cartUpdated

These patterns become rules for new code.

Refining the Output

1. Generate a Naming Checklist

Compile a concise, actionable checklist for future contributors. This is the artifact of the session.

> Variable Naming Checklist > > - [ ] Use current[Entity] for the current state > - [ ] Use new[Entity] for the updated, upcoming state > - [ ] Use fetch[Entity][Action] for API calls > - [ ] Use load[Entity] for loading from storage > - [ ] Use is[Feature] for boolean flags > - [ ] Use updated[Entity] for modified versions of an entity > - [ ] Prefer Entity[Count], EntityTotal, EntityList over count, total, list > - [ ] Avoid data, result, info, item unless clearly scoped > - [ ] Use apiResponse, serverError, clientRequest for network-related variables

2. Update the Codebase

Apply the new naming conventions across the codebase. Use sed, find, and grep to identify and rename variables.

For example, rename config to settings in all .ts files:

find src -name "*.ts" -exec sed -i 's/\bconfig\b/settings/g' {} \;

Then, use rg to verify:

rg 'settings\.' src/

Also, create a naming-guidelines.md file in the project root with the glossary and checklist.

3. Document the Process

Create a brainstorm.md file in docs/techniques/variable-naming-brainstorm/ that records:

  • The date and participants
  • A summary of decisions
  • The final naming glossary
  • The naming checklist
  • Links to code changes

This document becomes the canonical reference for future sessions.

Common Pitfalls and Silent Failings

The “Default” Name That Was Never Chosen

Many teams adopt data as the default for everything. But data is not a name—it’s a placeholder. The silent failure: after months of data, data becomes a black box, and readers must trace it back to its origin.

> Failure mode: A function returns data, but data is used in a loop, then transformed into data, then passed to another function. No one knows what data represents.

Fix: Define a rule: “Use data only when the type is unclear and the scope is local.” Else, use a more specific name.

Confusing list, array, items, collection

These terms are often used interchangeably, but each carries subtle meaning:

  • list → order matters, index-based, possibly mutable
  • array → more technical, often used in function signatures
  • items → a collection of discrete, similar objects
  • collection → a general-purpose container, often with methods

Failure mode: items is used for a list of users, but items is also used for a list of products. The reader assumes they’re the same, but they’re not.

Fix: Standardize:

  • Use userItems for a list of users
  • Use productList for a sorted array of products
  • Use userCollection for a set-like structure with deduplication

The “Context” Problem

ctx is common, but its meaning varies. When is ctx the request context? The component context? The state context?

Failure mode: ctx is passed through three layers of functions, but no one remembers what ctx.userId means.

Fix: Define ctx as a request context object with keys: userId, sessionId, requestId, headers, query, body, user.

Then, use:

  • componentCtx for component state
  • stateCtx for state machine context
  • requestCtx for HTTP request context

This prevents ambiguity.

Overuse of input, output, result, response

These names are often used without distinction. But they serve different roles:

  • input → data provided to a function
  • output → data returned by a function
  • result → the final outcome of a process
  • response → data from a remote service

Failure mode: A function returns result, but result is used as response in the next step.

Fix: Create a hierarchy:

  • input → output → result → response
  • Use input in function parameters
  • Use output in function return values
  • Use result for a processed value
  • Use response for an object returned by an HTTP call

Post-Brainstorm Maintenance

After the session, maintain the naming standard with a naming review process:

  • Every pull request must include a naming audit.
  • Use a GitHub action or pre-commit hook to check variable names against the glossary.
  • Run a weekly naming-report script:
#!/bin/bash


echo "=== Variable Naming Report ==="
echo "Current glossary:"
cat docs/techniques/variable-naming-brainstorm/naming-guidelines.md | grep -B 1 -A 2 '---' | grep -v '^---$'

echo -e "\nVariables with common but ambiguous names:"
rg '\b(data|result|input|output|config|settings|ctx|id)\b' --files-with-matches src/ | xargs grep -l '\b(data|result|input|output|config|settings|ctx|id)\b'

This report is reviewed every two weeks. Any new inconsistency triggers a new brainstorm session.

The variable naming brainstorm is not a one-time event, but a living practice. It evolves with the codebase, and its success is measured not in pages or meetings, but in clarity: when a developer reads a function and knows, without reading a line of code, what each variable represents.

This page was rewritten on 11 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.