Writing Better Code Series: Episode 1 - Naming

Hey there, Coding Chefs! 👨‍💻

TLDR: Good naming in code follows the same principles as good mathematical notation - clear, descriptive, and communicative. Your variable names should tell a story, just like how mathematical symbols and steps should clearly show your reasoning process.


I graduated as the top mathematics student in my class, and people often ask me what made the difference. It wasn't that I was naturally smarter - it was that I treated mathematics as a communication tool, not just a problem-solving exercise.

Every equation I wrote, every step I took, every variable I chose was designed to be crystal clear to anyone reading my work. This habit of clarity didn't just make me excel in math - it completely transformed how I write code.

The intention of this article is to show you how mathematical thinking can revolutionize your approach to naming in code, making your programs as clear and logical as a well-structured proof.

Let's get cooking,

Mathematics Taught Me That Naming Is Everything

In mathematics, you don't just solve problems - you communicate your reasoning. When I was working through complex calculus problems or statistical proofs, I learned that good mathematical writing follows specific principles:

In Math:

Let x = monthly subscription revenue
Let n = number of active subscribers  
Let r = average retention rate

Monthly growth = x × n × r

In Code:

const monthlySubscriptionRevenue = calculateMonthlyRevenue();
const numberOfActiveSubscribers = getActiveSubscriberCount();
const averageRetentionRate = calculateRetentionRate();

const monthlyGrowth = monthlySubscriptionRevenue * numberOfActiveSubscribers * averageRetentionRate;

Notice how both versions immediately tell you what each element represents. This isn't coincidence - it's communication.

The Six Principles That Made Me Shine in Math (And Code)

1. Proper Stepping - One Concept Per Line

In Math: I never crammed multiple operations into one complex equation. Each step built logically on the previous one.

Bad Math:

y = (x² + 2x + 1)/(x + 1) simplified directly to y = x + 1

Good Math:

Let f(x) = (x² + 2x + 1)/(x + 1)
Step 1: Factor numerator: x² + 2x + 1 = (x + 1)²  
Step 2: Substitute: f(x) = (x + 1)²/(x + 1)
Step 3: Simplify: f(x) = x + 1

In Code:

// Bad - everything crammed into one line
const result = users.filter(u => u.active && u.subscriptionType === 'premium').map(u => ({ ...u, revenue: u.monthlyFee * 12 })).reduce((sum, u) => sum + u.revenue, 0);

// Good - clear steps
const activeUsers = users.filter(user => user.active);
const premiumUsers = activeUsers.filter(user => user.subscriptionType === 'premium');
const usersWithAnnualRevenue = premiumUsers.map(user => ({
  ...user,
  annualRevenue: user.monthlyFee * 12
}));
const totalAnnualRevenue = usersWithAnnualRevenue.reduce((sum, user) => sum + user.annualRevenue, 0);

2. Clear Boundaries - Functions Do One Thing

In Math: Each theorem, lemma, or proof had a single, well-defined purpose.

In Code: Each function should have a single responsibility that's clear from its name.

// Bad - unclear what this function does
function processUser(user) {
  const isValid = user.email && user.name;
  if (isValid) {
    user.createdAt = new Date();
    sendWelcomeEmail(user);
    updateUserStats();
  }
  return isValid;
}

// Good - clear, single-purpose functions  
function validateUserData(user) {
  return user.email && user.name;
}

function createNewUser(userData) {
  const user = {
    ...userData,
    createdAt: new Date()
  };
  return user;
}

function onboardNewUser(user) {
  sendWelcomeEmail(user);
  updateUserStats();
}

3. Single Responsibility Clear from Naming

In Math: Variable names immediately told you their role: θ for angles, Δ for change, Σ for summation.

In Code: Your function and variable names should instantly communicate their purpose.

// Bad naming - unclear purpose
function calc(data) {
  let result = 0;
  for (let item of data) {
    result += item.val * 0.1;
  }
  return result;
}

// Good naming - crystal clear purpose
function calculateTotalCommission(salesTransactions) {
  let totalCommission = 0;
  for (let transaction of salesTransactions) {
    totalCommission += transaction.amount * COMMISSION_RATE;
  }
  return totalCommission;
}

// Even better - constants with clear names
const COMMISSION_RATE = 0.1;

function calculateTotalCommission(salesTransactions) {
  return salesTransactions.reduce((total, transaction) => {
    return total + (transaction.amount * COMMISSION_RATE);
  }, 0);
}

4. Top-Down Reading Support

In Math: I structured proofs so you could read from top to bottom and follow the logical flow.

In Code: Code should read like a story from top to bottom.

// Good - reads like a story
function processUserRegistration(userData) {
  const validatedUser = validateUserData(userData);
  const hashedPassword = hashPassword(validatedUser.password);
  const newUser = createUserAccount(validatedUser, hashedPassword);
  const welcomeEmail = sendWelcomeEmail(newUser);
  const userSession = createUserSession(newUser);

  return userSession;
}

// Supporting functions defined below - details hidden
function validateUserData(userData) { /* implementation */ }
function hashPassword(password) { /* implementation */ }  
function createUserAccount(userData, hashedPassword) { /* implementation */ }

5. No Overloading on One Line

In Math: I never tried to show off by cramming complex derivations into single lines.

In Code: Clarity beats cleverness every time.

// Bad - too much happening in one line
const result = data?.users?.filter(u => u.active)?.map(u => ({ ...u, score: calculateScore(u) }))?.sort((a, b) => b.score - a.score)?.[0] || null;

// Good - each step is clear
const users = data?.users || [];
const activeUsers = users.filter(user => user.active);
const usersWithScores = activeUsers.map(user => ({
  ...user,
  score: calculateScore(user)
}));
const sortedUsers = usersWithScores.sort((a, b) => b.score - a.score);
const topUser = sortedUsers[0] || null;

6. Clear Step-by-Step (With Comments)

In Math: I documented my reasoning at each step, especially for complex proofs.

In Code: Comments explain the "why," not the "what."

function calculateDynamicPricing(basePrice, demand, seasonality, inventory) {
  // Start with base price as foundation
  let adjustedPrice = basePrice;

  // Apply demand multiplier (high demand = higher price)
  const demandMultiplier = Math.min(demand / 100, 2.0); // Cap at 2x base price
  adjustedPrice *= demandMultiplier;

  // Apply seasonal adjustment (holidays, events, etc.)
  adjustedPrice *= seasonality;

  // Apply inventory pressure (low stock = premium pricing)
  if (inventory < 10) {
    adjustedPrice *= 1.2; // 20% premium for low stock
  }

  // Ensure we stay within reasonable bounds
  const maxPrice = basePrice * 3;
  const minPrice = basePrice * 0.5;

  return Math.max(minPrice, Math.min(maxPrice, adjustedPrice));
}

My Naming Conventions

Based on my mathematical background, here are the naming patterns I follow:

Variables

// Use full descriptive names
const userMonthlySubscriptionFee = 29.99;  // Not: fee, price, cost
const totalActiveSubscribers = 1247;       // Not: users, count, total

// Boolean variables start with is/has/can/should
const isUserActive = checkUserStatus(user);
const hasValidSubscription = validateSubscription(user.subscription);
const canUserAccessFeature = checkFeatureAccess(user, 'advanced_analytics');

Functions

// Functions are actions - use verbs
function calculateMonthlyRevenue() { }    // Not: monthlyRevenue()
function validateUserEmail() { }          // Not: userEmail()
function sendWelcomeEmail() { }           // Not: welcomeEmail()

// Be specific about what they return
function getUserById(id) { }              // Returns a user
function findActiveUsers() { }            // Returns array of users  
function countTotalSubscribers() { }      // Returns a number

Constants

// Use UPPER_SNAKE_CASE for constants
const MAX_LOGIN_ATTEMPTS = 3;
const DEFAULT_TIMEOUT_DURATION = 5000;
const API_BASE_URL = 'https://api.example.com';

The Communication Test

Before finalizing any name, I ask myself the same question I used to ask about my mathematical proofs:

"If someone else reads this in 6 months, will they immediately understand what this represents and what it does?"

If the answer is no, I rename it.

Real-World Example: Before and After

Before (Cryptic Math-Style Code):

function calc(u, p, d) {
  let r = p;
  if (u.t === 'premium') r *= 0.8;
  if (d > 365) r *= 0.9;
  return r;
}

After (Clear Mathematical Communication):

function calculateSubscriptionPrice(user, basePrice, daysSinceSignup) {
  let finalPrice = basePrice;

  // Premium users get 20% discount
  if (user.subscriptionType === 'premium') {
    finalPrice *= PREMIUM_DISCOUNT_RATE; // 0.8
  }

  // Loyalty discount for users over 1 year
  if (daysSinceSignup > DAYS_IN_YEAR) {
    finalPrice *= LOYALTY_DISCOUNT_RATE; // 0.9
  }

  return finalPrice;
}

The second version reads like a mathematical proof - each step is clear, each variable has meaning, and the logic flows naturally.

The Compound Effect

Just like in mathematics, where clear notation makes complex proofs manageable, good naming in code creates a compound effect:

  • Debugging becomes easier - you can trace logic by reading names

  • Code reviews are faster - reviewers understand intent immediately

  • Onboarding is smoother - new team members can contribute quickly

  • Maintenance is simpler - future changes are less risky

Wrapping Up

Mathematics taught me that clarity isn't just nice to have - it's essential for communication. The same principles that made me excel in math make code readable and maintainable.

Your variable names, function names, and overall code structure should tell a story as clearly as a well-written mathematical proof. When someone reads your code, they should be able to follow your reasoning step by step, just like following a logical mathematical argument.

Key takeaways:

  • Name things descriptively - no abbreviations or cryptic shortcuts

  • One concept per line - don't cram complex operations together

  • Single responsibility - functions and variables should have clear, focused purposes

  • Top-down readability - structure code so it reads like a story

  • Document the why - comments explain reasoning, not mechanics

The next time you're naming a variable or function, think like a mathematician writing a proof. Will someone else be able to follow your reasoning? Will they understand what each element represents?

Remember: Great code isn't about showing how clever you are. It's about communicating your ideas so clearly that others can build upon them.

A new day, another opportunity to write mathematically beautiful code! 🚀

0
Subscribe to my newsletter

Read articles from Oluwaferanmi Adeniji directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Oluwaferanmi Adeniji
Oluwaferanmi Adeniji