Return to site

✂️🧩 DIVERGENT CHANGE: WHEN ONE CLASS HAS TOO MANY REASONS TO CHANGE

· code-smell,cleancode
Section image

🔸 TL;DR

A “divergent change” smell happens when a single class/module must be edited for unrelated reasons (new field here, new format there, another endpoint later). It violates SRP, slows delivery, and breeds bugs. Slice responsibilities: extract classes/modules, group by reason-to-change, and add tests to lock behavior. 🚦

🔸 WHAT IT IS

▪️ One class changes for many unrelated reasons (UI tweak today, persistence rule tomorrow, integration detail next week).

▪️ Opposite of shotgun surgery (where one change touches many classes) — here many changes hit one place.

▪️ Symptom of missing boundaries and unclear responsibilities.

🔸 WHY IT HURTS

▪️ Slows you down: every edit navigates a maze of conditionals. 🐢

▪️ Increases risk: unrelated logic collides → regressions. 💥

▪️ Blocks parallel work: teams queue on the same file. ⛔

▪️ Kills readability: “God classes” with mixed concerns. 🌀

🔸 HOW TO SPOT IT

▪️ The same file is always in your PRs for unrelated tasks.

▪️ You frequently add if(feature) or switch(type) in one place.

▪️ The class imports everything (HTTP, DB, JSON, Cache, UI).

▪️ Unit tests feel impossible without heavy mocking.

🔸 EXAMPLE SCENARIO

▪️ OrderService knows about HTTP DTOs, discount rules, tax calculators, inventory checks, and DB mapping.

▪️ Adding a new discount or new channel both require touching OrderService, even though they’re unrelated.

🔸 HOW TO FIX IT (REFACTORING PLAYBOOK)

▪️ Extract Class / Module: split by reason-to-change (e.g., PricingPolicy, InventoryGateway, OrderMapper).

▪️ Introduce Interfaces/Ports: define boundaries (PricingPolicy, InventoryPort), hide details behind adapters.

▪️ Move Functions & Data: relocate logic to the module that owns it (cohesion ↑).

▪️ Replace Conditionals with Polymorphism: handle variations via strategy/factory instead of if/else.

▪️ Add Characterization Tests: freeze current behavior before you cut.

▪️ Create Feature Folders: group code by capability, not by technical layer only.

🔸 PREVENTION GUARDRAILS

▪️ Design with SRP (one reason to change).

▪️ Keep clean boundaries: domain ↔ infrastructure adapters.

▪️ Prefer composition over sprawling services.

▪️ Watch your metrics: file churn, growing method counts, cyclomatic complexity.

▪️ Review check: “Does this edit touch unrelated concerns?”

🔸 TAKEAWAYS

▪️ Divergent change = one class edited for many unrelated reasons.

▪️ It signals missing boundaries and low cohesion.

▪️ Refactor by slicing responsibilities and introducing ports/adapters.

▪️ Polymorphism beats giant conditionals.

▪️ Tests first, then safe, small extractions. ✅

#️⃣

#Refactoring #CleanCode #CodeSmells #SoftwareDesign #SRP #Architecture #DDD #Java #Microservices #Testing #Maintainability #TechDebt #DevEx #BestPractices

Go further with Java certification:

Java👇

Spring👇