Refactoring techniqueSimplifying Method Calls
Add Parameter
Give a method a new parameter when it needs data it cannot reach, migrating callers through a temporary overload or default value.
- Also known as
- Change Function Declaration
Problem
A method needs information it does not have. It reaches for a global, reads a field that only some callers set, or silently assumes a default that is wrong for some of them.
Solution
Add a parameter that carries the needed value and pass it from every caller. Use a default value or an overload to migrate callers safely, then remove the default if every caller should choose explicitly.
Before
function formatInvoiceTotal(invoice: Invoice): string {
// Always formatted for the US, even for EU customers
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: invoice.currency,
}).format(invoice.totalCents / 100);
}
renderPdf({ total: formatInvoiceTotal(invoice) });After
function formatInvoiceTotal(invoice: Invoice, locale: string): string {
return new Intl.NumberFormat(locale, {
style: "currency",
currency: invoice.currency,
}).format(invoice.totalCents / 100);
}
renderPdf({ total: formatInvoiceTotal(invoice, customer.locale) });Why
- The dependency becomes explicit at the call site, so readers and tests can see and control it.
- It avoids hidden coupling to globals or ambient state.
Steps
- Check whether the method can compute the value itself from what it already has. If so, do that instead; see Replace Parameter with Method Call.
- Add the parameter with a default equal to today's behavior (
locale = "en-US"). Run the tests; nothing changes. - Update callers one at a time to pass the real value. Run the tests after each batch.
- When every caller passes the argument, remove the default so new callers must decide. Run the type checker and tests.
- For overridden methods, add the parameter to every override and interface declaration in the same step.
Watch out
- Do not add a parameter if the method already has many. Group related data with Introduce Parameter Object or pass the source object with Preserve Whole Object.
- A boolean parameter that switches the method's behavior is a smell. Prefer two methods; see Replace Parameter with Explicit Methods.
- In JavaScript and TypeScript, adding a positional parameter before existing optional ones silently shifts arguments. Add new parameters at the end, or switch to an options object.
- Leaving a permanent default can hide callers that should have made a choice.
- The inverse technique is Remove Parameter.
Related
- Inverse: Remove Parameter.
- Alternatives when the list grows: Introduce Parameter Object, Preserve Whole Object.
- Can lead to Long Parameter List if overused.
Agent checklist
- The method cannot derive the value from data it already holds.
- The parameter list stays short (about four or fewer), or you used a parameter object.
- Every override and interface declaration got the parameter.
- Temporary defaults were removed once all callers were migrated, unless a default is genuinely correct.
See also
- Remove ParameterDelete a parameter the method body no longer uses, updating every caller and override so the signature states only real dependencies.
- Introduce Parameter ObjectReplace a group of parameters that always travel together with one object type, then move behavior on that group into it.
- Preserve Whole ObjectPass the object itself instead of several values pulled out of it, so the method signature stays stable as needs change.
- Rename MethodChange a method's name to say what it does, using a forwarding alias when callers cannot all be updated at once.
Original writing and examples. Topic coverage follows Refactoring.Guru, which explains this topic with its own illustrations.