Rule
Use named arguments for clarity
Named arguments make code self-documenting
and prevent parameter order mistakes.
Use named arguments when functions have more
than 2-3 parameters or boolean flags.
Supported languages: Python, PHPIntroduction
Functions with multiple parameters become unclear when you see the call site. Reading sendEmail('user@example.com', true, false, 30) requires looking up the function signature to understand what true, false, and 30 mean. Named arguments solve this by making each parameter's purpose explicit at the call site. They also prevent bugs from parameter reordering when function signatures change.
Why it matters
Code maintainability: Named arguments document intent at the call site without requiring constant reference checking. When you see sendEmail(to: $email, retry: true, async: false, timeout: 30), you understand exactly what each value controls. This eliminates confusion during code review and makes debugging faster since you don't need to mentally map positional arguments to parameter names.
Security implications: Parameter order mistakes in security-critical functions can create vulnerabilities. Swapping the $username and $password parameters, or accidentally passing the plaintext password where the hashed password belongs, fails silently with positional arguments. Named arguments force you to explicitly state which value goes where, preventing these dangerous mistakes.
Refactoring safety: Adding optional parameters to existing functions breaks all call sites with positional arguments unless you append them at the end. Named arguments let you add, reorder, or change parameters without breaking existing code, as long as parameter names stay consistent. This makes APIs more stable and evolution less risky.
Code examples
❌ Non-compliant:
function createUser($email, $password, $role, $verified, $sendEmail, $retryCount) {
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
$user = User::create([
'email' => $email,
'password' => $hashedPassword,
'role' => $role,
'verified' => $verified
]);
if ($sendEmail) {
sendWelcomeEmail($user->email, $retryCount);
}
return $user;
}
// Unclear what each parameter means
createUser('user@example.com', 'secret123', 'admin', true, false, 3);
Why it's wrong: The call site provides no context for what true, false, and 3 mean, requiring constant reference to the function signature. Swapping $role and $password or $verified and $sendEmail would fail silently, potentially creating security issues.
✅ Compliant:
function createUser(
string $email,
string $password,
string $role = 'user',
bool $verified = false,
bool $sendEmail = true,
int $retryCount = 3
) {
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
$user = User::create([
'email' => $email,
'password' => $hashedPassword,
'role' => $role,
'verified' => $verified
]);
if ($sendEmail) {
sendWelcomeEmail($user->email, $retryCount);
}
return $user;
}
// Self-documenting call site
createUser(
email: 'user@example.com',
password: 'secret123',
role: 'admin',
verified: true,
sendEmail: false,
retryCount: 3
);
Why this matters: Each parameter's purpose is explicit at the call site, making the code self-documenting. Parameter order mistakes are impossible since you explicitly name each argument, and adding new optional parameters won't break existing code.
Conclusion
Use named arguments for functions with more than 2-3 parameters, boolean flags, or similar types appearing consecutively. The slight verbosity at the call site pays for itself in clarity, safety, and maintainability. Reserve positional arguments for simple functions where parameter order is obvious and unlikely to change.
.avif)
