Fragile Code
- Anand Nerurkar
- 1 day ago
- 3 min read
🧩 Fragile Code
👉 Fragile code is code that breaks easily when you change something, even if the change seems small or unrelated.
It “works” today, but any modification (bug fix, new feature, refactor) causes unexpected side effects elsewhere.
🔎 Characteristics of Fragile Code
Tightly coupled → Many classes/modules depend on each other.
Hidden dependencies → Changing one line impacts distant parts of the system.
Low cohesion → A single module/class does too many things.
Poor tests → Little or no unit test coverage to catch regressions.
Copy-paste logic → Same code repeated in multiple places → fixing in one breaks another.
Implicit assumptions → Business rules hidden in complex conditions or magic numbers.
⚠️ Why Fragile Code is Bad
Slows down development → fear of breaking something.
Introduces regression bugs.
High maintenance cost.
Blocks innovation → “We can’t touch this code, it’s too risky.”
Reduces developer confidence.
🏦 Example: Digital Lending (Fragile Code)
public class LoanProcessor {
public String processLoan(Application app) {
// Age and salary validations mixed with credit rules
if (app.getAge() < 18) return "Rejected: Underage";
// Hard-coded business rule
if (app.getCreditScore() < 650) {
if (app.getSalary() > 50000) {
return "Manual Review"; // assumption: higher salary compensates score
} else {
return "Rejected: Low Score";
}
}
// Inline DB call
Database.save(app);
// Inline notification
EmailService.send(app.getEmail(), "Approved");
return "Approved";
}
}
🔎 Why is this fragile?
If you change the credit score threshold, you risk breaking salary-based logic.
If DB schema changes, this method breaks because it does DB calls directly.
If notification service changes, loan processing breaks too.
No tests → developers are scared to touch it.
✅ Refactored (More Resilient)
public class LoanProcessor {
private final LoanValidator validator;
private final LoanRepository repo;
private final NotificationService notifier;
public LoanProcessor(LoanValidator validator, LoanRepository repo, NotificationService notifier) {
this.validator = validator;
this.repo = repo;
this.notifier = notifier;
}
public String processLoan(Application app) {
validator.validate(app);
String status = LoanRulesEngine.evaluate(app);
repo.save(app, status);
notifier.notify(app.getEmail(), status);
return status;
}
}
Each piece has clear responsibility.
Easy to test each component in isolation.
Small changes in one place don’t cascade.
🧹 How to Avoid Fragile Code
Apply SOLID principles → esp. Single Responsibility & Dependency Inversion.
Write automated tests → unit + integration.
Use loose coupling → interfaces, dependency injection.
Refactor regularly → don’t let messy code rot.
Encapsulate business rules → use rule engines or services, not hard-coded logic.
Code reviews → catch risky design early.
✅ Quick rule:
Spaghetti code → messy and hard to read.
Dead code → unused and safe to delete.
Fragile code → risky because changing anything breaks everything.
Here’s a crisp side-by-side comparison table of Dead Code vs Spaghetti Code vs Fragile Code — super handy for interviews, architecture reviews, or documentation.
🧩 Code Smell Comparison
Aspect | Dead Code | Spaghetti Code | Fragile Code |
Definition | Code that exists but is never used/executed. | Messy, tangled, unstructured code with no clear separation of concerns. | Code that breaks easily when modified due to tight coupling and hidden dependencies. |
Impact | Wastes space, confuses developers, increases clutter. | Hard to read, extend, or debug → slows delivery. | High risk of regressions → small changes cause big unintended effects. |
Symptoms | - Unused variables/methods - Unreachable code - Commented-out code | - Long functions (>200 lines) - Nested if/else - Mix of DB, business, UI logic in one place | - Tightly coupled modules - Hidden dependencies - Hard-coded rules - No tests |
When It Happens | - Legacy features removed - “Future use” code that’s never used - Leftovers from refactor | - Quick fixes piled up - Lack of design/architecture - No modularization | - Poorly isolated concerns - No automated tests - Frequent business rule changes jammed into code |
Detection | Static analysis (SonarQube, PMD, ESLint), compiler warnings, coverage reports | Harder to auto-detect → found by code smells (complexity, long methods, high coupling) | Found during frequent regressions, change impact analysis, high bug rate |
Fix | Delete unused code (Git keeps history), or mark @Deprecated | Refactor into smaller, cohesive modules, apply SOLID, introduce layers/patterns | Decouple modules, add tests, encapsulate rules, use dependency injection |
Analogy | 🪵 Dead branch on a tree → contributes nothing | 🍝 Tangled spaghetti → hard to separate strands | 🏗️ House of cards → one small push, everything collapses |
✅ One-liner memory hook:
Dead Code = Unused.
Spaghetti Code = Used but messy.
Fragile Code = Used, but breaks when touched.
Comments