Recently I did read the following short piece from M. Fowler regarding the use of boolean flags in function signatures. I’ll wait while you read it… done? Good!
As a general rule, I completely agree with him. They can be confusing, and should, in general, be avoided (easier said than done). But the article got me to reflect on this advice in the context of Python.
The example shown in the article would translate to Python (with type annotations and following PEP8) as follows
class Concert:def book(self, customer: Customer, is_premium: bool): ...
This definition does indeed has all the downsides mentioned in the article. But what if we use the
keyword argument-only feature of Python?
class Concert:def book(self, customer: Customer, *, is_premium: bool = False): ...
In this case, by adding the
* in the signature, one is forced to mention the name of the argument when calling the function. Thus, a call like the following one
a_book = concert.book(customer, True)
will raise a
TypeError exception. Then, the correct way to call the function would be
a_book = concert.book(customer, is_premium=True)
There is no ambiguity as to what the flag points to, completely transparent and explicit.
However, since in most cases a boolean flag implies some branching in the code of the function, this approach still has some downsides that could be avoided by getting rid of such boolean flag.
Ultimately, it’s a matter of judgment as with everything. If the function has basically one of such flags that have a very restricted function, it’s still manageable.