Shotgun Surgery

One change requires edits in many different classes.

“Every time you make a kind of change, you have to make a lot of little changes to a lot of different classes.” – Fowler & Beck

The opposite of Divergent Change.

Signs of Use (Symptoms)

  • Adding a new field requires editing 10+ files.
  • “I changed X, but forgot to update Y, Z, W…”.

Why it is bad (Consequences)

  • Easy to miss changes: Bugs due to incomplete updates.
  • High effort: Small feature = Many files touched.

Why it happens (Root Cause)

A single concept is scattered across many places instead of being centralized.

When it might be okay (Exceptions)

  • Cross-cutting concerns might look like shotgun surgery but be intentional (though AOP is better).

Explanation

Problem

To add a new “User Role”, you must edit User.ts, UserForm.tsx, user_permissions.sql, RoleConstants.java, RoleDropdown.vue

The Flaw

The concept of “Role” is not encapsulated. It’s scattered.

Real world analogy

Changing the company logo. You must update the website, business cards, letterheads, signage manually. A centralized “Brand Guidelines” document would help.

Refactoring Solution

  • Move Method / Move Field: Centralize the scattered logic into one class.
  • Inline Class: If the scattered pieces are tiny.

Pros and Cons (of the Antipattern)

Pros (Why people do it) Cons (The price you pay)
  • None
  • High change effort
  • Easy to forget one place
  • Comparison

    • Related Antipatterns: Divergent Change (opposite).
    • Related Principles: Violates DRY (concept is repeated).

    Code example

    Typescript

    Bad (The Antipattern)

    Good (The Fix)