Extract Variable
Intent
Section titled “Intent”Take a piece of a larger expression, assign it to a well-named local variable, and use that name in place of the original sub-expression. Also known as Introduce Explaining Variable.
The smell
Section titled “The smell”This cures the cryptic one-liner — an expression so dense you have to mentally parse it every time you read it. A boolean condition stitched together from three comparisons, or a price formula with magic arithmetic, hides its meaning inside punctuation. Naming each part turns the line into something you can read aloud.
Before → After
Section titled “Before → After”A shipping check buries its meaning in one boolean expression. Naming the parts reveals the rules.
// Beforefunction isEligibleForFreeShipping(order: Order): boolean { return order.total > 50 && order.country === 'TH' && !order.isGift;}
// Afterfunction isEligibleForFreeShipping(order: Order): boolean { const overThreshold = order.total > 50; const domestic = order.country === 'TH'; const giftExcluded = !order.isGift; return overThreshold && domestic && giftExcluded;}# Beforedef is_eligible_for_free_shipping(order): return order.total > 50 and order.country == "TH" and not order.is_gift
# Afterdef is_eligible_for_free_shipping(order): over_threshold = order.total > 50 domestic = order.country == "TH" gift_excluded = not order.is_gift return over_threshold and domestic and gift_excluded// Beforefunc IsEligibleForFreeShipping(order Order) bool { return order.Total > 50 && order.Country == "TH" && !order.IsGift}
// Afterfunc IsEligibleForFreeShipping(order Order) bool { overThreshold := order.Total > 50 domestic := order.Country == "TH" giftExcluded := !order.IsGift return overThreshold && domestic && giftExcluded}// Beforefn is_eligible_for_free_shipping(order: &Order) -> bool { order.total > 50.0 && order.country == "TH" && !order.is_gift}
// Afterfn is_eligible_for_free_shipping(order: &Order) -> bool { let over_threshold = order.total > 50.0; let domestic = order.country == "TH"; let gift_excluded = !order.is_gift; over_threshold && domestic && gift_excluded}Mechanics
Section titled “Mechanics”- Check the sub-expression has no side effects — extracting one that mutates state can change behaviour.
- Declare an immutable local variable and assign the sub-expression to it.
- Give the variable a name that states what the value means, not how it is computed.
- Replace the original sub-expression with the new variable.
- Run your tests.
- If the same sub-expression appears more than once in scope, replace each occurrence and test again.
When to use / trade-offs
Section titled “When to use / trade-offs”Use it for debugging (a named local is easy to inspect), for breaking a long formula into reviewable pieces, and to make a condition self-documenting. Within a single function a local is enough; when the same explanation is useful across the whole object, prefer Replace Temp with Query or extracting a method instead.
The inverse is Inline Variable: when a variable’s name adds nothing over the expression it holds, substitute the expression back and drop the variable.