# Parameterize Method

> Merge several methods that do the same thing with different literal values into one method that takes the value as a parameter.

- kind: technique
- category: simplifying-method-calls
- aliases: Parameterize Function
- canonical: https://aipatterns.dev/refactoring/techniques/parameterize-method
- inspired-by: https://refactoring.guru/parameterize-method

## Problem

You have several methods with almost identical bodies. They differ only in a number, a string or a threshold. A bug fix in one is easily missed in the others, and adding a new variant means copying a method again.

## Solution

**Replace the family of methods with one method that takes the differing value as a parameter.**

## Before

```ts
class RetentionReport {
  activeLast7Days(events: UsageEvent[], now: Date): number {
    const since = now.getTime() - 7 * DAY_MS;
    return new Set(events.filter((e) => e.at.getTime() >= since).map((e) => e.userId)).size;
  }

  activeLast30Days(events: UsageEvent[], now: Date): number {
    const since = now.getTime() - 30 * DAY_MS;
    return new Set(events.filter((e) => e.at.getTime() >= since).map((e) => e.userId)).size;
  }

  activeLast90Days(events: UsageEvent[], now: Date): number {
    const since = now.getTime() - 90 * DAY_MS;
    return new Set(events.filter((e) => e.at.getTime() > since).map((e) => e.userId)).size;
  }
}
```

## After

```ts
class RetentionReport {
  activeUsers(events: UsageEvent[], now: Date, windowDays: number): number {
    const since = now.getTime() - windowDays * DAY_MS;
    const recent = events.filter((e) => e.at.getTime() >= since);
    return new Set(recent.map((e) => e.userId)).size;
  }
}

report.activeUsers(events, now, 30);
```

## Why

- One body to read, test and fix.
- New variants (14 days, 365 days) need no new code.
- Differences that were accidental become visible. The 90-day version used `>` instead of `>=`.

## Steps

1. Line up the methods and list every difference between their bodies. Each difference should be a value, not a different algorithm.
2. Resolve accidental differences first. Here, decide whether the boundary is inclusive, and fix the odd method out with a test that pins the chosen behavior.
3. Pick one method, add a parameter for the varying value, and replace the literal with it. Run the tests.
4. Change each sibling method to call the parameterized method with its literal. Run the tests.
5. Move callers to the parameterized method and delete the siblings, or keep them as named shortcuts if they read better at call sites.

## Watch out

- Do not merge methods whose bodies differ in logic, not only values. The resulting method would need flags and branches.
- If callers almost always pass one of a few fixed values, named methods can be clearer than a magic number. Keep thin wrappers like `activeLast30Days()` that delegate.
- Validate the new parameter's range if the old literals were implicitly safe (no negative window, no zero divisor).
- The inverse technique is [Replace Parameter with Explicit Methods](https://aipatterns.dev/refactoring/techniques/replace-parameter-with-explicit-methods.md).

## Related

- Fixes [Duplicate Code](https://aipatterns.dev/refactoring/smells/duplicate-code.md).
- Inverse: [Replace Parameter with Explicit Methods](https://aipatterns.dev/refactoring/techniques/replace-parameter-with-explicit-methods.md).
- Uses [Add Parameter](https://aipatterns.dev/refactoring/techniques/add-parameter.md).

## Agent checklist

- [ ] The merged methods differed only in values, not in control flow.
- [ ] Accidental differences between copies were resolved deliberately, with a test.
- [ ] The parameter has a clear name and unit (`windowDays`, not `n`).
- [ ] Invalid values for the new parameter are rejected or impossible.
