Code Simplification
Simplifies code for clarity. Use when refactoring code for clarity without changing behavior.
Simplifies code for clarity. Use when refactoring code for clarity without changing behavior.
Simplify code by reducing complexity while preserving exact behavior. The goal is code that is easier to read, understand, modify, and debug.
Don't change what the code does — only how it expresses it.
ASK BEFORE EVERY CHANGE:
→ Does this produce the same output for every input?
→ Does this maintain the same error behavior?
→ Does this preserve the same side effects and ordering?
→ Do all existing tests still pass without modification?
Simplification means making code more consistent with the codebase, not imposing external preferences.
// UNCLEAR: Dense ternary chain
const label = isNew ? 'New' : isUpdated ? 'Updated' : isArchived ? 'Archived' : 'Active';
// CLEAR: Readable mapping
function getStatusLabel(item: Item): string {
if (item.isNew) return 'New';
if (item.isUpdated) return 'Updated';
if (item.isArchived) return 'Archived';
return 'Active';
}
Watch for over-simplification traps:
Default to simplifying recently modified code. Avoid drive-by refactors of unrelated code.
Before changing anything, understand why it exists:
BEFORE SIMPLIFYING, ANSWER:
- What is this code's responsibility?
- What calls it? What does it call?
- What are the edge cases and error paths?
- Are there tests that define the expected behavior?
- Why might it have been written this way?
Structural complexity:
| Pattern | Signal | Simplification |
|---------|--------|----------------|
| Deep nesting (3+ levels) | Hard to follow control flow | Extract into guard clauses |
| Long functions (50+ lines) | Multiple responsibilities | Split into focused functions |
| Nested ternaries | Requires mental stack | Replace with if/else chains |
| Boolean parameter flags | doThing(true, false, true) | Replace with options objects |
| Repeated conditionals | Same if check in multiple places | Extract to predicate function |
Naming and readability:
| Pattern | Signal | Simplification |
|---------|--------|----------------|
| Generic names | data, result, temp | Rename to describe content |
| Misleading names | Function named get that mutates | Rename to reflect behavior |
| Comments explaining "what" | // increment counter | Delete the comment |
| Comments explaining "why" | // Retry because API is flaky | Keep these — they carry intent |
Redundancy:
| Pattern | Signal | Simplification | |---------|--------|----------------| | Duplicated logic | Same 5+ lines in multiple places | Extract to shared function | | Dead code | Unreachable branches, unused variables | Remove | | Unnecessary abstractions | Wrapper that adds no value | Inline the wrapper | | Over-engineered patterns | Factory-for-a-factory | Replace with simple approach |
Make one simplification at a time. Run tests after each change.
COMPARE BEFORE AND AFTER:
- Is the simplified version genuinely easier to understand?
- Did you introduce any new patterns inconsistent with the codebase?
- Is the diff clean and reviewable?
- Would a teammate approve this change?
// SIMPLIFY: Unnecessary async wrapper
// Before
async function getUser(id: string): Promise<User> {
return await userService.findById(id);
}
// After
function getUser(id: string): Promise<User> {
return userService.findById(id);
}
// SIMPLIFY: Verbose conditional assignment
// Before
let displayName: string;
if (user.nickname) {
displayName = user.nickname;
} else {
displayName = user.fullName;
}
// After
const displayName = user.nickname || user.fullName;
// SIMPLIFY: Manual array building
// Before
const activeUsers: User[] = [];
for (const user of users) {
if (user.isActive) {
activeUsers.push(user);
}
}
// After
const activeUsers = users.filter((user) => user.isActive);
After completing a simplification pass: