DEV Community

Timevolt
Timevolt

Posted on

The One Habit That Made My Code Actually Readable

The One Habit That Made My Code Actually Readable

Quick context (why you're writing this)

Here's the thing: I once spent three straight days trying to figure out why a quarterly‑sales report was showing numbers that were off by exactly 0.02 % for a handful of customers. The bug wasn’t some obscure race condition; it lived in a single 120‑line function that decided whether a discount should be applied, whether tax should be recalculated, and whether a loyalty bonus kicked in—all tangled together with hard‑coded thresholds and a few magic numbers that looked like they’d been copy‑pasted from a spec sheet five years ago.

I stared at that function until my eyes glazed over, added a bunch of console.logs that only made the output harder to follow, and eventually realized I was solving the wrong problem. The real issue wasn’t the math; it was that I couldn’t see what the code was trying to say.

That experience hammered home a habit that changed the way I write code forever: extract every non‑trivial conditional into a clearly named function (or early return) and let the main flow read like a sentence.

The Insight

When a conditional is more than a simple null check, it’s usually hiding a piece of business logic that deserves its own name. By pulling that logic out, you get three immediate wins:

  1. Readability drops – anyone (including future you) can glance at the top‑level function and understand the story without mentally parsing nested booleans.
  2. Testability skyrockets – each extracted predicate becomes a pure function you can unit‑test in isolation, edge cases and all.
  3. Bugs become obvious – when a condition is buried deep inside a monolith, a tiny typo can slip through review; when it’s a standalone function named isEligibleForHolidayDiscount, the intent is explicit and a wrong return value jumps out.

The trade‑off? You end up with a few more functions, but they’re tiny, focused, and usually cheaper to maintain than the cognitive load of a monster conditional.

How (with code)

Below is a simplified version of the report‑generation function I wrestled with. It’s written in JavaScript/Node.js, but the idea translates to any language.

Before – the “wall of conditionals”

function calculateFinalPrice(order) {
  let price = order.subtotal;

  // discount logic
  if (
    order.customer.type === 'premium' &&
    order.subtotal >= 100 &&
    order.items.some(i => i.category === 'electronics')
  ) {
    price *= 0.9; // 10% off
  }

  // tax logic – different for EU vs non‑EU
  if (order.shippingCountry.code === 'DE' || order.shippingCountry.code === 'FR') {
    price *= 1.19; // German/VAT
  } else if (
    order.shippingCountry.code === 'GB' ||
    order.shippingCountry.code === 'IE'
  ) {
    price *= 1.20; // UK VAT
  } else {
    price *= 1.0; // no tax
  }

  // loyalty bonus
  if (
    order.customer.points >= 500 &&
    order.subtotal >= 200 &&
    order.date.getMonth() === 11 // December
  ) {
    price -= 25; // flat $25 off
  }

  // shipping fee waiver
  if (order.subtotal >= 150 && order.customer.type !== 'new') {
    price += 0; // free shipping, just keep price
  } else {
    price += 12; // standard shipping
  }

  return Math.round(price * 100) / 100; // cents precision
}
Enter fullscreen mode Exit fullscreen mode

What’s happening here?

  • Three separate concerns (discount, tax, loyalty) are glued together.
  • Magic numbers (100, 0.9, 1.19, 500, 200, 12) are scattered.
  • The if chains are long enough that you lose track of which branch modifies price and which just reads it.

I spent hours stepping through this with a debugger, only to discover that the loyalty bonus wasn’t firing for a corner case where order.date.getMonth() returned 0 (January) because the original spec had been mis‑copied. The bug was a simple off‑by‑one, but it hid in the noise.

After – extracting intent

function calculateFinalPrice(order) {
  let price = order.subtotal;

  if (applyPremiumDiscount(order)) {
    price *= 0.9;
  }

  price *= applyTaxRate(order);

  if (applyLoyaltyBonus(order)) {
    price -= 25;
  }

  price += calculateShippingFee(order);

  return roundToCents(price);
}

/* ----- extracted predicates ----- */
function applyPremiumDiscount(order) {
  return (
    order.customer.type === 'premium' &&
    order.subtotal >= 100 &&
    hasElectronicsItem(order)
  );
}

function hasElectronicsItem(order) {
  return order.items.some(item => item.category === 'electronics');
}

function applyTaxRate(order) {
  switch (order.shippingCountry.code) {
    case 'DE':
    case 'FR':
      return 1.19;
    case 'GB':
    case 'IE':
      return 1.20;
    default:
      return 1.0;
  }
}

function applyLoyaltyBonus(order) {
  return (
    order.customer.points >= 500 &&
    order.subtotal >= 200 &&
    isDecember(order.date)
  );
}

function isDecember(date) {
  return date.getMonth() === 11; // 0‑based
}

function calculateShippingFee(order) {
  return order.subtotal >= 150 && order.customer.type !== 'new' ? 0 : 12;
}

function roundToCents(value) {
  return Math.round(value * 100) / 100;
}
Enter fullscreen mode Exit fullscreen mode

What changed?

  • The top‑level function now reads like a checklist: “apply discount, apply tax, apply bonus, add shipping, round.”
  • Each helper does one thing and has a name that states the business rule outright.
  • The magic numbers live next to the rule they belong to, making it obvious when a threshold needs tweaking.
  • Unit‑testing applyLoyaltyBonus is trivial: feed it a mock order and assert true/false for the three sub‑conditions.

If I had written the after‑version first, that pesky loyalty bug would have been caught in a five‑second test instead of three days of staring at a screen.

Why This Matters

When you bury decisions inside a wall of ifs, you force every reader to reconstruct the business story in their head. That mental effort is where bugs hide: a misplaced &&, a forgotten edge case, a stale constant that nobody notices because it’s hidden three levels deep.

By giving each decision a name, you turn code into documentation that the compiler can verify. You also create seams where you can safely insert logging, metrics, or feature flags without disturbing the core flow.

Sure, you end up with more functions, but they’re tiny, focused, and often reusable elsewhere (I’ve found myself calling hasElectronicsItem in a completely different module months later). The upfront cost of extracting a few lines is paid back many times over in reduced debugging time and higher confidence during refactors.

Wrap‑up

Try this on the next function you touch that makes you pause and think, “What does this actually do?” Pull out the first conditional that does more than a null check, give it a verb‑or‑question‑style name (isEligibleFor…, shouldApply…), and watch how the rest of the function suddenly feels lighter.

Your turn: Look at a recent piece of code you’ve written or reviewed. Identify one conditional that could be lifted out. What would you name it? How does the surrounding code read after the extraction? Drop your thoughts in the comments—I’m curious to see where you’ve applied this habit.

Top comments (0)