Stop Naming Your Variables "Flag": The Art of Boolean Prefixes (2025)

mooreds1 pts0 comments

Stop Naming Your Variables "Flag": The Art of Boolean Prefixes | Christopher Johnson before<br>the browser paints. Runs synchronously, no defer/async.<br>--><br>Skip to content<br>Go back<br>Stop Naming Your Variables "Flag": The Art of Boolean Prefixes<br>7 Dec, 2025

Table of Contents

The Problem

You inherit a codebase and find this:

public class OrderProcessor<br>private bool open;<br>private bool flag;<br>private bool done;<br>private bool status;

public void Process(bool check)<br>if (open && flag)<br>flag = false;<br>status = true;

if (done)<br>// what happens here?<br>Readable? No.

What is open? Is the store open? Should the file open? What is flag? That’s a variable screaming “I’ll fix this later.” And is done a question (“is it done?”) or a command (“mark it done”)?

Boolean names are ambiguous land mines. They look innocent until you have to figure out what they mean during a 3 AM outage.

Ambiguity breeds bugs. A reviewer looks at if (done) and guesses the intent. A maintainer rewrites flag = false and accidentally inverts logic they didn’t understand. if (!flag)… does that mean turn it on? Turn it off?

Boolean names matter because they aren’t abstract labels; they are questions . Your code asks the question, and the boolean value answers “yes” or “no.” If the variable name isn’t a clear question, the answer is meaningless.

The Solution: The 4 Prefixes

You can cover 99% of boolean naming scenarios with just four prefixes. If you stick to these, every boolean becomes a clear, grammatical question.

1. IS: Identity and State<br>Use is when describing what something is right now. It usually pairs with an adjective.

Good: isActive, isDeleted, isEmpty.

Bad: isAccess (Grammar mismatch. Use hasAccess).

2. HAS: Containment and Features<br>Use has when describing ownership or inclusion. It pairs with a noun.

Good: hasAccess, hasChildren, hasValidationErrors.

Bad: hasActive (Grammar mismatch. Use isActive).

3. CAN: Capability<br>Use can to check permissions or potential actions.

Good: canEdit, canDelete, canRetry.

Bad: canAdmin (Vague. Use isAdmin or canAdminister).

4. SHOULD: Intent<br>Use should for business rules or decisions the system needs to make. This separates “what we can do” from “what we want to do.”

Good: shouldRetry, shouldCacheResponse.

Bad: shouldUser (Incomplete. shouldCreateUser?).

Stick to this list. When you mix them up—like writing isAccess or hasActive—you force the reader to stop and re-parse the sentence in their head. That friction is where bugs get introduced.

PrefixDomainFunctionExampleISIdentity / StateDescribes what an object is currently.isActive, isEmptyHASContainmentDescribes ownership or feature presence.hasChildren, hasAccessCANCapabilityDescribes permission or potential action.canEdit, canRetrySHOULDIntent / LogicDescribes a business rule recommendation.shouldCache, shouldRetry<br>The “No Negatives” Rule

Here is the most important rule: Never use negation in the variable name.

Avoid names like isNotEnabled, hasNoAccess, or isDisabled.

Why? Because eventually, you will need to check for the opposite state.<br>if (!isDisabled) forces your brain to calculate a double negative: “If not is disabled…”

Compare that to:<br>if (isEnabled)

Immediate clarity.

Negative names feel natural when you write them (“I need to check if this is disabled”), but they are a tax on every person who reads the code later. Refactoring tools make this worse; if you invert an if statement, your IDE might helpfully rename isDisabled to isNotDisabled. Now you have code that is actively hostile to human readers.

The Exception:<br>The only time a negative name is acceptable is when you are mirroring an external API or HTML attribute that is negative by default, like noValidate. Even then, isolate it at the boundary. In your domain logic, always map it to a positive: bool shouldValidate = !request.noValidate.

Context Matters (The “Boolean Trap”)

The rules above work perfectly for properties (state). They fall apart for parameters (function arguments).

This is the “Boolean Trap”:

// Real code from NHibernate<br>schemaExport.Execute(false, true, false);<br>Quick: What does the second true do? You have no idea. You have to open the library source code to find out.

If you see a method signature like Execute(bool, bool, bool), you are looking at a design bug.

How to fix it:

1. Split the method<br>If the boolean changes the method’s behavior entirely, make two methods.

// Bad<br>email.Send(message, true); // is true "immediate"? "high priority"?

// Good<br>email.SendImmediately(message);<br>email.SendQueued(message);<br>2. Use an Enum<br>If there are modes, name them.

// Bad<br>file.Write(data, true);

// Good<br>file.Write(data, WriteMode.Append);<br>3. Use a Config Object<br>If you have multiple flags, pass an object.

// Bad<br>export.Execute(false, true, false);

// Good<br>export.Execute(new ExportOptions {<br>Script = false,<br>Export = true,<br>JustDrop = false<br>});<br>The Antipatterns

If you want to clean up your code, watch out for these specific smells in code reviews.

1. The “Shrug”...

boolean flag bool false true code

Related Articles