All articles
Software Development2 min read

19. Always Affirmative

Negations burn brain cycles — every "not" forces the reader to flip the logic. Prefer affirmative names and conditions to make code faster to read and safer to change.

Delft-blue tile reading "Always Affirmative"

"Don't ever not avoid negative logic."

Sounds confusing? Exactly.

Negations burn brain cycles. Every "not" forces readers (yes, developers too 😉) to mentally flip the logic. Prefer affirmative names and conditions.

🔎 Example (original)

if (!this.isNotLoggedIn() && !isNotEmpty) {
  // ...
}

Do you parse that in one go? Probably not.

✅ Better (affirmative, readable)

const isLoggedIn = this.isAuthenticated();
const hasItems = items.length > 0;

if (isLoggedIn && hasItems) {
  // ...
}

Guidelines

1. Name what's true when the flag is true.

  • isNotLoggedIn → ✅ isLoggedIn
  • isNotEmpty → ✅ hasItems
  • noAccess → ✅ hasAccess / canAccess

2. Avoid double negatives.

!isNotReady → ✅ isReady

Use well-named intermediates when needed:

const hasAccess = user.roles.includes('admin');
const isReady = hasConfig && hasAccess;
if (!isReady) return;

3. Rename functions; invert their internals if needed.

function isNotLoggedIn() { return !token; }function isLoggedIn() { return Boolean(token); }

4. Pick positive words for intent.

canEdit, shouldRender, mustRedirect, hasPermission, isVisible.

5. Be pragmatic with domain language.

"invalid", "expired", "denied" are fine when they describe a state.

Avoid isNotValid → use isInvalid.

Mini refactor checklist

  • Avoid patterns like isNot*, hasNo*, without*.
  • Split long conditions into clearly named steps.
  • Use early returns to reduce nesting.
  • Add tests around the new affirmative naming.

ESLint hints (optional)

Discourage negated conditions:

// .eslintrc
{ "rules": { "no-negated-condition": "warn" } }

Flag names starting with isNot (TS):

{
  "rules": {
    "@typescript-eslint/naming-convention": [
      "warn",
      {
        "selector": "variableLike",
        "filter": { "regex": "^isNot[A-Z].*", "match": true },
        "format": null
      }
    ]
  }
}

✨ TL;DR

Naming is developer UX. Affirmative names make code faster to read, easier to review, and safer to change.

What's the last double negative you removed from your codebase? 👇

Related articles