Skip to content
FollowtheDamnCode

Refactoring: Composing Methods

Extract, inline, and name — the moves that turn long functions into short ones that read like their own documentation.

Big idea

Most refactoring happens inside functions. Composing methods means pulling meaningful chunks out into well-named functions (and occasionally folding pointless ones back in), so each function does one thing at one level of detail and its name tells you what that thing is.

The techniques

TechniqueMoveWhen
Extract MethodTurn a fragment into a function named for what it doesA block needs a comment to explain it; a function is too long
Inline MethodReplace calls with the body, delete the functionThe body is as clear as the name; too much indirection
Extract VariableName a sub-expressionA complex condition or formula
Inline TempReplace a variable with its expressionThe variable adds nothing and blocks other refactorings
Replace Temp with QueryMove a computed temp into a methodThe value is needed in several methods
Split Temporary VariableOne variable per meaningA variable is reassigned for different purposes
Remove Assignments to ParametersUse a local insteadReassigning a parameter confuses readers
Substitute AlgorithmReplace the body with a clearer algorithmA simpler way exists (tests first!)

Think of it like

Editing a long, rambling paragraph into a list of headed sections. The words barely change; you add headings (function names), split where the topic changes, and delete headings that just repeat their only sentence. Suddenly a reader can skim.

Before and after

Extract Method: one long function becomes a short story
Extract Method and Extract Variable, behaviour unchanged
def statement_before(customer, rentals):
    out = f"Rentals for {customer}\n"
    total, points = 0, 0
    for title, days, kind in rentals:
        amount = 2 + max(0, days - 2) * 1.5 if kind == "regular" else days * 3
        points += 2 if kind == "new" and days > 1 else 1
        out += f"  {title:10} {amount:5.1f}\n"
        total += amount
    out += f"Owed {total:.1f}, earned {points} points"
    return out


# --- after: same output, each piece named ---
def charge(days, kind):
    return 2 + max(0, days - 2) * 1.5 if kind == "regular" else days * 3

def points_for(days, kind):
    is_new_long_rental = kind == "new" and days > 1          # Extract Variable
    return 2 if is_new_long_rental else 1

def statement(customer, rentals):
    lines = [f"  {title:10} {charge(d, k):5.1f}" for title, d, k in rentals]
    total = sum(charge(d, k) for _, d, k in rentals)         # Replace Temp with Query
    points = sum(points_for(d, k) for _, d, k in rentals)
    return "\n".join([f"Rentals for {customer}", *lines, f"Owed {total:.1f}, earned {points} points"])


rentals = [("Dune", 3, "regular"), ("Arrival", 2, "new"), ("Up", 1, "kids")]
print(statement(customer="Ana", rentals=rentals))
print("same as before:", statement("Ana", rentals) == statement_before("Ana", rentals))
output
Rentals for Ana
  Dune         3.5
  Arrival      6.0
  Up           3.0
Owed 12.5, earned 4 points
same as before: True

Run and edit it in the app.

When extracting a method, what should its name describe?

Watch it

Hands on

A temporary variable is reused for two meanings, and a later edit reads the wrong one. Split the temp (one name per meaning) so the output is correct.

Fix it: one variable, two meanings
def box_report(w, h, d):
    temp = 2 * (w * h + w * d + h * d)      # surface area
    print(f"surface area: {temp}")
    temp = w * h * d                        # volume
    print(f"volume: {temp}")
    print(f"paint needed: {temp / 10:.1f} litres")   # meant: surface area

box_report(2, 3, 4)
output
surface area: 52
volume: 24
paint needed: 5.2 litres

Run and edit it in the app.

When is Inline Method the right move?

How it relates

Key terms

  • Extract Method — Moving a code fragment into its own named function.
  • Inline Method — Replacing calls to a function with its body when the function adds nothing.
  • Extract Variable — Naming a sub-expression to make its meaning clear.
  • Split Temporary Variable — Giving each meaning of a reused variable its own name.