Move Statements to Callers
Before you begin: Functions, callers, and responsibility boundaries.
Move Statements to Callers moves work out of a shared function when the work belongs to the callers instead. Some duplication may reappear deliberately: two callers are now free to make different decisions instead of being forced to share an unrelated policy. 1
Original version: cleaning a name also chooses its punctuation
A name helper trims whitespace and adds an exclamation mark. Both a chat greeting and a badge use it. Inputs are non-null strings.
public static class Names
{
private static string Prepare(string name) { return name.Trim() + "!"; }
public static string Chat(string name) { return Prepare(name); }
public static string Badge(string name) { return Prepare(name); }
}def _prepare(name):
return name.strip() + "!"
def chat_name(name):
return _prepare(name)
def badge_name(name):
return _prepare(name)Trimming is a shared data-cleaning rule. Punctuation is a presentation choice that the chat and badge may need to change independently.
Refactored version: callers own the punctuation
public static class Names
{
private static string Prepare(string name) { return name.Trim(); }
public static string Chat(string name) { return Prepare(name) + "!"; }
public static string Badge(string name) { return Prepare(name) + "!"; }
}def _prepare(name):
return name.strip()
def chat_name(name):
return _prepare(name) + "!"
def badge_name(name):
return _prepare(name) + "!"Both callers still return Mira! for " Mira ". This first step changes ownership, not output. A later requirement can remove punctuation from badges by changing only the badge function; that would be the separate behavior change the refactoring prepares for.
Duplication can be more honest than the wrong shared rule
The exclamation mark now appears twice. That is acceptable if each occurrence belongs to an independently changing presentation decision. Keeping one copy solely to satisfy a literal “never repeat text” rule would couple unrelated requirements.
Before moving work, inspect all callers and preserve its execution order. A database write or authorization check should not be moved outward casually: callers might omit it, duplicate it, or perform it too late.
Move only the caller-specific part. The shared cleaning function remains because whitespace normalization is still one rule. Inlining the entire helper would be a different decision and could reintroduce duplication that genuinely should stay synchronized.