Tag Archive for Bug Patterns

When Not-True Doesn’t Equal False

There is a strangely common, reoccurring bug I’ve seen return, again and again, in most projects I’ve worked on in recent years. I call it the “Not True != False” bug, and it crops up, usually, when passing query parameters to a search service of some sort, when you want to search for entities who match a certain condition, and you end up not being able not to search by that condition.

Confusing? Let’s back up for a second.

One of the more common patterns in use is having our client run a query on our server by creating an object describing the query parameters. Call it the QueryFilter or SearchParams or QueryDTO or whatever. This class will encapsulate the parameters we want to search on:

public class PersonQueryFilter
{
    public string Name {get; set;}
    public bool IsVIP {get; set;}
}

Here, a simple query class that allows us to send a search to the server, returning a list of Person objects that match the given name, or that have the VIP property set to true. Simple, right? This is the common, straightforward and naive occurence of this bug that I see again and again. The developer needed a way to fetch all VIPs, so they added a field to specify VIPs.

Why is this a bug? Because as it stands, this class does not allow us to not search by IsVIP. We can ask for Persons that are VIPs. We can ask for Persons that aren't VIPs. But we can't ask for Persons regardless of whether they're VIPs. A boolean is simply that, a boolean. It doesn't encode information beyond yes/no. All matching entities must have either True or False.

This is a pernicious bug, but it will probably survive initial testing if the developer doesn't write comprehensive unit tests. That's because it will seem to work. "Write a feature that finds VIPs. Did it find VIPs? Yes, it did. Good, it works".

The solution to it is, of course, very simple. The opposite of "Find where X is True" is, in this case, not "Find where X is False", but "Find where X is irrelevant". For searching by Name, we can simply specify null as a marker for "don't search by this parameter". For our booleans, C# gives us the Nullable<bool> type (or bool?) to specify a third option for bool. Yes/No/Irrelevant. Other languages have their own solutions. Javascript can specify undefined or null for any data type. In Java you would probably use the Boolean object instead of the boolean primitive for many other reasons anyway (like generics), which can be set to null.

There are many workarounds. But many developers, especially relatively inexperienced ones, don't always think of the nullability of their search parameters.

Which is why I run into this bug again. And again. And again.