# Replace Parameter with Explicit Methods

> Split a method that branches on a flag or enum argument into one clearly named method per value.

- kind: technique
- category: simplifying-method-calls
- aliases: Remove Flag Argument
- canonical: https://aipatterns.dev/refactoring/techniques/replace-parameter-with-explicit-methods
- inspired-by: https://refactoring.guru/replace-parameter-with-explicit-methods

## Problem

A method takes a parameter whose only job is to choose which branch runs. Call sites read like `setStatus(account, true, false)`, and the reader must open the method to learn what `true` means. Each branch has little in common with the others.

## Solution

**Create a separate method for each value of the parameter, move the matching branch into it, and have callers call the explicit method.**

## Before

```ts
function exportReport(report: Report, format: "csv" | "pdf"): Buffer {
  if (format === "csv") {
    const header = report.columns.join(",");
    const rows = report.rows.map((r) => r.map(csvEscape).join(","));
    return Buffer.from([header, ...rows].join("\n"));
  } else {
    const doc = new PdfDocument({ size: "A4" });
    doc.table(report.columns, report.rows);
    return doc.render();
  }
}

const file = exportReport(monthly, "pdf");
```

## After

```ts
function exportCsv(report: Report): Buffer {
  const header = report.columns.join(",");
  const rows = report.rows.map((r) => r.map(csvEscape).join(","));
  return Buffer.from([header, ...rows].join("\n"));
}

function exportPdf(report: Report): Buffer {
  const doc = new PdfDocument({ size: "A4" });
  doc.table(report.columns, report.rows);
  return doc.render();
}

const file = exportPdf(monthly);
```

## Why

- Each call states what it does without a flag to decode.
- Each method has one job and only the dependencies that job needs.
- The type checker catches a missing case at compile time, rather than a runtime `else`.

## Steps

1. Confirm callers pass the parameter as a literal. If the value comes from data at runtime, stop; you would only move the branch to every caller.
2. Create one explicit method per value, with the body of its branch. Run the tests.
3. Make the original method delegate to the explicit methods. Run the tests.
4. Replace each call that passes a literal with a call to the matching explicit method. Run the tests.
5. Delete the original method when no callers remain.

## Watch out

- Do not split when the value is decided at runtime (from a user setting, request header or database). Keep the dispatching method, or move the choice to a lookup map. That map is often the boundary where callers need a single entry point.
- Do not split when the branches share most of their code and differ by a value. That is the case for [Parameterize Method](https://aipatterns.dev/refactoring/techniques/parameterize-method.md), the inverse technique.
- Many values (ten export formats) make many methods. Consider [Replace Conditional with Polymorphism](https://aipatterns.dev/refactoring/techniques/replace-conditional-with-polymorphism.md) with one exporter object per format.

## Related

- Inverse: [Parameterize Method](https://aipatterns.dev/refactoring/techniques/parameterize-method.md).
- Treats [Switch Statements](https://aipatterns.dev/refactoring/smells/switch-statements.md) driven by flag arguments and shortens [Long Method](https://aipatterns.dev/refactoring/smells/long-method.md).
- Escalate to [Replace Conditional with Polymorphism](https://aipatterns.dev/refactoring/techniques/replace-conditional-with-polymorphism.md) as cases grow.

## Agent checklist

- [ ] Most callers pass the parameter as a literal.
- [ ] The branches do different work, not the same work with different values.
- [ ] Any caller with a runtime value still has a single dispatch point.
- [ ] Boolean flag arguments were the first candidates.
