{"course":{"slug":"building-apps-with-ai","title":"Building Apps with AI","url":"https://addaly.com/learn/building-apps-with-ai","level":"beginner","track":"build"},"lesson":{"slug":"naming-things-so-they-stay-findable","title":"Naming things so you can still find them","url":"https://addaly.com/learn/building-apps-with-ai/naming-things-so-they-stay-findable","position":15,"of":87,"minutes":8,"answer":"Fix one word per concept and one naming convention per layer, because in code you did not write the names are the only index you have.","keyIdea":"Fix one word per concept and one naming convention per layer, because in code you did not write the names are the only index you have."},"body":{"format":"markdown","text":"## Names are the index of a project you did not write\n\nWhen you write code yourself, you remember where things are. When a model writes it, the names are the only map you have. A project with inconsistent names is one you cannot search, and searching is how you read a codebase you did not write.\n\nThis is not tidiness. It is the difference between finding the overlap rule in ten seconds and asking the model where it is, getting a wrong answer, and writing a second one.\n\n## One word per concept, everywhere\n\nDecide whether the person paying you is a **customer**, a **client** or a **user**, and then never use the other two. In the database column, in the variable, in the file name, in the button, in your prompts.\n\nWhat happens otherwise is specific and common: the table is `customers`, one file talks about `clients`, a route is `/api/users`, and now searching for any one of them finds two-thirds of the code. Worse, the model reads whichever file it happened to open and continues in that dialect, so the drift compounds.\n\nKeep a short glossary in your rules file:\n\n```\nCustomer — a person who books. Never client or user.\nStylist  — a person who performs services. Never staff or employee.\nBooking  — one appointment. Never reservation or slot.\nSlot     — an available time, not a booking.\n```\n\nFive lines, and the vocabulary stops moving.\n\n## Conventions that stop arguments\n\nThe specific convention matters far less than having one. Pick these and write them down:\n\n- Database tables and columns in `snake_case`, plural tables: `bookings`, `starts_at`.\n- JavaScript variables and functions in `camelCase`: `startsAt`, `findFreeSlots`.\n- React components in `PascalCase`, one per file, filename matching the component: `BookingCard.tsx`.\n- Booleans read as questions: `isCancelled`, `hasPaid`. Never `flag`, never `status2`.\n- Timestamps end in `_at`: `created_at`, `cancelled_at`. Durations name their unit: `duration_minutes`.\n\nThat last one prevents a real bug. A field called `duration` will be filled with minutes in one place and seconds in another, and the code that divides by sixty will be somewhere else entirely.\n\n## The names to refuse\n\n**`data`, `info`, `item`, `thing`, `handleClick2`.** They carry no information, and a model will produce them when it does not know what something is. A variable called `data` is a small sign that the code around it was written without understanding.\n\n**`utils.ts` and `helpers.ts`.** These become the drawer where everything unclassifiable goes. Within a month it is 600 lines of unrelated functions and nobody can find anything. Name files after what they do: `dates.ts`, `money.ts`, `slots.ts`.\n\n**`Manager`, `Service`, `Handler` with nothing else.** `BookingManager` tells you nothing that `bookings.ts` does not.\n\n**Anything with `New`, `2`, `Final` or `Old` in it.** `formatDateNew` means there are two, one of them is wrong, and both are probably still being called. When you see this, delete one immediately or you will debug the wrong file next Tuesday.\n\n## The duplicate check\n\nAsk for this occasionally, and act on the answer:\n\n```\nList every function in this project that formats a date or a price.\nFor each, say which files call it. If two do the same job,\nsay which one to delete.\n```\n\nGenerated codebases accumulate near-duplicates because each request is answered in isolation. Two date formatters differing by a comma is harmless. Two overlap checks differing by whether a booking ending at 14:30 blocks one starting at 14:30 is a bug that reproduces intermittently and will take you a full afternoon.\n\n## Rename early, while it is free\n\nThe day you notice a name is wrong is the cheapest day to fix it. A rename across four files is a two-minute agent task and a clean diff. The same rename across forty files is an afternoon and a risk.\n\nUse your editor's rename rather than search-and-replace where you can: VS Code's F2 understands the language and will not rename a string in a comment or a similarly-named variable in an unrelated file. Then read the diff, because a rename touching files you did not expect means the name was used somewhere you did not know about, and that is worth knowing."},"check":{"question":"A project has both `formatDate` and `formatDateNew`, and both are called from different files. What is the actual risk?","options":[{"text":"The duplicated code makes the bundle larger and slows the page down.","correct":false,"tempting":"Counts bytes for two small functions, which is negligible next to the behavioural divergence between them."},{"text":"Two implementations will drift, so a bug fixed in one still occurs through the other, intermittently.","correct":true},{"text":"The model will be confused about which one to use in future changes.","correct":false,"tempting":"Names a real annoyance while missing the user-visible consequence; the model choosing either is only a problem because they behave differently."},{"text":"The naming convention is inconsistent, which makes the codebase harder to read.","correct":false,"tempting":"Treats a symptom as the harm; the name is a warning sign, not the fault itself."}]},"prev":{"slug":"sketching-the-screens","title":"Sketching the screens, including the empty ones","url":"https://addaly.com/learn/building-apps-with-ai/sketching-the-screens"},"next":{"slug":"examples-beat-descriptions","title":"Examples beat descriptions","url":"https://addaly.com/learn/building-apps-with-ai/examples-beat-descriptions"},"authorship":"Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.","review":{"status":"Draft, open for academic review"},"cite":"Addaly (2026) 'Naming things so you can still find them', in Building Apps with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-apps-with-ai/naming-things-so-they-stay-findable (Accessed: 13 October 2026).","licence":{"name":"CC BY-NC-SA 4.0","url":"https://creativecommons.org/licenses/by-nc-sa/4.0/"},"reader":{"schema":1,"title":"Naming things so you can still find them","courseTitle":"Building Apps with AI","module":{"index":2,"slug":"saying-what-you-want","title":"Saying what you want, precisely enough"},"answer":null,"keyIdea":"Fix one word per concept and one naming convention per layer, because in code you did not write the names are the only index you have.","hero":{"kind":"plate","image":null,"alt":null,"caption":null},"blocks":[{"t":"h2","id":"names-are-the-index-of-a-project-you-did-not-write","runs":[{"text":"Names are the index of a project you did not write"}]},{"t":"p","runs":[{"text":"When you write code yourself, you remember where things are. When a model writes it, the names are the only map you have. A project with inconsistent names is one you cannot search, and searching is how you read a codebase you did not write."}]},{"t":"p","runs":[{"text":"This is not tidiness. It is the difference between finding the overlap rule in ten seconds and asking the model where it is, getting a wrong answer, and writing a second one."}]},{"t":"h2","id":"one-word-per-concept-everywhere","runs":[{"text":"One word per concept, everywhere"}]},{"t":"p","runs":[{"text":"Decide whether the person paying you is a "},{"text":"customer","b":true},{"text":", a "},{"text":"client","b":true},{"text":" or a "},{"text":"user","b":true},{"text":", and then never use the other two. In the database column, in the variable, in the file name, in the button, in your prompts."}]},{"t":"p","runs":[{"text":"What happens otherwise is specific and common: the table is "},{"text":"customers","code":true},{"text":", one file talks about "},{"text":"clients","code":true},{"text":", a route is "},{"text":"/api/users","code":true},{"text":", and now searching for any one of them finds two-thirds of the code. Worse, the model reads whichever file it happened to open and continues in that dialect, so the drift compounds."}]},{"t":"p","runs":[{"text":"Keep a short glossary in your rules file:"}]},{"t":"code","lang":"","label":"Text","text":"Customer — a person who books. Never client or user.\nStylist  — a person who performs services. Never staff or employee.\nBooking  — one appointment. Never reservation or slot.\nSlot     — an available time, not a booking."},{"t":"p","runs":[{"text":"Five lines, and the vocabulary stops moving."}]},{"t":"h2","id":"conventions-that-stop-arguments","runs":[{"text":"Conventions that stop arguments"}]},{"t":"p","runs":[{"text":"The specific convention matters far less than having one. Pick these and write them down:"}]},{"t":"ul","items":[[{"text":"Database tables and columns in "},{"text":"snake_case","code":true},{"text":", plural tables: "},{"text":"bookings","code":true},{"text":", "},{"text":"starts_at","code":true},{"text":"."}],[{"text":"JavaScript variables and functions in "},{"text":"camelCase","code":true},{"text":": "},{"text":"startsAt","code":true},{"text":", "},{"text":"findFreeSlots","code":true},{"text":"."}],[{"text":"React components in "},{"text":"PascalCase","code":true},{"text":", one per file, filename matching the component: "},{"text":"BookingCard.tsx","code":true},{"text":"."}],[{"text":"Booleans read as questions: "},{"text":"isCancelled","code":true},{"text":", "},{"text":"hasPaid","code":true},{"text":". Never "},{"text":"flag","code":true},{"text":", never "},{"text":"status2","code":true},{"text":"."}],[{"text":"Timestamps end in "},{"text":"_at","code":true},{"text":": "},{"text":"created_at","code":true},{"text":", "},{"text":"cancelled_at","code":true},{"text":". Durations name their unit: "},{"text":"duration_minutes","code":true},{"text":"."}]]},{"t":"p","runs":[{"text":"That last one prevents a real bug. A field called "},{"text":"duration","code":true},{"text":" will be filled with minutes in one place and seconds in another, and the code that divides by sixty will be somewhere else entirely."}]},{"t":"h2","id":"the-names-to-refuse","runs":[{"text":"The names to refuse"}]},{"t":"p","runs":[{"text":"data","b":true,"code":true},{"text":", ","b":true},{"text":"info","b":true,"code":true},{"text":", ","b":true},{"text":"item","b":true,"code":true},{"text":", ","b":true},{"text":"thing","b":true,"code":true},{"text":", ","b":true},{"text":"handleClick2","b":true,"code":true},{"text":".","b":true},{"text":" They carry no information, and a model will produce them when it does not know what something is. A variable called "},{"text":"data","code":true},{"text":" is a small sign that the code around it was written without understanding."}]},{"t":"p","runs":[{"text":"utils.ts","b":true,"code":true},{"text":" and ","b":true},{"text":"helpers.ts","b":true,"code":true},{"text":".","b":true},{"text":" These become the drawer where everything unclassifiable goes. Within a month it is 600 lines of unrelated functions and nobody can find anything. Name files after what they do: "},{"text":"dates.ts","code":true},{"text":", "},{"text":"money.ts","code":true},{"text":", "},{"text":"slots.ts","code":true},{"text":"."}]},{"t":"p","runs":[{"text":"Manager","b":true,"code":true},{"text":", ","b":true},{"text":"Service","b":true,"code":true},{"text":", ","b":true},{"text":"Handler","b":true,"code":true},{"text":" with nothing else.","b":true},{"text":" "},{"text":"BookingManager","code":true},{"text":" tells you nothing that "},{"text":"bookings.ts","code":true},{"text":" does not."}]},{"t":"p","runs":[{"text":"Anything with ","b":true},{"text":"New","b":true,"code":true},{"text":", ","b":true},{"text":"2","b":true,"code":true},{"text":", ","b":true},{"text":"Final","b":true,"code":true},{"text":" or ","b":true},{"text":"Old","b":true,"code":true},{"text":" in it.","b":true},{"text":" "},{"text":"formatDateNew","code":true},{"text":" means there are two, one of them is wrong, and both are probably still being called. When you see this, delete one immediately or you will debug the wrong file next Tuesday."}]},{"t":"h2","id":"the-duplicate-check","runs":[{"text":"The duplicate check"}]},{"t":"p","runs":[{"text":"Ask for this occasionally, and act on the answer:"}]},{"t":"code","lang":"","label":"Text","text":"List every function in this project that formats a date or a price.\nFor each, say which files call it. If two do the same job,\nsay which one to delete."},{"t":"p","runs":[{"text":"Generated codebases accumulate near-duplicates because each request is answered in isolation. Two date formatters differing by a comma is harmless. Two overlap checks differing by whether a booking ending at 14:30 blocks one starting at 14:30 is a bug that reproduces intermittently and will take you a full afternoon."}]},{"t":"h2","id":"rename-early-while-it-is-free","runs":[{"text":"Rename early, while it is free"}]},{"t":"p","runs":[{"text":"The day you notice a name is wrong is the cheapest day to fix it. A rename across four files is a two-minute agent task and a clean diff. The same rename across forty files is an afternoon and a risk."}]},{"t":"p","runs":[{"text":"Use your editor’s rename rather than search-and-replace where you can: VS Code’s F2 understands the language and will not rename a string in a comment or a similarly-named variable in an unrelated file. Then read the diff, because a rename touching files you did not expect means the name was used somewhere you did not know about, and that is worth knowing."}]}],"check":{"question":[{"text":"A project has both "},{"text":"formatDate","code":true},{"text":" and "},{"text":"formatDateNew","code":true},{"text":", and both are called from different files. What is the actual risk?"}],"options":[{"text":[{"text":"The duplicated code makes the bundle larger and slows the page down."}],"correct":false,"tempting":[{"text":"Counts bytes for two small functions, which is negligible next to the behavioural divergence between them."}]},{"text":[{"text":"Two implementations will drift, so a bug fixed in one still occurs through the other, intermittently."}],"correct":true,"tempting":null},{"text":[{"text":"The model will be confused about which one to use in future changes."}],"correct":false,"tempting":[{"text":"Names a real annoyance while missing the user-visible consequence; the model choosing either is only a problem because they behave differently."}]},{"text":[{"text":"The naming convention is inconsistent, which makes the codebase harder to read."}],"correct":false,"tempting":[{"text":"Treats a symptom as the harm; the name is a warning sign, not the fault itself."}]}],"order":[2,1,3,0],"why":null},"prev":{"slug":"sketching-the-screens","title":"Sketching the screens, including the empty ones","minutes":8},"next":{"slug":"examples-beat-descriptions","title":"Examples beat descriptions","minutes":8}}}