3

In many languages, the convention for naming Booleans is typically to prefix them with "is", "has" or "can". This convention seems to be applied mostly to fields and methods (e.g. Java's Scanner.hasNextInt()). Is there a convention for naming a method's Boolean arguments? I don't see the same convention being applied to them; for example, Java has String.regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len).

6
  • 2
    I personally stick with the "boolean" prefixes since the alternative usually violates the naming convention for variables which should start with a noun whereas your example starts with a verb which is reserved for methods... Jul 1, 2022 at 9:16
  • 2
    On the other hand boolean parameters are a violation of the Tell, don't ask Pattern as well as the Replace branching with Inheritance pattern. Instead of the boolean parameter we should pass an object providing one of the alternative behaviors. Jul 1, 2022 at 9:21
  • "matches" is grammatically boolean. you dont need to expand it to IsAMatchFor() or something
    – Ewan
    Jul 1, 2022 at 11:50
  • @Ewan I was talking about the boolean variable "ignoreCase", not "matches", but thanks anyway.
    – k314159
    Jul 1, 2022 at 11:59
  • I'm less concerned about boolean parameter naming than I am about how you are ignoring the naming of the non-boolean parameters in the regionMatches example. WTF is "other" meant to convey?
    – Peter M
    Jul 6, 2022 at 18:48

2 Answers 2

13

The typical is/has/can prefixes make sense grammatically in the context of an object. Given an object x, we can say that “x is something”, that “x has something”, or that “x can do something”. Having such a naming convention also distinguishes attributes from actions, e.g. the property/attribute “x is empty” versus the command “empty x”.

This doesn't generalize to function arguments where there may not be such context, and where we do not have to distinguish actions from attributes.

At least in Java, this doesn't matter too much: the name of the function argument happens to be included in documentation for that method (and maybe in IDE-provided annotations), but really it's just the name of a local variable within the function. The name is not part of the public API of that function, unlike in languages that offer named arguments such as Kotlin or C#. So while clear names for function arguments are helpful, this isn't really that important.

Whatever naming convention you use for boolean arguments, it's likely possible to find some argument that this convention is reasonable. None of the following is really problematic:

  • String#match(needle, ignoreCase) (where the boolean describes a command as part of the match)
  • String#match(needle, isCaseSensitive) (where the boolean describes an attribute of the match)
  • String#match(needle, withCase)
  • String#match(needle, caseSensitively) (where the boolean is an adverb – makes sense grammatically but I have never seen this in practice)

The real issue with boolean arguments is not their name, but that without named arguments their meaning is not obvious at the call site – what would "foo".match("F", true) mean? Solutions with different tradeoffs include:

  • turning the boolean argument into part of the function name, e.g. String#match(needle) vs String#matchIgnoreCase(needle).
    Pro: simple.
    Con: bloats API surface, exponential explosion of alternatives if there are multiple booleans, difficult to select alternatives programmatically.

  • using an enum instead of a boolean, e.g. "foo".match("F", Case.IGNORE).
    Pro: makes call-site more self-documenting, easy to select alternatives programmatically.
    Con: enums add to API surface, potentially very verbose.

  • using polymorphism instead of conditionals. The boolean argument will likely select between different behaviours. That could also be achieved by injecting different strategies. Here, the match function would need a strategy to determine if two characters or strings are equivalent. For such a string matching function, this would allow substantial flexibility, for example by providing strategies that do not perform normalization, strategies that ignore ASCII-case, strategies that do full Unicode case-insensitive matching, or even strategies that perform Unicode normalization before comparison.
    Pro: extremely flexible and extensible.
    Con: larger API surface, potential performance impact through extra level of indirection.

  • use a builder object, probably with a fluent API, to configure an action before performing it, though this is mostly just a hack around the absence of named arguments. For example:

    "foo".match("F")
         .withIgnoreCase(true)
         .execute()
    

    Pro: extremely flexible and easy to read.
    Con: fairly verbose, bloats the API surface with a method builder, takes a lot of effort to implement, easy to forget final execute().

1
  • In languages where the caller supplies argument names, bool parameters are fine. In languages where the call doesn’t include parameter names, it’s fatal. Imagine a function argument that could be “caseIgnored” or “caseSensitive”. Worse if you have three bool arguments and call f(true, false, true)
    – gnasher729
    Jul 2, 2022 at 15:14
7

It is really simple.

  • A field/property represents a state.
  • A method argument is a command.

This has implications for the language used. For a property it would be IsCaseIgnored, which describes a state. For a method argument it would be ignoreCase, which tells the code what to do.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.