Code Smell | Shotgun surgery

Code Smell | Shotgun surgery

This code smell can be detected if making a change have to replicate this change in different parts of our code.

ยท

2 min read

Hello, today we are back with the code smells refactoring series and in this case we are going to talk about code smell called Shotgun Surgery, this smell can be detected if making a change have to replicate this change in different parts of our code


Cause

A single responsibility has been split up among a large number of sites. This can happen after the overzealous application of Divergent Change


Example

We can see that the minimum balance check is being duplicated in both methods

class Account {
  private amount: number;

  constructor(amount: number) {
    this.amount = amount;

    //...
  }

 debit(debitAmount: number): void {
    if (this.amount <= 1000) {
      throw new Error('Minimum balance should be over 1000');
    }

    //...
  }

  transfer(from: Account, to: Account, transferAmount: number): void {
    if (from.amount <= 1000) {
      throw new Error('Minimum balance should be over 1000');
    }

    //...
  }
}

Solution

Extract minimum balance checks to method to be able to reuse it in the different methods of the class

class Account {
  private amount: number;

  constructor(amount: number) {
    this.amount = amount;

    //...
  }

  assertMinimumBalance(amount: number): void {
    const MINIMUM_AMOUNT = 1000;

    if (amount <= MINIMUM_AMOUNT) {
      throw new Error(`Minimum balance should be over ${MINIMUM_AMOUNT}`);
    }
  }

  debit(debitAmount: number): void {
    this.assertMinimumBalance(this.amount);

    //...
  }

  transfer(from: Account, to: Account, transferAmount: number): void {
    this.assertMinimumBalance(from.amount);

    //...
  }
}

Bonus track

Shotgun surgery in CSS? ๐Ÿค”

Yes, see the next example:

.button-primary {
  background-color: #ec407a;
}

.button-secondary {
  background-color: #b4004e;
}

.navbar-primary {
  background-color: #ec407a;
}

.navbar-secondary {
  background-color: #b4004e;
}

If now they ask us to modify the primary color for another, what is the solution? Search globally in all our CSS and replace it? NOOO!! โ›”๏ธ

The solution is use CSS variables:

We can declare variables in CSS globally with the pseudo-class :root and thus use them in any part of our CSS, in this way we centralize the possible changes in only the variables, thus avoiding having to replace each color value


:root {
  --primary-background: #ec407a;
  --secondary-background: #b4004e;
}

.button-primary {
  background-color: var(--primary-background);
}

.button-secondary {
  background-color: var(--secondary-background);
}

.navbar-primary {
  background-color: var(--primary-background);
}

.navbar-secondary {
  background-color: var(--secondary-background);
}

Thanks for reading me ๐Ÿ˜Š

ย