Skip to main content

Naming conventions 3: improving naming quality

This article is Part 3 of the three-part series on naming conventions. Building on the basics covered in Part 1: case conventions, variables, and constants and Part 2: Functions and Classes, it presents principles for improving naming quality, a comprehensive exercise, and an overall summary.

Use pronounceable, meaningful names​

❌ Bad: Abbreviated, unpronounceable
// ❌ Bad: Abbreviated, unpronounceable
const genYmdhms = (): string => {
const now = new Date();
const pad = (n: number) => String(n).padStart(2, "0");
return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`;
};

const dfColor = "#fff";
const usrCnt = 10;

// ✅ Good: Pronounceable with clear meaning
const generateTimestamp = (): string => {
const now = new Date();
const pad = (n: number) => String(n).padStart(2, "0");
return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`;
};

const defaultColor = "#fff";
const userCount = 10;

Reasons:

  • Easier to discuss with teammates
  • Easier to explain in code reviews
  • Easier for new members to understand

Use plural forms for arrays and lists​

A variable that represents an array or list is recognizable as an array at a glance when it is plural.

❌ Bad: Singular
// ❌ Bad: Singular
const user = [{ id: 1 }, { id: 2 }];
const item = ["apple", "banana", "orange"];

user.forEach(u => console.log(u)); // Hard to tell that user is an array

// ✅ Good: Plural
const users = [{ id: 1 }, { id: 2 }];
const items = ["apple", "banana", "orange"];

users.forEach(user => console.log(user)); // Clear that users is the array and user is the element

// ✅ Use plural forms in TypeScript type definitions too
type User = {
id: number;
name: string;
};

type Users = User[];

Irregular plurals​

✅ Good: Irregular English plurals
// ✅ Irregular English plurals
const children = [child1, child2]; // child → children
const people = [person1, person2]; // person → people
const mice = [mouse1, mouse2]; // mouse → mice

// ✅ Same singular and plural
const sheep = [sheep1, sheep2]; // sheep → sheep
const fish = [fish1, fish2]; // fish → fish

Unify words with the same meaning​

The scope of this unification is the whole project.

❌ Bad: Different words for the same concept
// ❌ Bad: Different words for the same concept
class UserController {
getUser(id: string): User { }
}

class ProductController {
fetchProduct(id: string): Product { } // ❌ get and fetch are mixed
}

class OrderController {
retrieveOrder(id: string): Order { } // ❌ retrieve is mixed in too
}

// ✅ Good: Unified
class UserController {
getUser(id: string): User { }
}

class ProductController {
getProduct(id: string): Product { }
}

class OrderController {
getOrder(id: string): Order { }
}

// ────────────────────────────────────────────
// Other unification examples
// ────────────────────────────────────────────

// ❌ Bad: Multiple words for deletion
function removeUser(id: string) { }
function deleteProduct(id: string) { }
function eraseOrder(id: string) { }

// ✅ Good: Unified on delete
function deleteUser(id: string) { }
function deleteProduct(id: string) { }
function deleteOrder(id: string) { }

Common similar words​

MeaningCandidates
Retrieveget / fetch / retrieve
Deletedelete / remove / erase
Createcreate / make / build
Updateupdate / modify / edit
Sendsend / submit / post
Displayshow / display / render

Recommended approach: Create a glossary for your project and share it across the whole team.

✅ Good: A project terminology example (glossary.ts)
// ✅ A project terminology example (glossary.ts)
/**
* Project glossary
*
* - Retrieve data: get (fetch when asynchronous)
* - Create data: create
* - Update data: update
* - Delete data: delete
* - Display: show
*/

Use contrasting words​

For values with opposite meanings, use names that form a contrast.

✅ Good: Examples of contrasting words
// ✅ Examples of contrasting words

// start ⇔ end
const startTime = new Date();
const endTime = new Date();

function startTimer() { }
function stopTimer() { } // ✅ start ⇔ stop

// min ⇔ max
const minValue = 0;
const maxValue = 100;

// previous ⇔ next
const previousPage = 1;
const nextPage = 3;

// first ⇔ last
const firstItem = items[0];
const lastItem = items[items.length - 1];

// open ⇔ close
function openModal() { }
function closeModal() { } // ✅ open ⇔ close

// show ⇔ hide
function showElement() { }
function hideElement() { } // ✅ show ⇔ hide

// enable ⇔ disable
function enableFeature() { }
function disableFeature() { } // ✅ enable ⇔ disable

// ❌ Bad: The contrast is unclear
function startProcess() { }
function endProcess() { } // ❌ Don't mix start and end for action functions

// ✅ Good
function startProcess() { }
function stopProcess() { } // ✅ start ⇔ stop

Use different pairs for points in time versus actions: for variables representing a point in time, startTime ⇔ endTime (start ⇔ end) is a natural pair. For functions representing an action, align them as start ⇔ stop or begin ⇔ end. The counterpart of startProcess is stopProcess.

Common contrasting words​

Start / actionOpposite
startstop (end)
beginend (finish)
openclose
showhide
enabledisable
activatedeactivate
lockunlock
firstlast
minmax
previousnext
incrementdecrement
addremove
insertdelete
pushpop
acquirerelease

Avoid meaningless words​

Generic words like Data, Info, and Manager provide no concrete information on their own. What you should avoid is a name made only of generic words, such as DataManager. When the thing being managed or described is clear, as in SessionManager or FileMetadata, there is no problem.

❌ Bad: Meaningless words
// ❌ Bad: Manager is too abstract (it's unclear what data it manages)
class DataManager {
processData() { }
}

// ✅ Good: Show the concrete responsibility
class UserRepository {
findById(id: string): User | null { }
save(user: User): void { }
}

// ────────────────────────────────────────────

// ❌ Bad: Object, Thing, and other abstractions
const userObject = { name: "Taro" };
const dataThing = [1, 2, 3];

// ✅ Good
const user = { name: "Taro" };
const numbers = [1, 2, 3];

There are exceptions, though​

Some words carry meaning in specific contexts.

✅ Good: Acceptable examples
// ✅ Acceptable examples

// Metadata: the specific meaning of "data about data"
interface FileMetadata {
size: number;
createdAt: Date;
mimeType: string;
}

// Config/Settings: a conventional name representing configuration
interface AppConfig {
apiUrl: string;
timeout: number;
}

// Context: a convention in frameworks such as React/Angular
const UserContext = React.createContext<User | null>(null);

Abbreviating variable names​

Use abbreviations only when they are generally recognized.

✅ Good: Generally recognized abbreviations
// ────────────────────────────────────────────
// ✅ Generally recognized abbreviations
// ────────────────────────────────────────────

// ID (identifier)
const userId = "12345";
const productId = 100;

// URL (Uniform Resource Locator)
const apiUrl = "https://api.example.com";

// HTTP (HyperText Transfer Protocol)
const httpClient = new HttpClient();

// API (Application Programming Interface)
const apiResponse = await fetchData();

// DB (Database)
const dbConnection = createConnection();

// Auth (Authentication)
const authToken = "abc123";

// Config (Configuration)
const appConfig = loadConfig();

// Temp (Temporary)
const tempValue = calculateTemp();

// Max/Min (Maximum/Minimum)
const maxRetries = 3;
const minValue = 0;

// Prev/Next (Previous/Next)
const prevPage = 1;
const nextPage = 3;

// ────────────────────────────────────────────
// ❌ Abbreviations to avoid
// ────────────────────────────────────────────

// ❌ Custom abbreviations
const usrNm = "Taro"; // ✅ userName
const prdLst = []; // ✅ productList
const calcTtl = () => {}; // ✅ calculateTotal

// ❌ Just dropping vowels
const btn = document.querySelector('button'); // ✅ button
const msg = "Hello"; // ✅ message
const err = new Error(); // ✅ error (err is sometimes acceptable)

// ❌ Abbreviations that make no sense without context
const d = new Date(); // ✅ date or currentDate
const i = 0; // ✅ index or count (outside of loops)
const tmp = getValue(); // ✅ temporary or a concrete name

Abbreviating loop variables is acceptable​

✅ Good: Conventional abbreviations are acceptable in loops
// ✅ Conventional abbreviations are acceptable in loops
for (let i = 0; i < 10; i++) {
console.log(i);
}

// ✅ Nested loops
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
matrix[i][j] = 0;
}
}

// ✅ When a more meaningful name is preferable
for (let userIndex = 0; userIndex < users.length; userIndex++) {
const user = users[userIndex];
// ...
}

// ✅ Use full names with forEach/map
users.forEach(user => { // ✅ user (not u)
console.log(user.name);
});

Exercise 5: A comprehensive naming exercise​

Fix the following code to follow the naming conventions for clean code.

❌ Bad: Before
// ❌ Before

const d = new Date();
const usrCnt = 100;

interface prdData {
id: number;
nm: string;
prc: number;
}

class usrMgr {
getUsrInf(id: number) {
// ...
}

delUsr(id: number) {
// ...
}
}

function calcTtl(items: any[]) {
let t = 0;
for (let i = 0; i < items.length; i++) {
t += items[i].prc;
}
return t;
}

const isNotComplete = false;
if (!isNotComplete) {
// ...
}
Answer and explanation
✅ Good: After
// ✅ After

const currentDate = new Date();
const userCount = 100;

interface ProductData {
id: number;
name: string;
price: number;
}

class UserManager {
getUser(id: number) {
// ...
}

deleteUser(id: number): void {
// ...
}
}

function calculateTotal(items: ProductData[]): number {
let total = 0;
for (let i = 0; i < items.length; i++) {
total += items[i].price;
}
return total;
}

// Avoid negative forms
const isComplete = true;
if (isComplete) {
// ...
}

calculateTotal also has an alternative using reduce.

✅ Good: Alternative (using reduce)
function calculateTotal(items: ProductData[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}

Key fixes:

  1. d → currentDate: clarify the meaning
  2. usrCnt → userCount: avoid abbreviation
  3. prdData → ProductData: PascalCase
  4. nm → name, prc → price: full words
  5. usrMgr → UserManager: PascalCase
  6. getUsrInf → getUser: use full words and remove the redundant "Info"
  7. delUsr → deleteUser: full word + unified verb
  8. calcTtl → calculateTotal: full words
  9. t → total: a meaningful name
  10. isNotComplete → isComplete: avoid the negative form

Summary of naming conventions​

TargetRuleExample
VariablecamelCaseuserName, itemCount
ConstantUPPER_SNAKE_CASEMAX_COUNT
FunctioncamelCasegetUserById
ClassPascalCaseUserService
InterfacePascalCaseUserProfile
Type aliasPascalCaseUserId
EnumPascalCaseUserRole
Booleanis / has / can / should + state/abilityisValid, canEdit
ArrayPluralusers, items
Naming principles
  • Use names with clear intent
  • Use searchable names
  • Maintain consistency
  • Reduce the reader's cognitive load

  • Comments — the idea of leaving only what code cannot express in comments
  • Variables — handling variables, which together with naming supports readability