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
andin the name" —saveAndNotifyis 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
- Open your capstone and find the three worst-named things. Rename them.
- Find every variable holding money and confirm each has
Paisein the name. - Find every timeout or delay and confirm each has
Ms. - Find an
asyncfunction whose name does not imply going somewhere. Rename it. - Call an
asyncfunction withoutawaitand render the result into the DOM. Look at what appears. - Search your code for
data,info,manager,helper,util. Try deleting the word from each. - Find a boolean not starting with
is,has,canorshould. Read a call site aloud. - Find two words used for the same concept and pick one.
- Find a function with
andin its name and split it. - 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