God Object
A God Object concentrates too many responsibilities in one class, becoming a coupling hub that resists change and testing. Decompose it by responsibility using SRP, DDD, and dependency injection, extracting cohesive clusters incrementally.
A God Object (also called a God Class or Blob) is a single class, module, or service that has grown to hold a disproportionate share of a system's data and behavior. It orchestrates many unrelated concerns, references most other parts of the system, and is referenced by most of them in turn. Because so much logic lives in one place, it becomes the gravitational center that every change must pass through.
Why It Happens
God Objects rarely appear by design. They accrete. A class starts with a clear purpose, then a developer adds "just one more" method because that is where related data already lives. Over months, convenience wins repeatedly. Deadline pressure discourages extracting new abstractions, since adding to an existing class is faster than designing a new one. Weak module boundaries and the absence of a clear domain model remove any natural stopping point. Utility or Manager/Helper classes are especially prone, because their names invite unlimited scope.
Why It Hurts
The God Object couples everything to everything. A change to one responsibility risks breaking unrelated ones, producing change amplification: small features require edits across a sprawling file. Testing is hard because instantiating the object drags in its entire dependency graph, so unit tests become integration tests. Parallel work stalls as multiple developers contend for the same file, creating constant merge conflicts. Reasoning about correctness is difficult because no one holds the whole object in their head. Performance suffers too, since the class is often loaded and instantiated even when only a sliver is needed.
Warning Signs
- A file thousands of lines long with dozens of methods spanning unrelated topics.
- The class imports or is imported by most of the codebase.
- Method names cover wildly different domains (billing, email, parsing, auth) in one type.
- Every feature branch touches the same file, causing frequent conflicts.
- New engineers are told "that class does everything, be careful."
Better Alternatives
Apply the Single Responsibility Principle: each class should have one reason to change. Decompose by domain concept using Domain-Driven Design, grouping data and behavior into cohesive aggregates and services. Use dependency injection so collaborators are explicit and replaceable, which also makes testing tractable. Favor many small, well-named types over one omniscient one.
How to Refactor Out of It
Refactor incrementally; do not attempt a rewrite. First, characterize behavior with tests at the current public boundary so you can refactor safely. Identify clusters of methods and fields that change together — these are candidate responsibilities. Extract one cluster at a time into a new class, delegating from the God Object so callers stay working. Move state along with the behavior that uses it. As collaborators become explicit, inject them rather than constructing them inline. Repeat until the original class is a thin coordinator or disappears entirely. Track progress by watching the file shrink and test isolation improve.