Intuition The ONE core idea
Refactoring is rearranging the inside of a program so it reads better, while the outside behaviour stays byte-for-byte identical . Every idea on this page exists to answer one question: how do we improve code and still PROVE we changed nothing a user can see?
Before you can trust the parent note, you must own every word it silently assumes. Below is every symbol, term, and notation the topic uses — each with a plain meaning, a picture, and the reason the topic needs it. We build them in an order where each rests on the one before.
Definition Code / program / function
Code is a list of written instructions a computer follows top to bottom. A ==function == is a named box that takes some things in (inputs ), does steps, and hands something back (output ).
Picture a function as a machine with a slot on the left (inputs go in) and a chute on the right (output comes out).
Look at the figure: the teal box is the function. You do not see the gears inside — you only see what goes in and what comes out. That "only see in/out" idea is the whole game, so hold onto it.
The parent's central word is behaviour-preserving . You cannot understand what is preserved until you can point at the two things a function shows the world: its inputs and its output .
Definition Behaviour (external / observable)
Behaviour = the full mapping from every possible input to the output the outside world sees (printed text, returned values, files written). It is what the function does , not how.
Two functions have the same behaviour if, for every input you could feed them, they hand back the same output.
In the figure, two differently-built machines (different gears inside) produce the same output for the same input. To an outside observer they are indistinguishable. Refactoring turns the left machine into the right machine — gears rearranged, output untouched.
Common mistake "Behaviour" is not "the code"
Two different piles of code can share one behaviour (that's the whole point of refactoring). So B ( code 1 ) = B ( code 2 ) can be true even when code 1 = code 2 .
Definition Internal structure
Structure = how the code is organised inside : how it's split into functions, how variables are named, how logic is grouped. It is everything the outside observer cannot see.
Picture the gears inside the box in Figure 1. Rearranging gears = changing structure. If the chute output is unchanged, behaviour is preserved.
Intuition The two-column mental model
Every line of code lives in one of two columns:
Behaviour column (visible outputs) — refactoring must leave this frozen.
Structure column (names, splits, groupings) — refactoring is only allowed to touch this.
If your change reaches into the behaviour column, it is no longer refactoring — it's a feature or a bug fix.
We claimed behaviour must stay identical. But behaviour is invisible — you can't stare at gears and know the output is unchanged. We need a measuring instrument . That instrument is a test .
Definition Test / test suite
A ==test == is a small piece of code that runs the function with a chosen input and checks the output equals what we expect. A ==test suite == T is the whole collection of them.
In the figure, each test pokes the machine with one input and compares the chute's output to a known-good answer. Green = matched (PASS). Red = mismatch (FAIL).
Intuition Why tests, and not "just be careful"?
B checks every input — infinite, impossible to inspect by eye. T checks a finite handful of well-chosen inputs. It is a proxy : the more inputs T covers, the closer it approximates B . This is exactly why the parent says "poor tests ⇒ unsafe refactoring." A sparse sampler can miss the input where you broke something.
See Unit Testing for how these tests are actually written.
The parent's safety rule uses ⟹ . This is not multiplication or an arrow you draw — it's a logic word .
⟹
P ⟹ Q means =="whenever P is true, Q must also be true." == Read it aloud as "if P then Q" or "P leads to Q."
Definition Transformation
f
f is a single refactoring step written as a function: you feed it code, it hands back the rearranged code. f ( code ) means "the code after applying transformation f ."
Picture f as a "tidy-up robot": code goes in messy, comes out reorganised, gears equivalent.
Intuition Why borrow function notation for a code edit?
Because a refactoring genuinely is a machine: input = old code, output = new code. Writing it as f ( code ) lets us reason about it precisely — e.g. we can chain steps f 2 ( f 1 ( code )) , meaning "do step 1, then step 2," each one tiny and test-checked.
A surface hint that structure is decaying , even though behaviour is fine. Not a bug; a symptom . You notice a smell before you understand the rot beneath it.
The figure maps three example smells to the pictures they evoke:
Long Method — one giant box you can't see the top and bottom of at once.
Duplicated Code — the same gear stamped in two places; fix one, forget the other.
Magic Number — a bare literal like 0.0825 with no label saying what it means.
A smell tells you where to point a refactoring f ; it does not force you to act (the Technical Debt you carry might be affordable for now).
These are plain-English concepts the parent leans on. Each links to a fuller vault note.
Definition Supporting concepts
==Technical debt == — the accumulated cost of shortcuts; refactoring pays it down. → Technical Debt
==DRY == ("Don't Repeat Yourself") — each piece of knowledge lives in exactly one place; kills Duplicated Code. → DRY Principle
==Single Responsibility == — one class/function does one job; cures the God Object smell. → Single Responsibility Principle
==Clean names == — identifiers that reveal intent; the Rename refactoring lives here. → Naming Conventions and Clean Code
==Cyclomatic complexity == — a number counting the branching paths through code; high = smelly. → Cyclomatic Complexity
==Design patterns == — named, reusable structure blueprints refactoring often moves toward. → Design Patterns
Behaviour, the visible in-out map
Structure, the hidden inside
Implication if-then arrow
Transformation f, one tiny step
Read top to bottom: you need code before behaviour vs structure ; you need behaviour before tests ; tests plus the if-then arrow plus a transformation give the safety invariant ; smells tell you where to apply the refactorings . Everything funnels into the parent: the Refactoring topic .
Cover each answer, then reveal to self-test your readiness.
What is a function in one sentence? A named box that takes inputs, runs steps, and hands back an output.
What does behaviour (external) mean? The complete mapping from every possible input to the output the outside world sees.
What does structure mean, and can we change it while refactoring? How code is organised inside (names, splits, grouping); yes — structure is the only thing refactoring is allowed to touch.
Two functions have the same behaviour when…? For every possible input they return the same output, no matter how their insides differ.
What does the symbol B ( code ) stand for? The behaviour of that code — its full input→output table.
What is a test, and what is a test suite T ? A test runs the function on a chosen input and checks the output; the suite T is the whole collection of tests.
Why are tests only a proxy for behaviour? They sample a finite set of inputs; behaviour covers all infinite inputs, so tests can miss cases.
Read aloud: P ⟹ Q . "If P is true, then Q must also be true."
What does f ( code ) mean? The code after applying one refactoring transformation f .
What is a code smell — is it a bug? A surface hint of deeper design decay; not a bug, the code may run perfectly.
State the safety invariant in plain words. If tests passed before the change, they still pass after it, and observable behaviour is unchanged.