Avoid Passing Nulls and Booleans
In a Shelfwise pull request you find print_invoice(order, True, None). What does True do? What happens because of None? You cannot tell without opening the function, and neither can the next reader. A call should explain itself, and bare flags and nulls make that impossible.
The rule
A flag argument hides two functions; a null argument hides a missing case.
Boolean flags. A function that takes True or False to switch its behaviour is really two functions sharing one name:
def print_invoice(order, duplicate):
if duplicate:
... # stamp "COPY", skip the payment QR code
else:
... # normal invoiceEvery caller must remember what the boolean means, and the body carries both behaviours. Better options:
- Split it:
print_invoice(order)andprint_duplicate_invoice(order). - Name it at the call, when the flag really is a small option:
print_invoice(order, duplicate=True). Python's keyword-only parameters (declared after a*) can enforce this.
Nulls. Passing None to mean "use the default" or "not applicable" forces the function to check for it, and returning None for "not found" forces every caller to check too. Forget once, and the program crashes somewhere far from the real cause with a message like 'NoneType' object has no attribute 'email'. Better options:
- Make the argument required and pass the real value.
- Give it a sensible default in the signature.
- For "not found", raise a clear exception, or offer a separate question such as
customer_exists(email).
When None really is a normal answer, at least make it visible. A type hint such as def find_customer(email) -> Customer | None tells every reader, and tools like type checkers, that a check is required before use.
The shortcut
Cover the function definition and read only the call. If you cannot say what each argument does, the signature needs fixing.
Read the call alone
TrueandNonecarry no meaning on their own. The call fails the test.
The trap is adding "just one more" flag. send_email(customer, True, False, True) is what one harmless flag grows into.
Drills
Answer fast — trust the rule.
What is the main problem with send_email(customer, True, False)?
find_customer(email) returns None when nobody matches. What is the main risk?
Which call is the clearest?
ship(order, express) runs two unrelated code paths chosen by express. What is the best fix?
Remember
- A flag hides two functions; a null hides a missing case.
- Cover the definition and read the call; if an argument means nothing, fix the signature.
- Trap: "just one more" flag, until calls look like
True, False, True.
