Skip to content
aipatterns.dev

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

TypeScript
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

TypeScript
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

  1. 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.
  2. Add the parameter with a default equal to today's behavior (locale = "en-US"). Run the tests; nothing changes.
  3. Update callers one at a time to pass the real value. Run the tests after each batch.
  4. When every caller passes the argument, remove the default so new callers must decide. Run the type checker and tests.
  5. 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.

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

Original writing and examples. Topic coverage follows Refactoring.Guru, which explains this topic with its own illustrations.