Separate Query from Modifier
Functions should either do something or return something, not both.
“A method returns a value but also changes the state of an object.”
CQS (Command Query Separation).
graph LR
A[func(): result + sideEffect] -->|Refactoring| B[query(): result]
A --> C[command(): sideEffect]
When to apply (Smells)
- Unexpected Side Effects: Calling
getTotal()also prints an email.
Motivation
- Predictability: Queries should be safe to call multiple times (idempotent).
- Separation of Concerns: Calculating vs Acting.
Mechanics (Steps)
- Create a query method that returns the value (without side effects).
- Create a command method that performs the side effect.
- Replace calls to the original method with calls to the command then the query (or vice versa).
Explanation
Problem
checkSecurity(people) returns “Found” AND sends an alert.
Solution
found = isFound(people) (Query)
sendAlert() (Command)
Pros and Cons
| Pros | Cons |
|---|---|
Code example
Typescript
Before
After
PHP
Before
After