Replace Temp with Query
Intent
Section titled “Intent”Take a local variable that is assigned the result of a calculation and then only read, and replace it with a function (a “query”) that performs the calculation. Every place that used the temp now calls the query.
The smell
Section titled “The smell”This cures temps that pin logic in place. A temporary variable couples a calculation to one function: you cannot reuse the result elsewhere, and you cannot Extract Function around code that depends on it without dragging the temp along as a parameter. Turning the temp into a query frees the calculation. It is most valuable as a preparation step — once the value is a method, larger extractions fall out cleanly.
Before → After
Section titled “Before → After”basePrice is a temp computed once and read twice. Promote it to a query method on the order.
// Beforeclass Order { constructor(private quantity: number, private itemPrice: number) {}
finalPrice(): number { const basePrice = this.quantity * this.itemPrice; const discount = Math.max(this.quantity - 100, 0) * this.itemPrice * 0.1; return basePrice - discount; }}
// Afterclass Order { constructor(private quantity: number, private itemPrice: number) {}
private basePrice(): number { return this.quantity * this.itemPrice; }
private discount(): number { return Math.max(this.quantity - 100, 0) * this.itemPrice * 0.1; }
finalPrice(): number { return this.basePrice() - this.discount(); }}# Beforeclass Order: def __init__(self, quantity, item_price): self.quantity = quantity self.item_price = item_price
def final_price(self): base_price = self.quantity * self.item_price discount = max(self.quantity - 100, 0) * self.item_price * 0.1 return base_price - discount
# Afterclass Order: def __init__(self, quantity, item_price): self.quantity = quantity self.item_price = item_price
def base_price(self): return self.quantity * self.item_price
def discount(self): return max(self.quantity - 100, 0) * self.item_price * 0.1
def final_price(self): return self.base_price() - self.discount()// Beforetype Order struct { Quantity int ItemPrice float64}
func (o Order) FinalPrice() float64 { basePrice := float64(o.Quantity) * o.ItemPrice discount := math.Max(float64(o.Quantity-100), 0) * o.ItemPrice * 0.1 return basePrice - discount}
// Aftertype Order struct { Quantity int ItemPrice float64}
func (o Order) basePrice() float64 { return float64(o.Quantity) * o.ItemPrice}
func (o Order) discount() float64 { return math.Max(float64(o.Quantity-100), 0) * o.ItemPrice * 0.1}
func (o Order) FinalPrice() float64 { return o.basePrice() - o.discount()}// Beforestruct Order { quantity: i32, item_price: f64,}
impl Order { fn final_price(&self) -> f64 { let base_price = self.quantity as f64 * self.item_price; let discount = (self.quantity - 100).max(0) as f64 * self.item_price * 0.1; base_price - discount }}
// Afterstruct Order { quantity: i32, item_price: f64,}
impl Order { fn base_price(&self) -> f64 { self.quantity as f64 * self.item_price }
fn discount(&self) -> f64 { (self.quantity - 100).max(0) as f64 * self.item_price * 0.1 }
fn final_price(&self) -> f64 { self.base_price() - self.discount() }}Mechanics
Section titled “Mechanics”- Check the temp is assigned exactly once and is never mutated after assignment. If it is reassigned, split it first so each value is determined in one place.
- Confirm the right-hand-side calculation has no side effects.
- Extract the calculation into a query function (a method when the data lives on an object).
- Replace each read of the temp with a call to the query.
- Run your tests after each replacement.
- Remove the now-unused temp declaration.
When to use / trade-offs
Section titled “When to use / trade-offs”Use it when a temp blocks an Extract Function you want to do, when the same calculation would be useful from more than one method, or simply to shrink a long method’s local state. The main trade-off is repeated computation: a query may recalculate on every call. For typical business logic this is negligible, and the clarity is worth it; for a genuinely hot path, measure before deciding.
The opposite direction is caching the value back into a local when profiling proves the query is a real bottleneck — but reach for that only with evidence.