IMPLEMENTATION QUALITY / OBJECT DESIGN BRIEF

Refactoring code smells

Code smells are surface symptoms of deeper design problems: long methods, large classes, duplicated logic, long parameter lists, feature envy (a method more interested in another class's data), switch statements on type, primitive obsession, and shotgun surgery (one change requires edits in many places).

IntermediatePhase 07 / Topic 6 of 8ResponsibilitiesCollaborationsExtensibility
01

Overview

Code smells are surface symptoms of deeper design problems: long methods, large classes, duplicated logic, long parameter lists, feature envy (a method more interested in another class's data), switch statements on type, primitive obsession, and shotgun surgery (one change requires edits in many places). Refactoring improves structure without changing behavior, in small, test-backed steps.

Knowing the smells and their standard refactorings (Extract Method, Extract Class, Move Method, Replace Conditional with Polymorphism, Introduce Parameter Object, Replace Primitive with Value Object) lets you both write better LLD solutions and discuss how you would improve an existing design, a frequent interview follow-up.

Reorganizing a messy garage

You do not throw everything out; you move items into labeled shelves one box at a time, checking you can still find things. Afterward, finding and adding tools is much easier.

02

When to use it

  • Before adding a feature to messy code.
  • Code reviews and interview follow-ups ('what would you improve?').
  • When a change touches many unrelated places.
03

Where it shows up in interviews

Design critique

Recognize it when: 'here is some code, how would you improve it?'

  • Refactor a god class OrderManager
  • Refactor a switch-based pricing function
04

Where it is used in real software

Martin Fowler's Refactoring

The catalog of smells and refactorings used across the industry.

IDE automated refactorings

IntelliJ, VS Code, and Rider automate extract method, rename, and move safely.

Static analysis

SonarQube and ESLint flag complexity, duplication, and long methods.

05

Key terms

Refactoring
Behavior-preserving structural change.
Long method / large class
Too much in one place.
Feature envy
A method using another object's data more than its own.
Shotgun surgery
One change requires many small edits across classes.
Primitive obsession
Primitives instead of small domain types.
06

How it works, step by step

  1. 1
    Get tests around the behavior

    Characterization tests if none exist.

  2. 2
    Identify the smell

    Name it precisely.

  3. 3
    Apply the matching refactoring

    Small step, run tests.

  4. 4
    Repeat

    Commit frequently.

  5. 5
    Stop when the change you need is easy

    Refactor with purpose.

07

Smells and fixes

Common smells in LLD code

Step 1 / 6
SmellSymptomRefactoring
Long method200-line checkout()Extract Method into named steps
Large classOrderManager does pricing, email, DBExtract Class (SRP)
Switch on typeif vehicle.type == TRUCK ...Replace Conditional with Polymorphism
Long parameter listbook(a, b, c, d, e, f)Introduce Parameter Object
Feature envyInvoice computes from customer fieldsMove Method to Customer
Primitive obsessiondouble price, String emailReplace Primitive with Value Object

NOWSmell: Long method | Symptom: 200-line checkout() | Refactoring: Extract Method into named steps

Each smell has a well-known, low-risk fix.

08

Implementation

// Smells: long method, switch on type, primitives, mixed concernsfunction checkout(items: any[], type: string, email: string, coupon: string) {  let total = 0;  for (const i of items) total += i.price * i.qty;  if (type === "gold") total *= 0.8;  else if (type === "silver") total *= 0.9;  if (coupon === "SAVE10") total -= 10;  if (total < 0) total = 0;  db.save({ items, total });  mailer.send(email, "Thanks! Total " + total.toFixed(2));  return total;}
09

Complexity and performance

Refactoring stepMinutes each

Small and safe.

RiskLow with tests

High without.

10

Trade-offs

Refactor now vs later

Refactoring before a change makes the change easier; refactoring code nobody touches has low value.

Big-bang rewrites

Rewrites are risky; incremental refactoring keeps the system working.

11

Variants and related techniques

Strangler fig

Incrementally replace a legacy module behind an interface.

Preparatory refactoring

'Make the change easy, then make the easy change.'

12

Common mistakes

  • Refactoring without tests.

    Fix: Add characterization tests first.

  • Mixing refactoring with behavior changes.

    Fix: Separate commits: structure first, then feature.

13

Interview questions

What refactoring would you apply to a large switch on object type?

Replace Conditional with Polymorphism: introduce an interface, move each branch into a class implementing it, and let callers call the method without checking types.

What is shotgun surgery and how do you fix it?

When one logical change requires edits in many classes. Fix by moving the related logic into one place (Move Method/Field, Extract Class) so the concept has a single home.

14

Practice problems

ProblemDifficultyWhat it trains
Refactor a 150-line OrderManagerMediumExtract Class and Method.
Replace a vehicle-type switch with polymorphismEasyConditional to polymorphism.