Arguments and Side Effects Must Be Honest
What this concept is
Functions should be honest about what they need and what they change. Too many arguments often signal unclear responsibility. Hidden mutation makes the caller reason about surprises that are not visible in the name.
Why it matters here
Function cleanliness is not only about length. A short function that silently mutates shared state can be harder to trust than a longer pure function with obvious inputs and outputs.
Concrete example
def normalize(user, cache, logger, retries, strict):
...
This signature already raises questions. Why does normalization need logging, retries, and a cache? It may be doing several jobs.
Hidden side effect:
def calculate_total(cart):
cart.last_viewed_at = now()
...
The name promises a calculation but performs mutation too.
Common confusion / misconception
Commands are allowed to mutate, and queries are allowed to return values. The problem is not mutation itself. The problem is surprise. A function should not sound like a harmless query when it is also updating state.
How to use it
Look for:
- long parameter lists
- boolean flags that switch behavior
- out parameters or mutation of shared objects
- functions that both answer a question and perform an action
Refactor with:
- smaller responsibility boundaries
- richer domain objects where appropriate
- separate command and query paths
- better names that reveal mutation
Check yourself
Why is a boolean flag in a function signature often a design smell?
Mini drill or application
Find one function with four or more parameters or one boolean flag. Rewrite the API so the function either becomes more focused or the behavior split becomes explicit.