{"post":{"slug":"how-to-name-variables-well-2026","title":"How to name variables well in 2026: rules that make code read itself","excerpt":"Variable names are the cheapest form of documentation you will ever write. This 2026 guide gives concrete rules, patterns, and anti-patterns for every situation.","category":"code","date":"March 13, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">N</span>aming is the single highest-leverage writing skill in software engineering. A good name collapses the entire mental model of a thing into a word or two. A bad name sends every reader on a detour to figure out what the thing actually is. In 2026, AI-assisted coding makes naming even more important — a well-named codebase produces far better autocomplete and explanation quality than a soup of abbreviations.\n\n## What changed in 2026\n\n- **LLM pair programmers index on names.** GitHub Copilot, Cursor, and similar tools use identifiers as strong signals for suggestion quality. Descriptive names produce dramatically better completions.\n- **Type inference reduced the need for type-in-name.** TypeScript, Python type hints, and Rust make `strUserName` redundant — the type is already visible in the signature.\n- **Linters now flag common naming smells.** ESLint, Ruff, and Clippy have grown rules that catch single-letter variables outside loops and non-question-form booleans.\n- **Code search is ubiquitous.** Everyone uses semantic search now. Descriptive names are searchable; `tmp2` is not.\n\n## The fundamental rule: reveal intent\n\nThe name should tell a reader *what the value is*, not *what data structure holds it* or *how it was computed*.\n\n```python\n# Bad — mechanics, not intent\nd = {}\nlst = []\ntmp = get_data()\nval = user.age * 365\n\n# Good — intent revealed\nusers_by_email = {}\npending_orders = []\nraw_config = get_data()\nage_in_days = user.age * 365\n```\n\n## Scope-based verbosity\n\nLonger scope deserves longer names. The rule of thumb: name length should scale with the distance between declaration and last use.\n\n```typescript\n// Fine: 3-line lambda, 'u' is obvious from context\nconst names = users.map(u => u.name);\n\n// Not fine: 80-line function, 'u' forces the reader to scroll back\nfunction processUsers(u: User[]) {\n  // 40 lines later — is 'u' still users? filtered users? one user?\n}\n\n// Better\nfunction processUsers(activeUsers: User[]) { ... }\n```\n\n## Naming by category\n\n### Booleans\n\nAlways a question: `is*`, `has*`, `can*`, `should*`, `was*`.\n\n```typescript\n// Bad\nlet loading = true;\nlet error = false;\nlet editMode = false;\nlet active2 = true;\n\n// Good\nlet isLoading = true;\nlet hasError = false;\nlet canEdit = false;\nlet isActive = true;\n```\n\n### Functions and methods\n\nUse a verb + object form. The verb describes the action.\n\n| Pattern | Examples |\n| --- | --- |\n| `get*` — returns a value, no side effects | `getUserById`, `getTotal` |\n| `fetch*` — async I/O | `fetchOrders`, `fetchUserProfile` |\n| `set*` — mutates a single value | `setPageTitle`, `setStatus` |\n| `update*` — partial mutation | `updateUserEmail` |\n| `create*` / `build*` | `createInvoice`, `buildQuery` |\n| `handle*` — event handler | `handleSubmit`, `handleClick` |\n| `is*` / `has*` / `can*` — predicate | `isExpired`, `hasPermission` |\n\n### Collections\n\nAlways plural and named by what they contain, not their structure:\n\n```python\n# Bad\nuser_list = []\ndata = {}\nitems = set()\n\n# Good\npending_users = []\nconfig_by_env = {}\nseen_ids = set()\n```\n\n### Constants\n\nSCREAMING_SNAKE_CASE for true constants. Do not use it for values that may change per environment.\n\n```typescript\nconst MAX_RETRY_ATTEMPTS = 3;          // true constant\nconst DEFAULT_PAGE_SIZE = 25;          // true constant\nconst API_BASE_URL = process.env.API_URL; // NOT a constant — it varies\n```\n\n## The naming table\n\n| Situation | Bad | Good |\n| --- | --- | --- |\n| User data map | `map`, `d`, `userData` | `usersByEmail`, `usersById` |\n| Error boolean | `error`, `err2`, `flag` | `hasError`, `isNetworkError` |\n| Async state | `loading`, `fetching` | `isLoading`, `isFetching` |\n| Event handler | `fn`, `handler`, `click` | `handleAddToCart`, `onFormSubmit` |\n| Loop counter | `i` (fine in a 3-line loop) | `rowIndex`, `pageNumber` if loops nest |\n| Temporary result | `tmp`, `res`, `data` | `filteredUsers`, `parsedResponse` |\n\n## How to pick names under pressure\n\n1. **Say it aloud.** If you would not say \"pass me the `isActiveUsers`\" in conversation, the name is off.\n2. **Avoid noise words.** `userInfo`, `dataObject`, `managerHelper` — these add length without meaning. Drop the suffix.\n3. **When in doubt, longer is better.** `accountDeletionScheduledAt` > `deletedAt`. You can always shorten later; you cannot regain lost context.\n4. **Domain language first.** Match your naming to the business domain (invoices, subscriptions, cohorts), not the technical layer (controllers, handlers, processors).\n\n## Common mistakes\n\n**Re-using names in nested scopes.** A `user` variable in the outer scope shadowed by a `user` parameter in a callback is a silent bug waiting to happen.\n\n**Abbreviating inconsistently.** `usr`, `user`, `u`, `usr_obj` for the same concept in the same file. Pick one and lint for it.\n\n**Naming after the type.** `userArray`, `configObject`, `callbackFunction` — the type annotation already says this; the name should say *which* users, *which* config.\n\n**Gerunds for nouns.** `processing`, `loading`, `filtering` as variable names — these sound like actions, not values. If it is a boolean, use `isProcessing`. If it is a list, use `processedItems`.\n\n## What to skip\n\n- **Hungarian notation.** `strName`, `iCount`, `bIsValid` — dropped by most style guides since 2010; type systems make it redundant.\n- **Single-letter names outside a 5-line math/loop context.** `n`, `x`, `t` deep in business logic.\n- **Comments that explain a bad name.** `let d = {}; // dictionary of users by email` — just rename it.\n\n## FAQ\n\n**Should I rename things as I read code?**\nYes, if you can run the tests after. A rename-with-passing-tests is always welcome in a code review.\n\n**What about names that are long and unwieldy?**\nIf a name needs 5+ words to be clear, the concept it represents may need to be extracted into its own type or function.\n\n**How do I name a function that does two things?**\nYou found a bug in the design, not the name. Split the function.\n\n**What about names in SQL?**\nSame rules. `u` as a table alias in a 40-join query is a nightmare. Use `users u` and reference `u.email` — that is acceptable abbreviation.\n\n## Where to go next\n\n- [How to structure a project in 2026](/blog/how-to-structure-a-project-2026)\n- [How to review code effectively in 2026](/blog/how-to-review-code-effectively-2026)\n- [How to write good commit messages in 2026](/blog/how-to-write-good-commit-messages-2026)","hue":322,"metaTitle":"How to Name Variables Well in 2026: Clear Naming Rules","metaDescription":"Practical 2026 rules for naming variables, functions, and types. Intent-revealing names, boolean conventions, scope-based verbosity","keywords":["how to name variables 2026","variable naming conventions 2026","clean code naming","intent-revealing names","boolean variable naming","function naming best practices","naming conventions software engineering","readable code naming","variable name anti-patterns","clean code 2026"],"tldr":["**Names are for humans, not compilers** — the machine does not care; your future self does.","**Reveal intent, not mechanics** — `usersByEmail` beats `map1`; `isEligible` beats `flag`.","**Scope determines verbosity** — one-letter names are fine inside a 3-line lambda; terrible in a 200-line function.","**Booleans must sound like questions** — `isLoading`, `hasError`, `canEdit` — never `loading`, `error2`, `editMode`.","**Skip:** Hungarian notation, type prefixes (`strName`, `bIsActive`), and any name that requires a comment to explain it."],"readTime":"5 min read","wordCount":1018},"related":[{"slug":"how-to-name-variables-2026","title":"How to Name Variables in 2026: clear, practical rules","excerpt":"Good variable names make code readable and bugs rarer. Here are practical naming rules for 2026, with before-and-after examples and conventions by language.","category":"code","date":"June 7, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":222},{"slug":"how-to-write-clean-functions-2026","title":"How to write clean functions in 2026","excerpt":"Clean functions are the single highest-leverage thing you can do for code quality. Here is the 2026 playbook with concrete rules and real examples.","category":"code","date":"March 18, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":318},{"slug":"how-to-write-clean-code-2026","title":"How to write clean code in 2026: principles that actually matter","excerpt":"Clean code is not about style guides or linters — it is about writing code that your future self and teammates can understand and change safely.","category":"code","date":"April 6, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":316}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"how-to-mirror-phone-to-tv-2026","title":"How to mirror your phone to TV in 2026: every method that actually works","excerpt":"Screen mirroring from phone to TV is easier than ever in 2026, but the right method depends on your phone and TV. Here is what works and what to skip.","category":"tech","date":"March 13, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":230},"older":{"slug":"how-to-negotiate-a-raise-for-more-money-2026","title":"How to negotiate a raise for more money in 2026: a practical script","excerpt":"Most people never ask for a raise, and most who do ask without preparation. Here is the 2026 framework for researching market rate, building your case, and having the conversation that actually gets you more money.","category":"finance","date":"March 13, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":312}}