Too Many Parameters: How to Refactor Long Parameter Lists

A function with seven positional parameters is easy to call wrongly: swap two strings or two booleans and the code still compiles. Long parameter lists also hint that a function does too much or that related values belong together. Here is how to shorten them without hiding what the function needs.

Video explainer (1:16) · Watch with transcript

How many is too many?

Zero to three parameters is easy to read. Four or five deserves a second look. Beyond that, most linters and analyzers start warning, and call sites become hard to read without an IDE showing parameter names.

Watch especially for several parameters of the same type next to each other, and for boolean flags, which make calls like send(user, true, false) unreadable.

Before: positional arguments

function createUser(
  firstName: string, lastName: string, email: string, phone: string,
  country: string, isAdmin: boolean, sendWelcome: boolean
) { /* ... */ }

createUser('Ana', 'Silva', '[email protected]', '+44...', 'GB', false, true);

Fix 1: a parameter (options) object

type NewUser = {
  firstName: string;
  lastName: string;
  email: string;
  phone?: string;
  country: string;
};

type CreateUserOptions = { isAdmin?: boolean; sendWelcome?: boolean };

function createUser(user: NewUser, { isAdmin = false, sendWelcome = true }: CreateUserOptions = {}) {
  /* ... */
}

createUser({ firstName: 'Ana', lastName: 'Silva', email: '[email protected]', country: 'GB' }, { sendWelcome: true });

Fix 2: group values that travel together

If the same three or four values are passed through several functions (street, city, postcode, country), they are a missing type. Introduce an Address type or record and pass that instead. This is the "Introduce Parameter Object" refactoring.

Fix 3: replace boolean flags with separate functions

A flag that switches between two behaviours usually means two functions. sendInvoice(order, true) is clearer as sendInvoiceByEmail(order) and sendInvoiceByPost(order).

Fix 4: inject dependencies, don't pass them

Loggers, repositories, and clients passed into every call belong in the constructor (or a closure), not the parameter list. What remains are the values that actually change per call.

Find long parameter lists automatically

CodeInspector flags functions with too many parameters in JavaScript (JS0006), Java, and C++ (CPP0003), with the function name and count. Scan a repository at https://codeinspector.app; new accounts get 100 free credits.

Related