God Class: How to Spot and Refactor a Class That Does Everything
Every codebase has one: OrderManager, Utils, or AppService, thousands of lines long, imported everywhere, and touched by every pull request. That is a god class, a class that holds too much of the system's logic. It makes changes risky and merges painful. Here is how to recognise one and take it apart without a big-bang rewrite.
Warning signs
- Hundreds or thousands of lines, and dozens of public methods
- Many unrelated dependencies injected into the constructor
- Method groups that never use each other's fields
- A vague name: Manager, Helper, Utils, Service, Processor
- It appears in most pull requests and most merge conflicts
Why it hurts
A class with many responsibilities has many reasons to change, so unrelated features collide in the same file. Tests need large setups because every method shares the same dependencies. New developers cannot tell where code belongs, so the class keeps growing.
Before: one class, four responsibilities
public class OrderManager
{
public decimal CalculateTotal(Order order) { /* discounts, tax */ }
public void Save(Order order) { /* SQL */ }
public void ChargeCard(Order order, Card card) { /* payment gateway */ }
public void SendConfirmationEmail(Order order) { /* SMTP */ }
public void SendShippingSms(Order order) { /* SMS */ }
public Report BuildMonthlyReport(int month) { /* reporting */ }
// ... 60 more methods
}
After: one class per responsibility
public class OrderPricing { public decimal CalculateTotal(Order order) { /* ... */ } }
public class OrderRepository { public Task SaveAsync(Order order) { /* ... */ } }
public class PaymentService { public Task ChargeAsync(Order order, Card card) { /* ... */ } }
public class OrderNotifications { public Task SendConfirmationAsync(Order order) { /* ... */ } }
public class SalesReports { public Report BuildMonthly(int month) { /* ... */ } }
Split it step by step
- Group the methods by what they use and why they change (pricing, storage, messaging...)
- Pick the most independent group and move it into a new class with Extract Class
- Keep the old method as a one-line call to the new class so callers keep working
- Move callers over gradually, then delete the forwarding method
- Repeat for the next group; ship each step as its own small pull request
Keep it from coming back
- Name classes after one responsibility, not "Manager" or "Helper"
- Review constructor parameter counts: many dependencies means many jobs
- Set a size limit in code review or static analysis and look at classes that cross it
Find large classes across a repository
CodeInspector flags large classes in C++ (CPP0007) and Java, together with long methods and too many parameters, so you can see which classes to split first. Scan a repository at https://codeinspector.app with 100 free credits.