RizTech Academy logo
RizTech Academy
Best Practices: Code Others Can ReadLesson 1 of 535 min

Naming things, which is most of the job

You will spend far more time reading code than writing it — your own included, six months later. A name is the interface between what the code does and what the next person believes it does, and where those drift apart is where bugs live.

JavaScript makes this matter more than most languages, because there are no types in the signature. function process(x) tells you nothing at all.

The conventions

Thing Convention Example
Variable, function, method camelCase totalPaise, loadRates
Class PascalCase OrderStore
Constant (module-level, fixed) UPPER_SNAKE_CASE MAX_PIECES
Private class field #name #count
"Internal" by convention leading underscore _cache
File kebab-case.js order-store.js
Component file (React) PascalCase.jsx OrderRow.jsx
Deliberately unused _ .map((_, i) => i)

Two notes:

UPPER_SNAKE_CASE is for genuine constants — a fixed value known at authoring time, like const MAX_PIECES = 50. Not for everything declared with const. const orders = [] is a const binding holding a mutable array; it is not a constant.

#private is real privacy, unlike a leading underscore. order.#count from outside is a syntax error, not a convention.

Say what, not how

// how
function filterArrayWithReduceLoop(items, month) { … }

// what
function ordersIn(month) { … }

The second survives changing the implementation. The first is a comment about the current body, written where it cannot be ignored, and it becomes a lie the moment somebody rewrites it as a filter.

Length should match scope

orders.map((o) => o.pieces)

o is fine — it is born and dies within the same line. But a name that lives longer has to carry more:

const ordersByCustomer = new Map();   // good
const m = new Map();                  // not

The further a name travels, the more it must carry. A callback parameter, one letter. A module-level export, a full phrase.

Put the unit in the name

The single highest-value habit:

const amountPaise = 28_500;
const timeoutMs = 300;
const fileSizeBytes = 1_048_576;

amount raises a question the reader must answer elsewhere — rupees or paise? amountPaise cannot be misread, and the day somebody writes amountPaise = 285 meaning ₹285, the name is arguing with them.

timeoutMs matters especially in JavaScript, where every timing API takes milliseconds and people routinely pass seconds.

Numeric separators help too: 28_500 is obviously twenty-eight and a half thousand; 28500 needs counting.

Booleans read as questions

if (order.isDelivered) …
if (cart.hasItems()) …
if (user.canEdit(order)) …

is, has, can, should. The test is whether the if reads as English.

And avoid negatives — if (!order.isNotDelivered) is two negatives and one confused reader.

Async functions should look async

async function loadRates() { … }         // returns a promise
function formatRates(rates) { … }        // returns a value

There is nothing in a call site that tells you whether you need await, so the name and the async keyword are carrying it. A function that returns a promise and is named like a plain getter is how [object Promise] ends up rendered on a page.

Some teams suffix them — loadRatesAsync — which is a C# habit and usually unnecessary if the verb is right. load, fetch, save and send all imply going somewhere.

Say no to the noise words

orderData        // as opposed to an order that is not data?
orderInfo
orderObject
processOrder     // "process" means nothing
handleOrder      // except for event handlers, where it is conventional
doSave()
manageOrders()

manager, helper, util, data, info, object, process. If removing the word does not change the meaning, remove it.

handleClick is the exception — handle is an established convention for event handlers and reads correctly there.

A function you cannot name is usually doing more than one thing. That is a design problem surfacing as a naming problem.

Be consistent about one idea

// Pick one:
getOrder / fetchOrder / loadOrder / retrieveOrder

Two words for the same thing makes the reader hunt for a distinction that does not exist. Two words for genuinely different things is right — your capstone uses order for a row and item for a line on the rate card, and those differ.

JavaScript's own traps

Do not shadow globals.

const name = "Asha";        // shadows window.name at the top level of a script
const length = 5;
const event = {};
const location = "Pune";

At module scope this is harmless. In a plain <script> it can collide with window properties in ways that produce genuinely baffling behaviour — window.name is a string the browser owns, and assigning a number to it silently converts.

Beware arguments and this in arrows. An arrow has neither of its own, so naming something arguments inside one is a confusing thing to do to the next reader.

Event handler naming has a convention worth following:

// the handler
function handleSubmit(event) { … }
// the prop or option that receives it
<form onSubmit={handleSubmit}>

onX is the slot, handleX is the function. Mixing them up makes React code hard to skim.

Names as a design signal

  • "I cannot name this function" — it probably does two things.
  • "I need and in the name" — saveAndNotify is two functions.
  • "I keep writing manager" — the responsibility is not clear yet.
  • "The name is very long" — either it does too much, or it belongs somewhere the context is implied.
// hard to name
function processOrderAndUpdateTotalsAndSave(order) { … }

// easy to name
function addOrder(order) { … }
function recalculateTotals() { … }
function save() { … }

Check your work

Why names matter more in JavaScript: there are no types in the signature.

What UPPER_SNAKE_CASE is actually for: a fixed value known at authoring time, not everything declared const.

What #private gives you that an underscore does not: a syntax error rather than a convention.

Why name what, not how: a name describing the body becomes a lie when the body changes.

The highest-value habit: the unit in the name — amountPaise, timeoutMs.

How booleans should read: as a question.

Why async names matter: nothing at the call site says you need await, so the verb has to.

Which noise words to delete: manager, helper, util, data, info, process — but handle is conventional for event handlers.

The onX / handleX convention: on is the slot, handle is the function.

What naming difficulty tells you: a function you cannot name does two things.

Practice

  1. Open your capstone and find the three worst-named things. Rename them.
  2. Find every variable holding money and confirm each has Paise in the name.
  3. Find every timeout or delay and confirm each has Ms.
  4. Find an async function whose name does not imply going somewhere. Rename it.
  5. Call an async function without await and render the result into the DOM. Look at what appears.
  6. Search your code for data, info, manager, helper, util. Try deleting the word from each.
  7. Find a boolean not starting with is, has, can or should. Read a call site aloud.
  8. Find two words used for the same concept and pick one.
  9. Find a function with and in its name and split it.
  10. Ask somebody to guess what one of your functions does from its name alone.

Next: how big is too big.

Stuck on this lesson?

Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.

About the internship